Release ForgeFlow 0.6.0
This commit is contained in:
@@ -178,3 +178,68 @@ test('stages a large Windows-sized partial selection through NUL-delimited stdin
|
||||
assert.equal(status.counts.staged, names.length);
|
||||
assert.equal(status.counts.unstaged, 0);
|
||||
});
|
||||
|
||||
|
||||
test('detects and removes a stale HEAD.lock while skipping Git object storage', async (t) => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'forgeflow-head-lock-'));
|
||||
t.after(() => fs.rm(root, { recursive: true, force: true }));
|
||||
await git(['init'], root);
|
||||
await git(['config', 'user.name', 'ForgeFlow Test'], root);
|
||||
await git(['config', 'user.email', 'forgeflow@example.invalid'], root);
|
||||
await fs.writeFile(path.join(root, 'README.md'), 'lock test\n');
|
||||
await git(['add', '.'], root);
|
||||
await git(['commit', '-m', 'Initial'], root);
|
||||
const headLock = path.join(root, '.git', 'HEAD.lock');
|
||||
const ignoredObjectLock = path.join(root, '.git', 'objects', 'fake.lock');
|
||||
await fs.writeFile(headLock, 'stale');
|
||||
await fs.writeFile(ignoredObjectLock, 'not a repository mutation lock');
|
||||
const old = new Date(Date.now() - 60_000);
|
||||
await fs.utimes(headLock, old, old);
|
||||
const service = new GitService();
|
||||
const report = await service.listGitLocks(root);
|
||||
assert.deepEqual(report.locks.map((item) => item.name), ['HEAD.lock']);
|
||||
const repaired = await service.repairStaleGitLocks(root, { minimumAgeMs: 0, allowWithoutProcessProbe: true });
|
||||
assert.equal(repaired.removed.length, 1);
|
||||
await assert.rejects(() => fs.stat(headLock), (error) => error.code === 'ENOENT');
|
||||
assert.ok(await fs.stat(ignoredObjectLock));
|
||||
});
|
||||
|
||||
test('repairs a diverged branch by creating a safety branch before resetting to upstream', async (t) => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'forgeflow-diverged-'));
|
||||
t.after(() => fs.rm(root, { recursive: true, force: true }));
|
||||
const remote = path.join(root, 'remote.git');
|
||||
const working = path.join(root, 'working');
|
||||
const other = path.join(root, 'other');
|
||||
await git(['init', '--bare', remote], root);
|
||||
await git(['clone', remote, working], root);
|
||||
await git(['config', 'user.name', 'ForgeFlow Test'], working);
|
||||
await git(['config', 'user.email', 'forgeflow@example.invalid'], working);
|
||||
await fs.writeFile(path.join(working, 'README.md'), 'initial\n');
|
||||
await git(['add', '.'], working);
|
||||
await git(['commit', '-m', 'Initial'], working);
|
||||
await git(['branch', '-M', 'main'], working);
|
||||
await git(['push', '-u', 'origin', 'main'], working);
|
||||
await git(['clone', remote, other], root);
|
||||
await git(['config', 'user.name', 'Other Test'], other);
|
||||
await git(['config', 'user.email', 'other@example.invalid'], other);
|
||||
await git(['checkout', 'main'], other);
|
||||
await fs.writeFile(path.join(other, 'remote.txt'), 'remote\n');
|
||||
await git(['add', '.'], other);
|
||||
await git(['commit', '-m', 'Remote commit'], other);
|
||||
await git(['push', 'origin', 'main'], other);
|
||||
await fs.writeFile(path.join(working, 'local.txt'), 'local\n');
|
||||
await git(['add', '.'], working);
|
||||
await git(['commit', '-m', 'Local commit'], working);
|
||||
const localBefore = (await git(['rev-parse', 'HEAD'], working)).stdout.trim();
|
||||
const service = new GitService();
|
||||
const scan = await service.reconcile(working);
|
||||
assert.equal(scan.status.branch.ahead, 1);
|
||||
assert.equal(scan.status.branch.behind, 1);
|
||||
assert.ok(scan.recommendations.some((item) => item.action === 'backup-reset'));
|
||||
const repaired = await service.repairSync(working, 'backup-reset');
|
||||
assert.match(repaired.backupBranch, /^forgeflow\/backup-main-/);
|
||||
assert.equal(repaired.status.branch.ahead, 0);
|
||||
assert.equal(repaired.status.branch.behind, 0);
|
||||
const backupSha = (await git(['rev-parse', repaired.backupBranch], working)).stdout.trim();
|
||||
assert.equal(backupSha, localBefore);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user