diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e86e38..79a986a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -158,7 +158,7 @@ jobs: id: execute-msys2 uses: ./ with: - debug: true + debug: false process-paths: msys2 - name: Dump outputs (except "all") diff --git a/dist/index.js b/dist/index.js index 509a725..df6121b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -109,6 +109,9 @@ function issueCommand(command, properties, message) { const cmd = new Command(command, properties, message); process.stdout.write(cmd.toString() + os.EOL); } +function issue(name, message = '') { + issueCommand(name, {}, message); +} const CMD_STRING = '::'; class Command { constructor(command, properties, message) { @@ -28822,7 +28825,7 @@ function setOutput(name, value) { */ function setFailed(message) { process.exitCode = ExitCode.Failure; - error$1(message); + error(message); } //----------------------------------------------------------------------- // Logging Commands @@ -28845,7 +28848,7 @@ function debug$1(message) { * @param message error issue message. Errors will be converted to string via toString() * @param properties optional properties to add to the annotation. */ -function error$1(message, properties = {}) { +function error(message, properties = {}) { issueCommand('error', toCommandProperties(properties), message instanceof Error ? message.toString() : message); } /** @@ -28863,6 +28866,22 @@ function warning$1(message, properties = {}) { function info(message) { process.stdout.write(message + os.EOL); } +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + issue('group', name); +} +/** + * End an output group. + */ +function endGroup() { + issue('endgroup'); +} let enableDebug = false; function setDebug(value) { @@ -28870,9 +28889,7 @@ function setDebug(value) { } function debug(message) { if (enableDebug) { - String(message) - .split(/\r?\n/) - .forEach((line) => info(`[DEBUG] ${line}`)); + info(message); } else if (isDebug()) { debug$1(message); @@ -28881,8 +28898,18 @@ function debug(message) { function warning(message) { warning$1(message); } -function error(message) { - error$1(message); +function startDebugGroup(name) { + if (enableDebug) { + startGroup(name); + } + else if (isDebug()) { + debug$1(`--- ${name} ---`); + } +} +function endDebugGroup() { + if (enableDebug) { + endGroup(); + } } var OnNonWindowsAction; @@ -29009,34 +29036,36 @@ async function findProgram(program) { return found; } -let vsWherePath; async function findVsWhere() { - if (vsWherePath !== undefined) { - if (vsWherePath instanceof Error) { - throw vsWherePath; - } - return vsWherePath; - } + let vsWherePath; + startDebugGroup("Finding vswhere.exe"); try { vsWherePath = await findProgram("vswhere.exe"); - return vsWherePath; } catch (err) { debug(`Failed to find vswhere.exe with where.exe (${err instanceof Error ? err.message : err}), let's try with some known paths`); } + if (vsWherePath) { + debug(`Found vswhere.exe at ${vsWherePath}`); + endDebugGroup(); + return vsWherePath; + } const programsPath = path$1.join(process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)"); const p = path$1.join(programsPath, "Microsoft Visual Studio", "Installer", "vswhere.exe"); try { vsWherePath = fs$1.realpathSync.native(p); - debug(`vswhere.exe at expected location ${vsWherePath}`); - return vsWherePath; } catch { - vsWherePath = new Error("vswhere.exe not found at expected locations: " + p); - error(vsWherePath); - throw vsWherePath; + debug(`vswhere.exe not found at expected location ${p}`); } + if (vsWherePath) { + debug(`Found vswhere.exe at ${vsWherePath}`); + endDebugGroup(); + return vsWherePath; + } + endDebugGroup(); + throw new Error("Unable to find vswhere.exe"); } function compareVersionNumbers(a, b) { @@ -29107,7 +29136,7 @@ function getVSWhereVersionArguments(version) { } return ["-version", `${version.minVersion},${version.maxVersion}`]; } -async function findVisualStudioInstallationPathWithVSWhere(version) { +async function findVisualStudioInstallationPathWithVSWhere(version, vsWherePath) { const args = [ "-products", "*", @@ -29117,7 +29146,6 @@ async function findVisualStudioInstallationPathWithVSWhere(version) { "-property", "installationPath", ]; - const vsWherePath = await findVsWhere(); const result = await run$1(`"${vsWherePath}"`, args, { throwIfNonZeroExitCode: true, }); @@ -29167,19 +29195,33 @@ function findVisualStudioInstallationPathDefaults(version) { throw new Error(`Unable to find Visual Studio ${version.year} installation`); } async function findVisualStudioInstallationPath(version) { + let vsWherePath; try { - return await findVisualStudioInstallationPathWithVSWhere(version); + vsWherePath = await findVsWhere(); } - catch (err) { - debug(`Failed to find Visual Studio installation with vswhere.exe: ${err instanceof Error ? err.message : err}`); + catch { } + startDebugGroup("Finding Visual Studio"); try { - return findVisualStudioInstallationPathDefaults(version); + if (vsWherePath) { + try { + return await findVisualStudioInstallationPathWithVSWhere(version, vsWherePath); + } + catch (err) { + debug(`Failed to find Visual Studio installation with vswhere.exe: ${err instanceof Error ? err.message : err}`); + } + } + try { + return findVisualStudioInstallationPathDefaults(version); + } + catch (err) { + debug(`Failed to find Visual Studio installation with default paths: ${err instanceof Error ? err.message : err}`); + } + throw new Error(`Unable to find Visual Studio installation for version ${version === "latest" ? version : version.year}`); } - catch (err) { - debug(`Failed to find Visual Studio installation with default paths: ${err instanceof Error ? err.message : err}`); + finally { + endDebugGroup(); } - throw new Error(`Unable to find Visual Studio installation for version ${version === "latest" ? version : version.year}`); } async function findVcvarsallByVisualStudioVersion(version) { @@ -29187,13 +29229,19 @@ async function findVcvarsallByVisualStudioVersion(version) { return findVcvarsallByVisualStudioPath(vsPath); } function findVcvarsallByVisualStudioPath(visualStudioPath) { - const tryPath = path$1.join(visualStudioPath, "VC", "Auxiliary", "Build", "vcvarsall.bat"); - if (fs$1.statSync(tryPath).isFile()) { - const realPath = fs$1.realpathSync.native(tryPath); - debug(`vcvarsall.bat found at: ${realPath}`); - return realPath; + startDebugGroup("Finding vcvarsall.bat"); + try { + const tryPath = path$1.join(visualStudioPath, "VC", "Auxiliary", "Build", "vcvarsall.bat"); + if (fs$1.statSync(tryPath).isFile()) { + const realPath = fs$1.realpathSync.native(tryPath); + debug(`vcvarsall.bat found at: ${realPath}`); + return realPath; + } + throw new Error(`vcvarsall.bat not found in Visual Studio installation at: ${visualStudioPath}`); + } + finally { + endDebugGroup(); } - throw new Error(`vcvarsall.bat not found in Visual Studio installation at: ${visualStudioPath}`); } /** @@ -29430,86 +29478,97 @@ function parseSetOutput(setOutput) { return result; } function computeEnvDelta(before, after) { - const delta = new CaseInsensitiveStringMap(); - for (const [key, afterValue] of after) { - const beforeValue = before.get(key); - if (beforeValue === undefined) { - debug(`- new: ${key}=${afterValue}`); - delta.set(key, afterValue); - continue; - } - if (afterValue === beforeValue) { - debug(`- unchanged: ${key}=${afterValue}`); - continue; - } - if (!isMultiPathEnvVar(key)) { - debug(`- changed: ${key}=${afterValue} (was ${beforeValue})`); - delta.set(key, afterValue); - continue; - } - debug(`- computing delta for path-list: ${key}`); - const beforeValues = beforeValue.split(';').map(s => s.trim()).filter(s => s.length > 0); - const afterValues = afterValue.split(';').map(s => s.trim()).filter(s => s.length > 0); - const newAfterValues = afterValues.filter(av => { - if (beforeValues.some(bv => pathsAreSame(bv, av))) { - debug(` - path same as before, skipping: ${av}`); - return false; + startDebugGroup(`Computing environment variable delta`); + try { + const delta = new CaseInsensitiveStringMap(); + for (const [key, afterValue] of after) { + const beforeValue = before.get(key); + if (beforeValue === undefined) { + debug(`new: ${key}=${afterValue}`); + delta.set(key, afterValue); + continue; + } + if (afterValue === beforeValue) { + debug(`unchanged: ${key}=${afterValue}`); + continue; + } + if (!isMultiPathEnvVar(key)) { + debug(`changed: ${key}=${afterValue} (was ${beforeValue})`); + delta.set(key, afterValue); + continue; + } + debug(`computing delta for path-list: ${key}`); + const beforeValues = beforeValue.split(';').map(s => s.trim()).filter(s => s.length > 0); + const afterValues = afterValue.split(';').map(s => s.trim()).filter(s => s.length > 0); + const newAfterValues = afterValues.filter(av => { + if (beforeValues.some(bv => pathsAreSame(bv, av))) { + debug(`- path same as before, skipping: ${av}`); + return false; + } + debug(`- new path, including in delta: ${av}`); + return true; + }); + if (newAfterValues.length === 0) { + debug('- no new paths found, skipping environment variable'); + } + else { + delta.set(key, newAfterValues.join(';')); } - debug(` - new path, including in delta: ${av}`); - return true; - }); - if (newAfterValues.length === 0) { - debug(' - no new paths found, skipping environment variable'); - } - else { - delta.set(key, newAfterValues.join(';')); } + return delta; + } + finally { + endDebugGroup(); } - return delta; } function processPaths(vars, processStyle) { - debug(`Processing environment variables with process style ${processStyle}`); - const result = new CaseInsensitiveStringMap(); - for (const [key, value] of vars) { - if (isSinglePathEnvVar(key)) { - const path = processExistingPath(value, processStyle); - debug(`- single path "${key}": ${value} -> ${value === path ? '(unchanged)' : path}`); - if (path) { - result.set(key, path); - } - continue; - } - if (isMultiPathEnvVar(key)) { - debug(`- multi path "${key}"`); - const paths = value - .split(';') - .map(s => { - const processed = processExistingPath(s, processStyle); - debug(` - ${s} -> ${s === processed ? '(unchanged)' : processed}`); - return processed; - }) - .filter(s => s !== ''); - if (paths.length === 0) { - debug(' - no valid paths found, skipping environment variable'); + startDebugGroup(`Processing environment variables (${processStyle})`); + try { + const result = new CaseInsensitiveStringMap(); + for (const [key, value] of vars) { + if (isSinglePathEnvVar(key)) { + const path = processExistingPath(value, processStyle); + debug(`single path "${key}": ${value} -> ${value === path ? '(unchanged)' : path}`); + if (path) { + result.set(key, path); + } continue; } - switch (processStyle) { - case ProcessStyle.Windows: - result.set(key, paths.join(';')); - break; - case ProcessStyle.Cygwin: - case ProcessStyle.MSYS2: - result.set(key, paths.join(':')); - break; - default: - throw new Error(`Unsupported process style: ${processStyle}`); + if (isMultiPathEnvVar(key)) { + debug(`multi path "${key}"`); + const paths = value + .split(';') + .map(s => { + const processed = processExistingPath(s, processStyle); + debug(`- ${s} -> ${s === processed ? '(unchanged)' : processed}`); + return processed; + }) + .filter(s => s !== ''); + if (paths.length === 0) { + debug('- no valid paths found, skipping environment variable'); + continue; + } + switch (processStyle) { + case ProcessStyle.Windows: + result.set(key, paths.join(';')); + break; + case ProcessStyle.Cygwin: + case ProcessStyle.MSYS2: + result.set(key, paths.join(':')); + break; + default: + throw new Error(`Unsupported process style: ${processStyle}`); + } + continue; } - continue; + debug(`not path "${key}": ${value}`); + result.set(key, value); } - debug(`- not path "${key}": ${value}`); - result.set(key, value); + return result; + } + finally { + endDebugGroup(); } - return result; } const byteToHex = []; @@ -29708,23 +29767,30 @@ function parseProcessPathsOption(option) { } async function inspectVCVarsAllEnvironmentVariables(vcVarsAllPath, options) { const processStyle = parseProcessPathsOption(options?.processPaths || ""); - const args = getArgumentsFromOptions(options); - debug(`vcvarsall.bat arguments: ${JSON.stringify(args)}`); const sep = "[----------SEPARATOR-" + v4() + "----------]"; - const result = await run$1('cmd.exe', ['/c', `set && echo ${sep} && "${vcVarsAllPath}" ${args.join(" ")} && echo ${sep} && set`], { - env: { - ComSpec: process.env.ComSpec || - path$1.join(process.env.SystemRoot || process.env.windir || "C:\\Windows", "System32", "cmd.exe"), - Path: [ - path$1.join(process.env.SystemRoot || process.env.windir || "C:\\Windows", "System32"), - process.env.SystemRoot || process.env.windir || "C:\\Windows", - ].join(";"), - SystemRoot: process.env.SystemRoot || process.env.windir || "C:\\Windows", - windir: process.env.SystemRoot || process.env.windir || "C:\\Windows", - }, - }); - if (result.exitCode !== 0) { - throw new Error(`Failed to get environment variables: ${result.stderr || result.stdout || `Exited with code ${result.exitCode}`}`); + startDebugGroup("Running vcvarsall.bat"); + let result; + try { + const args = getArgumentsFromOptions(options); + debug(`vcvarsall.bat arguments: ${JSON.stringify(args)}`); + result = await run$1('cmd.exe', ['/c', `set && echo ${sep} && "${vcVarsAllPath}" ${args.join(" ")} && echo ${sep} && set`], { + env: { + ComSpec: process.env.ComSpec || + path$1.join(process.env.SystemRoot || process.env.windir || "C:\\Windows", "System32", "cmd.exe"), + Path: [ + path$1.join(process.env.SystemRoot || process.env.windir || "C:\\Windows", "System32"), + process.env.SystemRoot || process.env.windir || "C:\\Windows", + ].join(";"), + SystemRoot: process.env.SystemRoot || process.env.windir || "C:\\Windows", + windir: process.env.SystemRoot || process.env.windir || "C:\\Windows", + }, + }); + if (result.exitCode !== 0) { + throw new Error(`Failed to get environment variables: ${result.stderr || result.stdout || `Exited with code ${result.exitCode}`}`); + } + } + finally { + endDebugGroup(); } const [rawEnvBefore, _, rawEnvAfter] = result.stdout .split(sep) @@ -29732,11 +29798,14 @@ async function inspectVCVarsAllEnvironmentVariables(vcVarsAllPath, options) { if (!rawEnvBefore || !rawEnvAfter) { throw new Error(`Failed to parse environment variables: ${result.stdout}`); } - debug(`Parsing environment variables set before running vcvarsall.bat\n ${rawEnvBefore.replace(/\n/g, "\n ")}`); + startDebugGroup("Environment variables before vcvarsall.bat"); + debug(rawEnvBefore); + endDebugGroup(); const envBefore = parseSetOutput(rawEnvBefore); - debug(`Parsing environment variables set after running vcvarsall.bat\n ${rawEnvAfter.replace(/\n/g, "\n ")}`); + startDebugGroup("Environment variables after vcvarsall.bat"); + debug(rawEnvAfter); + endDebugGroup(); const envAfter = parseSetOutput(rawEnvAfter); - debug(`Computing environment variable delta`); let delta = computeEnvDelta(envBefore, envAfter); if (processStyle !== null) { delta = processPaths(delta, processStyle); diff --git a/src/env-vars.ts b/src/env-vars.ts index f5f3e00..74c2e4d 100644 --- a/src/env-vars.ts +++ b/src/env-vars.ts @@ -48,7 +48,7 @@ function isMultiPathEnvVar(name: string): boolean { return MULTI_PATH_ENV_VARS.includes(envNameNormalizer(name)); } -const pathsAreSame: (path1: string, path2: string) => boolean = (function() { +const pathsAreSame: (path1: string, path2: string) => boolean = (function () { function getComparablePath(path: string): string { path = path.trim().toLocaleLowerCase(); if (!/^[a-zA-Z]:[/\\]/.test(path)) { @@ -58,7 +58,7 @@ const pathsAreSame: (path1: string, path2: string) => boolean = (function() { .replace(/\//g, '\\') .replace(/\\+/g, '\\') .replace(/\\$/, '') - ; + ; if (path[2] === undefined) { path += '\\'; } @@ -74,93 +74,101 @@ export function parseSetOutput(setOutput: string): CaseInsensitiveStringMap { setOutput.split('\n').forEach(line => { const match = line.replace(/\r+$/, '').match(/^([^=]+)=(.*)$/); if (match) { - result.set(match[1].trim(), match[2]); + result.set(match[1].trim(), match[2]); } }); return result; } export function computeEnvDelta(before: CaseInsensitiveStringMap, after: CaseInsensitiveStringMap): CaseInsensitiveStringMap { - const delta = new CaseInsensitiveStringMap(); - - for (const [key, afterValue] of after) { - const beforeValue = before.get(key); - if (beforeValue === undefined) { - log.debug(`- new: ${key}=${afterValue}`); - delta.set(key, afterValue); - continue; - } - if (afterValue === beforeValue) { - log.debug(`- unchanged: ${key}=${afterValue}`); - continue; - } - if (!isMultiPathEnvVar(key)) { - log.debug(`- changed: ${key}=${afterValue} (was ${beforeValue})`); - delta.set(key, afterValue); - continue; - } - log.debug(`- computing delta for path-list: ${key}`); - const beforeValues = beforeValue.split(';').map(s => s.trim()).filter(s => s.length > 0); - const afterValues = afterValue.split(';').map(s => s.trim()).filter(s => s.length > 0); - const newAfterValues = afterValues.filter(av => { - if (beforeValues.some(bv => pathsAreSame(bv, av))) { - log.debug(` - path same as before, skipping: ${av}`); - return false; + log.startDebugGroup(`Computing environment variable delta`); + try { + const delta = new CaseInsensitiveStringMap(); + for (const [key, afterValue] of after) { + const beforeValue = before.get(key); + if (beforeValue === undefined) { + log.debug(`new: ${key}=${afterValue}`); + delta.set(key, afterValue); + continue; + } + if (afterValue === beforeValue) { + log.debug(`unchanged: ${key}=${afterValue}`); + continue; + } + if (!isMultiPathEnvVar(key)) { + log.debug(`changed: ${key}=${afterValue} (was ${beforeValue})`); + delta.set(key, afterValue); + continue; + } + log.debug(`computing delta for path-list: ${key}`); + const beforeValues = beforeValue.split(';').map(s => s.trim()).filter(s => s.length > 0); + const afterValues = afterValue.split(';').map(s => s.trim()).filter(s => s.length > 0); + const newAfterValues = afterValues.filter(av => { + if (beforeValues.some(bv => pathsAreSame(bv, av))) { + log.debug(`- path same as before, skipping: ${av}`); + return false; + } + log.debug(`- new path, including in delta: ${av}`); + return true; + }); + if (newAfterValues.length === 0) { + log.debug('- no new paths found, skipping environment variable'); + } else { + delta.set(key, newAfterValues.join(';')); } - log.debug(` - new path, including in delta: ${av}`); - return true; - }); - if (newAfterValues.length === 0) { - log.debug(' - no new paths found, skipping environment variable'); - } else { - delta.set(key, newAfterValues.join(';')); } + return delta; + } finally { + log.endDebugGroup(); } - return delta; } export function processPaths(vars: CaseInsensitiveStringMap, processStyle: ProcessStyle): CaseInsensitiveStringMap { - log.debug(`Processing environment variables with process style ${processStyle}`); - const result = new CaseInsensitiveStringMap(); - for (const [key, value] of vars) { - if (isSinglePathEnvVar(key)) { - const path = processExistingPath(value, processStyle); - log.debug(`- single path "${key}": ${value} -> ${value === path ? '(unchanged)' : path}`); - if (path) { - result.set(key, path); + log.startDebugGroup(`Processing environment variables (${processStyle})`); + try { + const result = new CaseInsensitiveStringMap(); + for (const [key, value] of vars) { + if (isSinglePathEnvVar(key)) { + const path = processExistingPath(value, processStyle); + log.debug(`single path "${key}": ${value} -> ${value === path ? '(unchanged)' : path}`); + if (path) { + result.set(key, path); + } + continue } - continue - } - if (isMultiPathEnvVar(key)) { - log.debug(`- multi path "${key}"`); - const paths = value - .split(';') - .map(s => { - const processed = processExistingPath(s, processStyle); - log.debug(` - ${s} -> ${s === processed ? '(unchanged)' : processed}`); - return processed; - }) - .filter(s => s !== '') - ; - if (paths.length === 0) { - log.debug(' - no valid paths found, skipping environment variable'); + if (isMultiPathEnvVar(key)) { + log.debug(`multi path "${key}"`); + const paths = value + .split(';') + .map(s => { + const processed = processExistingPath(s, processStyle); + log.debug(`- ${s} -> ${s === processed ? '(unchanged)' : processed}`); + return processed; + }) + .filter(s => s !== '') + ; + if (paths.length === 0) { + log.debug('- no valid paths found, skipping environment variable'); + continue; + } + switch (processStyle) { + case ProcessStyle.Windows: + result.set(key, paths.join(';')); + break; + case ProcessStyle.Cygwin: + case ProcessStyle.MSYS2: + result.set(key, paths.join(':')); + break; + default: + throw new Error(`Unsupported process style: ${processStyle}`); + } continue; } - switch (processStyle) { - case ProcessStyle.Windows: - result.set(key, paths.join(';')); - break; - case ProcessStyle.Cygwin: - case ProcessStyle.MSYS2: - result.set(key, paths.join(':')); - break; - default: - throw new Error(`Unsupported process style: ${processStyle}`); - } - continue; + log.debug(`not path "${key}": ${value}`); + result.set(key, value); } - log.debug(`- not path "${key}": ${value}`); - result.set(key, value); + return result; + } finally { + log.endDebugGroup(); } - return result; } diff --git a/src/log.ts b/src/log.ts index bc3ee2f..c6fd99c 100644 --- a/src/log.ts +++ b/src/log.ts @@ -8,9 +8,7 @@ export function setDebug(value: boolean): void { export function debug(message: string): void { if (enableDebug) { - String(message) - .split(/\r?\n/) - .forEach((line) => core.info(`[DEBUG] ${line}`)); + core.info(message) } else if (core.isDebug()) { core.debug(message); } @@ -39,3 +37,17 @@ export function startGroup(name: string): void { export function endGroup(): void { core.endGroup(); } + +export function startDebugGroup(name: string): void { + if (enableDebug) { + core.startGroup(name); + } else if (core.isDebug()) { + core.debug(`--- ${name} ---`); + } +} + +export function endDebugGroup(): void { + if (enableDebug) { + core.endGroup(); + } +} diff --git a/src/vcvarsall-enviro-inspector.ts b/src/vcvarsall-enviro-inspector.ts index d982a8a..bfdba93 100644 --- a/src/vcvarsall-enviro-inspector.ts +++ b/src/vcvarsall-enviro-inspector.ts @@ -10,10 +10,10 @@ interface Options { architecture?: Architecture | string; platformType?: "" | "store" | "uwp" | string; windowsSDKVersion?: - | "" - | `${number}.${number}` - | `${number}.${number}.${number}.${number}` - | string; + | "" + | `${number}.${number}` + | `${number}.${number}.${number}.${number}` + | string; spectreMode?: boolean; processPaths?: "" | "windows" | "cygwin" | "msys2" | string; } @@ -167,37 +167,43 @@ export async function inspectVCVarsAllEnvironmentVariables( options?: Options, ): Promise { const processStyle = parseProcessPathsOption(options?.processPaths || ""); - const args = getArgumentsFromOptions(options); - log.debug(`vcvarsall.bat arguments: ${JSON.stringify(args)}`); const sep = "[----------SEPARATOR-" + uuidV4() + "----------]"; - const result = await runner.run( - 'cmd.exe', - ['/c', `set && echo ${sep} && "${vcVarsAllPath}" ${args.join(" ")} && echo ${sep} && set`], - { - env: { - ComSpec: - process.env.ComSpec || - path.join( + log.startDebugGroup("Running vcvarsall.bat"); + let result: runner.Result; + try { + const args = getArgumentsFromOptions(options); + log.debug(`vcvarsall.bat arguments: ${JSON.stringify(args)}`); + result = await runner.run( + 'cmd.exe', + ['/c', `set && echo ${sep} && "${vcVarsAllPath}" ${args.join(" ")} && echo ${sep} && set`], + { + env: { + ComSpec: + process.env.ComSpec || + path.join( + process.env.SystemRoot || process.env.windir || "C:\\Windows", + "System32", + "cmd.exe", + ), + Path: [ + path.join( + process.env.SystemRoot || process.env.windir || "C:\\Windows", + "System32", + ), process.env.SystemRoot || process.env.windir || "C:\\Windows", - "System32", - "cmd.exe", - ), - Path: [ - path.join( - process.env.SystemRoot || process.env.windir || "C:\\Windows", - "System32", - ), - process.env.SystemRoot || process.env.windir || "C:\\Windows", - ].join(";"), - SystemRoot: process.env.SystemRoot || process.env.windir || "C:\\Windows", - windir: process.env.SystemRoot || process.env.windir || "C:\\Windows", + ].join(";"), + SystemRoot: process.env.SystemRoot || process.env.windir || "C:\\Windows", + windir: process.env.SystemRoot || process.env.windir || "C:\\Windows", + }, }, - }, - ); - if (result.exitCode !== 0) { - throw new Error( - `Failed to get environment variables: ${result.stderr || result.stdout || `Exited with code ${result.exitCode}`}`, ); + if (result.exitCode !== 0) { + throw new Error( + `Failed to get environment variables: ${result.stderr || result.stdout || `Exited with code ${result.exitCode}`}`, + ); + } + } finally { + log.endDebugGroup(); } const [rawEnvBefore, _, rawEnvAfter] = result.stdout .split(sep) @@ -205,15 +211,14 @@ export async function inspectVCVarsAllEnvironmentVariables( if (!rawEnvBefore || !rawEnvAfter) { throw new Error(`Failed to parse environment variables: ${result.stdout}`); } - log.debug( - `Parsing environment variables set before running vcvarsall.bat\n ${rawEnvBefore.replace(/\n/g, "\n ")}`, - ); + log.startDebugGroup("Environment variables before vcvarsall.bat"); + log.debug(rawEnvBefore); + log.endDebugGroup(); const envBefore = parseSetOutput(rawEnvBefore); - log.debug( - `Parsing environment variables set after running vcvarsall.bat\n ${rawEnvAfter.replace(/\n/g, "\n ")}`, - ); + log.startDebugGroup("Environment variables after vcvarsall.bat"); + log.debug(rawEnvAfter); + log.endDebugGroup(); const envAfter = parseSetOutput(rawEnvAfter); - log.debug(`Computing environment variable delta`); let delta: CaseInsensitiveStringMap = computeEnvDelta(envBefore, envAfter); if (processStyle !== null) { delta = processPaths(delta, processStyle); diff --git a/src/vcvarsall-locator.ts b/src/vcvarsall-locator.ts index 4f11fa7..e3f6539 100644 --- a/src/vcvarsall-locator.ts +++ b/src/vcvarsall-locator.ts @@ -17,19 +17,24 @@ export async function findVcvarsallByVisualStudioVersion( export function findVcvarsallByVisualStudioPath( visualStudioPath: string, ): string { - const tryPath = path.join( - visualStudioPath, - "VC", - "Auxiliary", - "Build", - "vcvarsall.bat", - ); - if (fs.statSync(tryPath).isFile()) { - const realPath = fs.realpathSync.native(tryPath); - log.debug(`vcvarsall.bat found at: ${realPath}`); - return realPath; + log.startDebugGroup("Finding vcvarsall.bat"); + try { + const tryPath = path.join( + visualStudioPath, + "VC", + "Auxiliary", + "Build", + "vcvarsall.bat", + ); + if (fs.statSync(tryPath).isFile()) { + const realPath = fs.realpathSync.native(tryPath); + log.debug(`vcvarsall.bat found at: ${realPath}`); + return realPath; + } + throw new Error( + `vcvarsall.bat not found in Visual Studio installation at: ${visualStudioPath}`, + ); + } finally { + log.endDebugGroup(); } - throw new Error( - `vcvarsall.bat not found in Visual Studio installation at: ${visualStudioPath}`, - ); } diff --git a/src/visualstudio-finder.ts b/src/visualstudio-finder.ts index d190ae4..7edd928 100644 --- a/src/visualstudio-finder.ts +++ b/src/visualstudio-finder.ts @@ -24,6 +24,7 @@ function getVSWhereVersionArguments( async function findVisualStudioInstallationPathWithVSWhere( version: VisualStudioVersion | LatestVersion, + vsWherePath: string, ): Promise { const args: string[] = [ "-products", @@ -34,7 +35,6 @@ async function findVisualStudioInstallationPathWithVSWhere( "-property", "installationPath", ]; - const vsWherePath = await findVsWhere(); const result = await runner.run(`"${vsWherePath}"`, args, { throwIfNonZeroExitCode: true, }); @@ -101,21 +101,33 @@ function findVisualStudioInstallationPathDefaults( export async function findVisualStudioInstallationPath( version: VisualStudioVersion | LatestVersion, ): Promise { + let vsWherePath: string | undefined; try { - return await findVisualStudioInstallationPathWithVSWhere(version); - } catch (err) { - log.debug( - `Failed to find Visual Studio installation with vswhere.exe: ${err instanceof Error ? err.message : err}`, - ); + vsWherePath = await findVsWhere(); + } catch { } + log.startDebugGroup("Finding Visual Studio") try { - return findVisualStudioInstallationPathDefaults(version); - } catch (err) { - log.debug( - `Failed to find Visual Studio installation with default paths: ${err instanceof Error ? err.message : err}`, + if (vsWherePath) { + try { + return await findVisualStudioInstallationPathWithVSWhere(version, vsWherePath); + } catch (err) { + log.debug( + `Failed to find Visual Studio installation with vswhere.exe: ${err instanceof Error ? err.message : err}`, + ); + } + } + try { + return findVisualStudioInstallationPathDefaults(version); + } catch (err) { + log.debug( + `Failed to find Visual Studio installation with default paths: ${err instanceof Error ? err.message : err}`, + ); + } + throw new Error( + `Unable to find Visual Studio installation for version ${version === "latest" ? version : version.year}`, ); + } finally { + log.endDebugGroup(); } - throw new Error( - `Unable to find Visual Studio installation for version ${version === "latest" ? version : version.year}`, - ); } diff --git a/src/vswhere-finder.ts b/src/vswhere-finder.ts index adc89e3..c8d9369 100644 --- a/src/vswhere-finder.ts +++ b/src/vswhere-finder.ts @@ -3,27 +3,25 @@ import * as path from "node:path"; import { findProgram } from "./program-finder"; import * as log from "./log"; -let vsWherePath: string | Error | undefined; - export async function findVsWhere(): Promise { - if (vsWherePath !== undefined) { - if (vsWherePath instanceof Error) { - throw vsWherePath; - } - return vsWherePath; - } + let vsWherePath: string | undefined; + log.startDebugGroup("Finding vswhere.exe"); try { vsWherePath = await findProgram("vswhere.exe"); - return vsWherePath; } catch (err) { log.debug( `Failed to find vswhere.exe with where.exe (${err instanceof Error ? err.message : err}), let's try with some known paths`, ); } + if (vsWherePath) { + log.debug(`Found vswhere.exe at ${vsWherePath}`); + log.endDebugGroup(); + return vsWherePath; + } const programsPath = path.join( process.env["ProgramFiles(x86)"] || - "C:\\Program Files (x86)" || - "C:\\Program Files", + "C:\\Program Files (x86)" || + "C:\\Program Files", ); const p = path.join( programsPath, @@ -33,13 +31,14 @@ export async function findVsWhere(): Promise { ); try { vsWherePath = fs.realpathSync.native(p); - log.debug(`vswhere.exe at expected location ${vsWherePath}`); - return vsWherePath; } catch { - vsWherePath = new Error( - "vswhere.exe not found at expected locations: " + p, - ); - log.error(vsWherePath); - throw vsWherePath; + log.debug(`vswhere.exe not found at expected location ${p}`); + } + if (vsWherePath) { + log.debug(`Found vswhere.exe at ${vsWherePath}`); + log.endDebugGroup(); + return vsWherePath; } + log.endDebugGroup(); + throw new Error("Unable to find vswhere.exe"); }