Restrict orphan worktree cleanup

This commit is contained in:
Bohdan Triapitsyn
2026-06-12 18:33:22 +03:00
parent 106b31a407
commit ea3bb103eb
2 changed files with 46 additions and 0 deletions
@@ -9,6 +9,7 @@ import {
checkoutCommit,
cherryPick,
getStatus,
removeWorktree,
resetToCommit,
resolveBaseRefForLog,
revertCommit,
@@ -139,6 +140,46 @@ describe('getStatus', () => {
});
});
// ---------------------------------------------------------------------------
// removeWorktree
// ---------------------------------------------------------------------------
describe('removeWorktree', () => {
it('refuses orphan cleanup outside the managed worktree root', async () => {
if (!canRunGit()) return;
const previousXdgDataHome = process.env.XDG_DATA_HOME;
const dataHome = createTempDir();
process.env.XDG_DATA_HOME = dataHome;
try {
const repo = createTempDir();
const sentinel = createTempDir();
const canary = path.join(sentinel, 'canary.txt');
runGit(repo, ['init', '-b', 'main']);
runGit(repo, ['config', 'user.email', 'test@example.com']);
runGit(repo, ['config', 'user.name', 'Test User']);
fs.writeFileSync(path.join(repo, 'README.md'), '# Test\n');
runGit(repo, ['add', 'README.md']);
runGit(repo, ['commit', '-m', 'Initial commit']);
fs.writeFileSync(canary, 'sentinel');
await expect(removeWorktree(repo, {
directory: sentinel,
deleteLocalBranch: false,
})).rejects.toThrow('Cannot remove unmanaged worktree directory');
expect(fs.existsSync(canary)).toBe(true);
} finally {
if (previousXdgDataHome === undefined) {
delete process.env.XDG_DATA_HOME;
} else {
process.env.XDG_DATA_HOME = previousXdgDataHome;
}
}
});
});
// ---------------------------------------------------------------------------
// checkoutCommit
// ---------------------------------------------------------------------------