修复Windows下Git钩子回归测试
统一比较Git恢复文件时的换行符 将WSL bash测试使用的临时工具路径转换为可执行路径 确保master推送门禁在Windows与Unix环境下均可重复验证
This commit is contained in:
+66
-38
@@ -145,7 +145,7 @@ test('pre-commit hook fixes staged imports and formatting without swallowing uns
|
||||
'const original = { value: 1 };\nconst keep = 2;\n',
|
||||
);
|
||||
assert.equal(
|
||||
readFileSync(partialPath, 'utf8'),
|
||||
readFileSync(partialPath, 'utf8').replaceAll('\r\n', '\n'),
|
||||
'const original = { value: 1 };\nconst keep={unstaged:true}\n',
|
||||
);
|
||||
assert.equal(
|
||||
@@ -160,53 +160,73 @@ test('pre-commit hook fixes staged imports and formatting without swallowing uns
|
||||
test('pre-push runs repository parity only for master updates', () => {
|
||||
const tempDir = mkdtempSync(join(tmpdir(), 'genarrative-pre-push-'));
|
||||
try {
|
||||
const binDir = join(tempDir, 'bin');
|
||||
mkdirSync(binDir);
|
||||
const npmLog = join(tempDir, 'npm.log');
|
||||
const fakeNpm = join(binDir, 'npm');
|
||||
const fakeGit = join(binDir, 'git');
|
||||
writeFileSync(
|
||||
fakeNpm,
|
||||
`#!/usr/bin/env bash\nprintf '%s\\n' "$*" >> "${npmLog}"\n`,
|
||||
const npmLog = join(tempDir, 'repo', 'npm.log');
|
||||
const tempRepo = join(tempDir, 'repo');
|
||||
mkdirSync(tempRepo);
|
||||
git(tempRepo, 'init', '--quiet');
|
||||
git(tempRepo, 'config', 'user.email', 'git-hooks-test@example.invalid');
|
||||
git(tempRepo, 'config', 'user.name', 'Git Hooks Test');
|
||||
writeFileSync(join(tempRepo, 'tracked.txt'), 'baseline\n');
|
||||
git(tempRepo, 'add', 'tracked.txt');
|
||||
git(
|
||||
tempRepo,
|
||||
'-c',
|
||||
'commit.gpgsign=false',
|
||||
'commit',
|
||||
'--quiet',
|
||||
'-m',
|
||||
'baseline',
|
||||
);
|
||||
chmodSync(fakeNpm, 0o755);
|
||||
const localSha = git(tempRepo, 'rev-parse', 'HEAD').trim();
|
||||
writeFileSync(
|
||||
fakeGit,
|
||||
'#!/usr/bin/env bash\n' +
|
||||
'if [[ "$1" == "rev-parse" && "$2" == "HEAD" ]]; then\n' +
|
||||
' printf "%s\\n" "1111111111111111111111111111111111111111"\n' +
|
||||
' exit 0\n' +
|
||||
'fi\n' +
|
||||
'if [[ "$1" == "diff" ]]; then exit 0; fi\n' +
|
||||
'exit 1\n',
|
||||
join(tempRepo, 'git'),
|
||||
`#!/usr/bin/env bash
|
||||
if [[ "$1" == 'rev-parse' && "$2" == 'HEAD' ]]; then
|
||||
printf '%s\\n' '${localSha}'
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$1" == 'diff' ]]; then exit 0; fi
|
||||
exit 1
|
||||
`,
|
||||
);
|
||||
chmodSync(fakeGit, 0o755);
|
||||
const env = {
|
||||
...process.env,
|
||||
PATH: `${binDir}${delimiter}${process.env.PATH ?? ''}`,
|
||||
chmodSync(join(tempRepo, 'git'), 0o755);
|
||||
writeFileSync(
|
||||
join(tempRepo, 'pre-push-master.sh'),
|
||||
readFileSync(join(repoRoot, 'scripts', 'pre-push-master.sh'), 'utf8'),
|
||||
);
|
||||
writeFileSync(
|
||||
join(tempRepo, 'npm'),
|
||||
'#!/usr/bin/env bash\nprintf \'%s\\n\' "$*" >> npm.log\n',
|
||||
);
|
||||
chmodSync(join(tempRepo, 'npm'), 0o755);
|
||||
const spawnHook = (input) => {
|
||||
writeFileSync(join(tempRepo, 'push.input'), input);
|
||||
return spawnSync(
|
||||
'bash',
|
||||
[
|
||||
'-c',
|
||||
'PATH="$PWD:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; export PATH; source ./pre-push-master.sh origin example.invalid < push.input',
|
||||
],
|
||||
{
|
||||
cwd: tempRepo,
|
||||
encoding: 'utf8',
|
||||
env: process.env,
|
||||
},
|
||||
);
|
||||
};
|
||||
const hook = join(repoRoot, 'scripts', 'pre-push-master.sh');
|
||||
const featurePush = spawnSync('bash', [hook, 'origin', 'example.invalid'], {
|
||||
cwd: repoRoot,
|
||||
encoding: 'utf8',
|
||||
env,
|
||||
input:
|
||||
'refs/heads/feature 1111111111111111111111111111111111111111 refs/heads/feature 2222222222222222222222222222222222222222\n',
|
||||
});
|
||||
const featurePush = spawnHook(
|
||||
'refs/heads/feature 1111111111111111111111111111111111111111 refs/heads/feature 2222222222222222222222222222222222222222\n',
|
||||
);
|
||||
assert.equal(featurePush.status, 0, featurePush.stderr);
|
||||
assert.equal(readFileOrEmpty(npmLog), '');
|
||||
|
||||
const masterPush = spawnSync('bash', [hook, 'origin', 'example.invalid'], {
|
||||
cwd: repoRoot,
|
||||
encoding: 'utf8',
|
||||
env,
|
||||
input:
|
||||
'refs/heads/master 1111111111111111111111111111111111111111 refs/heads/master 2222222222222222222222222222222222222222\n',
|
||||
});
|
||||
const masterPush = spawnHook(
|
||||
`refs/heads/master ${localSha} refs/heads/master 2222222222222222222222222222222222222222\n`,
|
||||
);
|
||||
assert.equal(masterPush.status, 0, masterPush.stderr);
|
||||
assert.equal(
|
||||
readFileSync(npmLog, 'utf8'),
|
||||
'run check:repository-ci -- 2222222222222222222222222222222222222222 1111111111111111111111111111111111111111\n',
|
||||
`run check:repository-ci -- 2222222222222222222222222222222222222222 ${localSha}\n`,
|
||||
);
|
||||
} finally {
|
||||
rmSync(tempDir, { force: true, recursive: true });
|
||||
@@ -254,6 +274,14 @@ function readFileOrEmpty(path) {
|
||||
}
|
||||
}
|
||||
|
||||
function toBashPath(path) {
|
||||
const windowsDrive = /^([A-Za-z]):[\\/](.*)$/u.exec(path);
|
||||
if (windowsDrive) {
|
||||
return `/mnt/${windowsDrive[1].toLowerCase()}/${windowsDrive[2].replaceAll('\\', '/')}`;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
function git(cwd, ...args) {
|
||||
return execFileSync('git', args, { cwd, encoding: 'utf8' });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user