Skip to content

Commit dbb7c7a

Browse files
author
pacotedev
committed
fix: add check to ensure we actually get our commit
1 parent 91847c4 commit dbb7c7a

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

‎lib/git.js‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ const repoUrl = (h, opts) =>
2525
// add git+ to the url, but only one time.
2626
const addGitPlus = url => url && `git+${url}`.replace(/^(git\+)+/, 'git+')
2727

28+
const checkoutError = (expected, found) => {
29+
const err = new Error(`Commit mismatch: expected SHA ${expected} and cloned HEAD ${found}`)
30+
err.code = 'EGITCHECKOUT'
31+
err.sha = expected
32+
err.head = found
33+
return err
34+
}
35+
2836
class GitFetcher extends Fetcher {
2937
constructor (spec, opts) {
3038
super(spec, opts)
@@ -259,6 +267,10 @@ class GitFetcher extends Fetcher {
259267
h ? this.#cloneHosted(ref, tmp)
260268
: this.#cloneRepo(this.spec.fetchSpec, ref, tmp)
261269
)
270+
// if we already have a resolved sha ensure it doesn't change
271+
if (this.resolvedSha && this.resolvedSha !== sha) {
272+
throw checkoutError(this.resolvedSha, sha)
273+
}
262274
this.resolvedSha = sha
263275
if (!this.resolved) {
264276
await this.#addGitSha(sha)

‎test/git.js‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ HostedGit.addHost('localhostssh', {
7272
})
7373

7474
const remote = `git://localhost:${gitPort}/repo`
75+
const remoteBroken = `git://localhost:${gitPort}/broken`
7576
const remoteHosted = `git://127.0.0.1:${gitPort}/repo`
7677
const submodsRemote = `git://localhost:${gitPort}/submodule-repo`
7778
const workspacesRemote = `git://localhost:${gitPort}/workspaces-repo`
@@ -86,6 +87,7 @@ const me = t.testdir({
8687
cache: {},
8788
})
8889
const repo = resolve(me, 'repo')
90+
const broken = resolve(me, 'broken')
8991
const cache = resolve(me, 'cache')
9092
const cycleA = resolve(me, 'cycle-a')
9193
const cycleB = resolve(me, 'cycle-b')
@@ -455,6 +457,37 @@ t.test('ignores integrity for git deps', { skip: isWindows && 'posix only' }, as
455457
t.end()
456458
})
457459

460+
t.test('detects changes in the resolved sha', {}, async (t) => {
461+
const git = (...cmd) => spawnGit(cmd, { cwd: broken })
462+
const write = (f, c) => fs.writeFileSync(f, c)
463+
464+
await mkdir(broken, { recursive: true })
465+
.then(() => git('config', 'user.name', 'pacotedev'))
466+
.then(() => git('config', 'user.email', 'i+pacotedev@izs.me'))
467+
.then(() => git('config', 'tag.gpgSign', 'false'))
468+
.then(() => git('config', 'commit.gpgSign', 'false'))
469+
.then(() => git('config', 'tag.forceSignAnnotated', 'false'))
470+
.then(() => git('init'))
471+
.then(() => write(`${broken}/package.json`, JSON.stringify({
472+
name: 'repo',
473+
version: '0.0.0',
474+
})))
475+
.then(() => git('add', 'package.json'))
476+
.then(() => git('commit', '-m', 'package json file'))
477+
.then(() => git('checkout', '-b', REPO_HEAD))
478+
479+
const { stdout: actual } = await git('rev-parse', 'HEAD')
480+
481+
const fetcher = new GitFetcher(remoteBroken + '#' + REPO_HEAD, opts)
482+
await t.rejects(() => fetcher.manifest(), {
483+
message: `Commit mismatch: expected SHA ${REPO_HEAD} and cloned HEAD ${actual}`,
484+
code: 'EGITCHECKOUT',
485+
sha: REPO_HEAD,
486+
head: actual,
487+
})
488+
t.end()
489+
})
490+
458491
t.test('weird hosted that doesnt provide any fetch targets', { skip: isWindows && 'posix only' },
459492
t => {
460493
const hosted = {

0 commit comments

Comments
 (0)