%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/npm/test/bin/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/npm/test/bin/windows-shims.js |
const t = require('tap') const { spawnSync } = require('child_process') const { resolve, join, extname, basename, sep } = require('path') const { copyFileSync, readFileSync, chmodSync, readdirSync, rmSync, statSync } = require('fs') const Diff = require('diff') const { sync: which } = require('which') const { version } = require('../../package.json') const readNonJsFiles = (dir) => readdirSync(dir).reduce((acc, shim) => { const p = join(dir, shim) if (extname(p) !== '.js' && !statSync(p).isDirectory()) { acc[shim] = readFileSync(p, 'utf-8') } return acc }, {}) const ROOT = resolve(__dirname, '../..') const BIN = join(ROOT, 'bin') const SHIMS = readNonJsFiles(BIN) const NODE_GYP = readNonJsFiles(join(BIN, 'node-gyp-bin')) const SHIM_EXTS = [...new Set(Object.keys(SHIMS).map(p => extname(p)))] // windows requires each segment of a command path to be quoted when using shell: true const quotePath = (cmd) => cmd .split(sep) .map(p => p.includes(' ') ? `"${p}"` : p) .join(sep) t.test('shim contents', t => { // these scripts should be kept in sync so this tests the contents of each // and does a diff to ensure the only differences between them are necessary const diffFiles = (npm, npx) => Diff.diffChars(npm, npx) .filter(v => v.added || v.removed) .reduce((acc, v) => { if (v.value.length === 1) { acc.letters.add(v.value.toUpperCase()) } else { acc.diff.push(v.value) } return acc }, { diff: [], letters: new Set() }) t.plan(SHIM_EXTS.length) t.test('bash', t => { const { diff, letters } = diffFiles(SHIMS.npm, SHIMS.npx) t.match(diff[0].split('\n').reverse().join(''), /^NPX_CLI_JS=/, 'has NPX_CLI') t.equal(diff.length, 1) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) t.test('cmd', t => { const { diff, letters } = diffFiles(SHIMS['npm.cmd'], SHIMS['npx.cmd']) t.match(diff[0], /^SET "NPX_CLI_JS=/, 'has NPX_CLI') t.equal(diff.length, 1) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) t.test('pwsh', t => { const { diff, letters } = diffFiles(SHIMS['npm.ps1'], SHIMS['npx.ps1']) t.equal(diff.length, 0) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) }) t.test('node-gyp', t => { // these files need to exist to avoid breaking yarn 1.x for (const [key, file] of Object.entries(NODE_GYP)) { t.match(file, /npm_config_node_gyp/, `${key} contains env var`) t.match( file, /[\\/]\.\.[\\/]\.\.[\\/]node_modules[\\/]node-gyp[\\/]bin[\\/]node-gyp\.js/, `${key} contains path` ) } t.end() }) t.test('run shims', t => { const path = t.testdir({ ...SHIMS, // simulate the state where one version of npm is installed // with node, but we should load the globally installed one 'global-prefix': { node_modules: { npm: t.fixture('symlink', ROOT), }, }, // put in a shim that ONLY prints the intended global prefix, // and should not be used for anything else. node_modules: { npm: { bin: { 'npx-cli.js': `throw new Error('this should not be called')`, 'npm-cli.js': ` const assert = require('assert') const { resolve } = require('path') assert.equal(process.argv.slice(2).join(' '), 'prefix -g') console.log(resolve(__dirname, '../../../global-prefix')) `, }, }, }, }) // hacky fix to decrease flakes of this test from `NOTEMPTY: directory not empty, rmdir` // this should get better in tap@18 and we can try removing it then copyFileSync(process.execPath, join(path, 'node.exe')) t.teardown(async () => { rmSync(join(path, 'node.exe')) await new Promise(res => setTimeout(res, 100)) // this is superstition rmSync(join(path, 'node.exe'), { force: true }) }) const spawnPath = (cmd, args, { log, stdioString = true, ...opts } = {}) => { if (cmd.endsWith('bash.exe')) { // only cygwin *requires* the -l, but the others are ok with it args.unshift('-l') } const result = spawnSync(cmd, args, { // don't hit the registry for the update check env: { PATH: path, npm_config_update_notifier: 'false' }, cwd: path, windowsHide: true, ...opts, }) if (stdioString) { result.stdout = result.stdout?.toString()?.trim() result.stderr = result.stderr?.toString()?.trim() } return { status: result.status, signal: result.signal, stdout: result.stdout, stderr: result.stderr, } } const getWslVersion = (cmd) => { const defaultVersion = 1 try { const opts = { shell: cmd, env: process.env } const wsl = spawnPath('wslpath', [`'${which('wsl')}'`], opts).stdout const distrosRaw = spawnPath(wsl, ['-l', '-v'], { ...opts, stdioString: false }).stdout const distros = spawnPath('iconv', ['-f', 'unicode'], { ...opts, input: distrosRaw }).stdout const distroArgs = distros .replace(/\r\n/g, '\n') .split('\n') .slice(1) .find(d => d.startsWith('*')) .replace(/\s+/g, ' ') .split(' ') return Number(distroArgs[distroArgs.length - 1]) || defaultVersion } catch { return defaultVersion } } for (const shim of Object.keys(SHIMS)) { chmodSync(join(path, shim), 0o755) } const { ProgramFiles = '/', SystemRoot = '/', NYC_CONFIG, WINDOWS_SHIMS_TEST } = process.env const skipDefault = WINDOWS_SHIMS_TEST || process.platform === 'win32' ? null : 'test not relevant on platform' const shells = Object.entries({ cmd: 'cmd', pwsh: 'pwsh', git: join(ProgramFiles, 'Git', 'bin', 'bash.exe'), 'user git': join(ProgramFiles, 'Git', 'usr', 'bin', 'bash.exe'), wsl: join(SystemRoot, 'System32', 'bash.exe'), cygwin: resolve(SystemRoot, '/', 'cygwin64', 'bin', 'bash.exe'), }).map(([name, cmd]) => { let match = {} const skip = { reason: skipDefault, fail: WINDOWS_SHIMS_TEST } const isBash = cmd.endsWith('bash.exe') const testName = `${name} ${isBash ? 'bash' : ''}`.trim() if (!skip.reason) { if (isBash) { try { // If WSL is installed, it *has* a bash.exe, but it fails if // there is no distro installed, so we need to detect that. if (spawnPath(cmd, ['-c', 'exit 0']).status !== 0) { throw new Error('not installed') } if (name === 'cygwin' && NYC_CONFIG) { throw new Error('does not play nicely with nyc') } // WSL version 1 does not work due to // https://github.com/microsoft/WSL/issues/2370 if (name === 'wsl' && getWslVersion(cmd) === 1) { match = { status: 1, stderr: 'WSL 1 is not supported. Please upgrade to WSL 2 or above.', stdout: String, } } } catch (err) { skip.reason = err.message } } else { try { cmd = which(cmd) } catch { skip.reason = 'not installed' } } } return { match, cmd, name: testName, skip: { ...skip, reason: skip.reason ? `${testName} - ${skip.reason}` : null, }, } }) const matchCmd = (t, cmd, bin, match) => { const args = [] const opts = {} switch (basename(cmd).toLowerCase()) { case 'cmd.exe': cmd = `${bin}.cmd` break case 'bash.exe': args.push(bin) break case 'pwsh.exe': cmd = quotePath(cmd) args.push(`${bin}.ps1`) opts.shell = true break default: throw new Error('unknown shell') } const isNpm = bin === 'npm' const result = spawnPath(cmd, [...args, isNpm ? 'help' : '--version'], opts) t.match(result, { status: 0, signal: null, stderr: '', stdout: isNpm ? `npm@${version} ${ROOT}` : version, ...match, }, `${cmd} ${bin}`) } // ensure that all tests are either run or skipped t.plan(shells.length) for (const { cmd, skip, name, match } of shells) { t.test(name, t => { if (skip.reason) { if (skip.fail) { t.fail(skip.reason) } else { t.skip(skip.reason) } return t.end() } t.plan(2) matchCmd(t, cmd, 'npm', match) matchCmd(t, cmd, 'npx', match) }) } })