mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 00:48:18 +00:00
installHelper's "already current" fast path ran chmodSync(helperPath, 0o755) unconditionally, before the dryRun check further down — so `gbrain sources harden --dry-run` mutated the helper's permissions even though dry-run is documented as a pure preview. This is the 5th instance of the #3594 class (see #3692 for the sibling fix to the step-1 pull, same function). Gate the chmod with `if (!dryRun)`, mirroring the guard pattern already used in installLocalHook's own "already current" branch. Non-dry-run behavior is unchanged. Adds a regression pair to test/brain-repo-durability.serial.test.ts: one asserting dry-run leaves a drifted-permission helper untouched, and a control asserting the real run still restores the exec bit.
This commit is contained in:
@@ -394,8 +394,9 @@ function installHelper(repoPath: string, dryRun: boolean): { status: StepStatus;
|
||||
const helperPath = join(repoPath, HELPER_REL);
|
||||
const script = renderCommitPushHelper();
|
||||
if (existsSync(helperPath) && readFileSync(helperPath, 'utf-8') === script) {
|
||||
// Ensure exec bit even when content is current.
|
||||
try { chmodSync(helperPath, 0o755); } catch { /* */ }
|
||||
// Ensure exec bit even when content is current — but not in dry-run: a
|
||||
// preview must not mutate permissions (#3736).
|
||||
if (!dryRun) { try { chmodSync(helperPath, 0o755); } catch { /* */ } }
|
||||
return { status: 'ok', detail: `${HELPER_REL} already current` };
|
||||
}
|
||||
if (dryRun) return { status: 'fixed', detail: `would write ${HELPER_REL} (dry-run)` };
|
||||
|
||||
@@ -169,6 +169,22 @@ describe('hardenBrainRepo', () => {
|
||||
expect(commitCount(work)).toBe(before);
|
||||
expect(existsSync(join(work, 'scripts', 'brain-commit-push.sh'))).toBe(false);
|
||||
});
|
||||
|
||||
test('dry-run does not chmod an already-current helper (#3736)', async () => {
|
||||
await harden(); // real run installs scripts/brain-commit-push.sh at 0o755
|
||||
const helperPath = join(work, 'scripts', 'brain-commit-push.sh');
|
||||
chmodSync(helperPath, 0o644); // simulate perms drifting away from +x, content unchanged
|
||||
await harden({ dryRun: true });
|
||||
expect(statSync(helperPath).mode & 0o777).toBe(0o644); // untouched — preview must not mutate
|
||||
});
|
||||
|
||||
test('non-dry-run restores the exec bit on an already-current helper', async () => {
|
||||
await harden();
|
||||
const helperPath = join(work, 'scripts', 'brain-commit-push.sh');
|
||||
chmodSync(helperPath, 0o644);
|
||||
await harden();
|
||||
expect(statSync(helperPath).mode & 0o111).toBeTruthy(); // exec bit restored
|
||||
});
|
||||
});
|
||||
|
||||
describe('unhardenBrainRepo', () => {
|
||||
|
||||
Reference in New Issue
Block a user