From ab646cff2829d2b81e809f5a1d86419d5de23f6b Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 5 May 2021 20:44:54 -0700 Subject: [PATCH] Do not allow git replacement objects by default (#30) Fix: https://github.com/github/npm-cli/issues/46 --- lib/clone.js | 2 +- lib/spawn.js | 11 +- package-lock.json | 284 ---------------------------------------------- test/clone.js | 58 +++++++++- test/spawn.js | 25 +++- 5 files changed, 85 insertions(+), 295 deletions(-) diff --git a/lib/clone.js b/lib/clone.js index 1fea5ac..6754fd7 100644 --- a/lib/clone.js +++ b/lib/clone.js @@ -30,7 +30,7 @@ const pickManifest = require('npm-pick-manifest') const fs = require('fs') const mkdirp = require('mkdirp') -module.exports = (repo, ref = 'HEAD', target = null, /* istanbul ignore next */ opts = {}) => +module.exports = (repo, ref = 'HEAD', target = null, opts = {}) => revs(repo, opts).then(revs => clone( repo, revs, diff --git a/lib/spawn.js b/lib/spawn.js index cee3a7b..337164a 100644 --- a/lib/spawn.js +++ b/lib/spawn.js @@ -10,6 +10,11 @@ module.exports = (gitArgs, opts = {}) => { if (gitPath instanceof Error) { return Promise.reject(gitPath) } + // undocumented option, mostly only here for tests + const args = opts.allowReplace || gitArgs[0] === '--no-replace-objects' + ? gitArgs + : ['--no-replace-objects', ...gitArgs] + const log = opts.log || procLog let retry = opts.retry if (retry === null || retry === undefined) { @@ -22,11 +27,11 @@ module.exports = (gitArgs, opts = {}) => { } return promiseRetry((retry, number) => { if (number !== 1) { - log.silly('pacote', `Retrying git command: ${ - gitArgs.join(' ')} attempt # ${number}`) + log.silly('git', `Retrying git command: ${ + args.join(' ')} attempt # ${number}`) } - return spawn(gitPath, gitArgs, makeOpts(opts)) + return spawn(gitPath, args, makeOpts(opts)) .catch(er => { if (!shouldRetry(er.stderr, number)) { throw er diff --git a/package-lock.json b/package-lock.json index c552675..8546d36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -122,15 +122,6 @@ "node": ">=0.10.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.13" - } - }, "node_modules/@babel/helper-compilation-targets": { "version": "7.13.16", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", @@ -218,12 +209,6 @@ "@babel/types": "^7.12.13" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, "node_modules/@babel/helper-replace-supers": { "version": "7.13.12", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", @@ -300,86 +285,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz", - "integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.13.8", - "@babel/helper-compilation-targets": "^7.13.8", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.13.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz", - "integrity": "sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz", - "integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.13.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz", - "integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.13.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.13.12.tgz", - "integrity": "sha512-jcEI2UqIcpCqB5U5DRxIl0tQEProI2gcu+g8VTIqxLO5Iidojb4d77q+fwGseCvd8af/lJ9masp4QWzBXFE2xA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/types": "^7.13.12" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", @@ -912,39 +817,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-callsite/node_modules/callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2643,35 +2515,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-jsx": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-jsx/-/import-jsx-4.0.0.tgz", - "integrity": "sha512-CnjJ2BZFJzbFDmYG5S47xPQjMlSbZLyLJuG4znzL4TdPtJBxHtFP1xVmR+EYX4synFSldiY3B6m00XkPM3zVnA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.5.5", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/plugin-transform-destructuring": "^7.5.0", - "@babel/plugin-transform-react-jsx": "^7.3.0", - "caller-path": "^2.0.0", - "find-cache-dir": "^3.2.0", - "make-dir": "^3.0.2", - "resolve-from": "^3.0.0", - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/import-jsx/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -7426,15 +7269,6 @@ } } }, - "@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, "@babel/helper-compilation-targets": { "version": "7.13.16", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", @@ -7518,12 +7352,6 @@ "@babel/types": "^7.12.13" } }, - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, "@babel/helper-replace-supers": { "version": "7.13.12", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", @@ -7594,68 +7422,6 @@ "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", "dev": true }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz", - "integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.13.8", - "@babel/helper-compilation-targets": "^7.13.8", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.13.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz", - "integrity": "sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz", - "integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.13.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz", - "integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.13.0" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.13.12.tgz", - "integrity": "sha512-jcEI2UqIcpCqB5U5DRxIl0tQEProI2gcu+g8VTIqxLO5Iidojb4d77q+fwGseCvd8af/lJ9masp4QWzBXFE2xA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/types": "^7.13.12" - } - }, "@babel/runtime": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", @@ -8077,32 +7843,6 @@ "get-intrinsic": "^1.0.2" } }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -9391,30 +9131,6 @@ "resolve-from": "^4.0.0" } }, - "import-jsx": { - "version": "https://registry.npmjs.org/import-jsx/-/import-jsx-4.0.0.tgz", - "integrity": "sha512-CnjJ2BZFJzbFDmYG5S47xPQjMlSbZLyLJuG4znzL4TdPtJBxHtFP1xVmR+EYX4synFSldiY3B6m00XkPM3zVnA==", - "dev": true, - "requires": { - "@babel/core": "^7.5.5", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/plugin-transform-destructuring": "^7.5.0", - "@babel/plugin-transform-react-jsx": "^7.3.0", - "caller-path": "^2.0.0", - "find-cache-dir": "^3.2.0", - "make-dir": "^3.0.2", - "resolve-from": "^3.0.0", - "rimraf": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", diff --git a/test/clone.js b/test/clone.js index e8caa52..2ee1a94 100644 --- a/test/clone.js +++ b/test/clone.js @@ -8,17 +8,22 @@ const rimraf = require('rimraf') const { resolve, join } = require('path') const mkdirp = require('mkdirp') +// keep the fixture, because Windows fails when it tries to delete it, +// due to all the git operations happening inside. +t.saveFixture = true + const port = 12345 + (+process.env.TAP_CHILD_ID || 0) const spawnGit = require('../lib/spawn.js') -t.saveFixture = true const regularRepoDir = 'regular-folder' const me = t.testdir({ 'submodule-repo': {}, repo: {}, - [regularRepoDir]: {} + [regularRepoDir]: {}, + 'replacement-repo': {} }) const remote = `git://localhost:${port}/repo` const submodsRemote = `git://localhost:${port}/submodule-repo` +const replacementRemote = `git://localhost:${port}/replacement-repo` const repo = resolve(me, 'repo') let repoSha = '' @@ -28,7 +33,7 @@ t.setTimeout(120000) t.test('create repo', { bail: true }, t => { const git = (...cmd) => spawnGit(cmd, { cwd: repo }) const write = (f, c) => fs.writeFileSync(`${repo}/${f}`, c) - return git('init') + return git('init', '-b', 'main') .then(() => git('config', 'user.name', 'pacotedev')) .then(() => git('config', 'user.email', 'i+pacotedev@izs.me')) .then(() => git('config', 'tag.gpgSign', 'false')) @@ -88,6 +93,7 @@ t.test('spawn daemon', { bail: true }, t => { daemon.stderr.removeListener('data', onDaemonData) const pid = +cpid[1] t.parent.teardown(() => process.kill(pid)) + t.parent.on('bailout', () => process.kill(pid)) t.end() } } @@ -100,7 +106,7 @@ t.test('create a repo with a submodule', { bail: true }, t => { const repo = resolve(me, 'submodule-repo') const git = (...cmd) => spawnGit(cmd, { cwd: repo }) const write = (f, c) => fs.writeFileSync(`${repo}/${f}`, c) - return git('init') + return git('init', '-b', 'main') .then(() => git('config', 'user.name', 'pacotedev')) .then(() => git('config', 'user.email', 'i+pacotedev@izs.me')) .then(() => git('config', 'tag.gpgSign', 'false')) @@ -228,7 +234,7 @@ const clonedRepoSpaces2 = join(me, clonedSpacesRepoDir2) t.test('setup aditional tests', t => { const git = (...cmd) => spawnGit(cmd, { cwd: regularRepo }) const write = (f, c) => fs.writeFileSync(`${regularRepo}/${f}`, c) - return git('init') + return git('init', '-b', 'main') .then(() => write('foo', 'bar')) .then(() => git('add', 'foo')) .then(() => git('commit', '-m', 'foobar')) @@ -258,3 +264,45 @@ if ((process.platform) === 'win32') { .then((r) => revs(clonedRepoSpaces2).then((r2) => t.same(Object.keys(r.shas), Object.keys(r2.shas)))) ) } + +t.test('avoid having replacements break the world', { saveFixture: false }, async t => { + let replacementSha + t.before(async () => { + // The replacement ends up being 2 steps behind HEAD + const path = resolve(me, 'replacement-repo') + const git = (...cmd) => spawnGit(cmd, { cwd: path, allowReplace: true }) + const write = (f, c) => fs.writeFileSync(`${path}/${f}`, c) + await git('clone', '--mirror', remote, `${path}/.git`) + await git('init', '-b', 'main') + await git('config', 'user.name', 'pacotedev') + await git('config', 'user.email', 'i+pacotedev@izs.me') + await git('config', 'tag.gpgSign', 'false') + await git('config', 'commit.gpgSign', 'false') + await git('config', 'tag.forceSignAnnotated', 'false') + await git('checkout', 'main') + await git('checkout', '-b', 'replacement-branch') + await write('replacement-file', 'replacement contents') + await git('add', 'replacement-file') + await git('commit', '-m', 'replacement commit') + const { stdout } = await git('rev-parse', 'HEAD') + replacementSha = stdout.trim() + await git('checkout', 'main') + await write('post-replacement', 'after replacement') + await git('add', 'post-replacement') + await git('commit', '-m', 'after the replacement') + await git('replace', '-f', repoSha, replacementSha) + }) + t.test('get the original thing by default', async t => { + const path = t.testdir() + '/noreplace' + await clone(replacementRemote, 'HEAD^^', path) + t.throws(() => fs.statSync(resolve(path, 'replacement-file')), { + code: 'ENOENT' + }, 'should not have file from replacement commit') + }) + t.test('get the replaced thing if allowReplace:true', async t => { + const path = t.testdir() + '/yesreplace' + await clone(replacementRemote, 'HEAD^^', path, { allowReplace: true }) + t.equal(fs.readFileSync(resolve(path, 'replacement-file'), 'utf8'), + 'replacement contents') + }) +}) diff --git a/test/spawn.js b/test/spawn.js index 47b6c99..9fe03b6 100644 --- a/test/spawn.js +++ b/test/spawn.js @@ -21,6 +21,26 @@ t.test('setup repo', t => { { stdout: `Initialized empty Git repository in ${slash(fs.realpathSync.native(repo))}` }) }) +t.test('argument test for allowReplace', async t => { + // Note: the *actual* impact of allowReplace:true is tested in + // test/clone.js, since it covers the use case that is relevant + // for our purposes. This just tests that the argument is added + // by default. + const spawn = t.mock('../lib/spawn.js', { + '@npmcli/promise-spawn': async (exe, args, opts) => args + }) + const [allow, deny, allowWithArg, denyWithArg] = await Promise.all([ + spawn(['a', 'b', 'c'], { allowReplace: true }), + spawn(['a', 'b', 'c']), + spawn(['--no-replace-objects', 'a', 'b', 'c'], { allowReplace: true }), + spawn(['--no-replace-objects', 'a', 'b', 'c']) + ]) + t.same(allow, ['a', 'b', 'c'], 'replacements allowed') + t.same(deny, ['--no-replace-objects', 'a', 'b', 'c'], 'replacements not allowed') + t.same(allowWithArg, ['--no-replace-objects', 'a', 'b', 'c'], 'allowed by config, not pruned out') + t.same(denyWithArg, ['--no-replace-objects', 'a', 'b', 'c'], 'denied by config, not duplicated') +}) + t.test('retries', t => { const logs = [] process.on('log', (...log) => logs.push(log)) @@ -58,18 +78,19 @@ process.exit(1) t.rejects(spawn([te], { cwd: repo, git: process.execPath, + allowReplace: true, log: procLog, ...(retryOptions[n]) }), er).then(() => { t.same(logs, [ [ 'silly', - 'pacote', + 'git', `Retrying git command: ${te} attempt # 2` ], [ 'silly', - 'pacote', + 'git', `Retrying git command: ${te} attempt # 3` ] ], 'got expected logs')