test(ci): read the Lefthook fixture lock path without trimming
git() trims its output, which also drops a worktree directory's own trailing whitespace; the installer removes only the line terminator. Derive the expected lock path through gitPath()/stripGitLineTerminator(), which applies the installer's exact rule, so the same-string claim holds for every path. Adds the trailing-space injection case (skipped on Windows, which cannot create such a directory); it fails with the same probe ENOENT under the trimming derivation.
This commit is contained in:
1 parent
acb66b4c23
commit
1829cdfec9
1 file changed
+32
-5
@@ -55,6 +55,24 @@ function git(fixture: Fixture, cwd: string, args: string[]): string {
|
||||
return result.stdout.trim()
|
||||
}
|
||||
|
||||
/** Remove the line terminator Git appends to a printed path, as the installer does. */
|
||||
function stripGitLineTerminator(output: string): string {
|
||||
const withoutLineFeed = output.endsWith('\n') ? output.slice(0, -1) : output
|
||||
return process.platform === 'win32' && withoutLineFeed.endsWith('\r')
|
||||
? withoutLineFeed.slice(0, -1)
|
||||
: withoutLineFeed
|
||||
}
|
||||
|
||||
// `git()` trims, which also drops a worktree directory's own trailing whitespace. Paths that must
|
||||
// equal the installer's own reading keep only the line terminator, so a trailing space survives.
|
||||
function gitPath(fixture: Fixture, cwd: string, args: string[]): string {
|
||||
const result = gitResult(fixture, cwd, args)
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`git ${args.join(' ')} failed: ${result.stderr}`)
|
||||
}
|
||||
return stripGitLineTerminator(result.stdout)
|
||||
}
|
||||
|
||||
function write(path: string, content: string, mode?: number): void {
|
||||
mkdirSync(dirname(path), { recursive: true })
|
||||
writeFileSync(path, content, mode === undefined ? undefined : { mode })
|
||||
@@ -161,12 +179,12 @@ function gitDirectory(fixture: Fixture, root: string): string {
|
||||
// The installer resolves the common directory against Git's own top-level path, and the host
|
||||
// spells that path differently from the fixture directory this file created: Git canonicalizes
|
||||
// Windows 8.3 short names and the macOS `/var` symlink, while `mkdtempSync` returns the temp
|
||||
// directory's own spelling. Resolving the relative common directory against Git's top-level
|
||||
// instead of the fixture directory gives the same string the installer computes, so an injected
|
||||
// failure on this path reaches the installer's own lock instead of missing it.
|
||||
// directory's own spelling. Reading both values the way the installer reads them (`gitPath`, not
|
||||
// the trimming `git()`) keeps the relative common directory resolved to the same string the
|
||||
// installer computes, so an injected failure on this path reaches the installer's own lock.
|
||||
function commonDirectory(fixture: Fixture): string {
|
||||
const root = git(fixture, fixture.main, ['rev-parse', '--show-toplevel'])
|
||||
const output = git(fixture, fixture.main, ['rev-parse', '--git-common-dir'])
|
||||
const root = gitPath(fixture, fixture.main, ['rev-parse', '--show-toplevel'])
|
||||
const output = gitPath(fixture, fixture.main, ['rev-parse', '--git-common-dir'])
|
||||
return isAbsolute(output) ? output : resolve(root, output)
|
||||
}
|
||||
|
||||
@@ -397,6 +415,15 @@ syncBuiltinESMExports()
|
||||
await expectInjectedLockAccessFailure(fixture, { operation: 'openSync', code: 'EPERM', expires: false })
|
||||
})
|
||||
|
||||
// A worktree directory can end in a space on POSIX hosts; Git prints that path verbatim while a
|
||||
// trimming read would drop the space and name a different directory, so the injection only fires
|
||||
// when the expected path is read the installer's way. Windows cannot create such a directory.
|
||||
it.skipIf(process.platform === 'win32')('handles an injected lock failure in a worktree whose path ends with a space', async () => {
|
||||
await expectInjectedLockAccessFailure(createFixture({ main: 'main ' }), {
|
||||
operation: 'openSync', code: 'EPERM', expires: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('waits for a concurrent installer to finish publishing its lock record', async () => {
|
||||
const fixture = createFixture()
|
||||
const lockPath = installLockPath(fixture)
|
||||
|
||||
Reference in new issue
Block a user