mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Guard non-standard default branches like conventional ones
Cursor Bugbot: sitting on a non-standard default such as trunk (the origin/HEAD target) still ran candidate selection, where develop or main could win and produce an integration-vs-integration diff. The guard now treats the remote default branch as an integration branch alongside the conventional names. Failing-first test: on trunk with a develop branch present, the scope stays the working tree. Prepared with AI assistance (Claude Code), directed by @pbakaus. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
e82653965c
commit
afb5d9a479
@@ -112,13 +112,15 @@ function gitSignals(cwd) {
|
||||
// signal may override that: an origin/HEAD or upstream naming a DIFFERENT
|
||||
// integration branch (sitting on develop while the remote default is
|
||||
// main) would produce exactly the integration-vs-integration divergence
|
||||
// this detection exists to prevent.
|
||||
const onIntegrationBranch = conventional.includes(branch);
|
||||
// this detection exists to prevent. "Integration branch" means a
|
||||
// conventional name OR the remote's default branch, so a non-standard
|
||||
// default like trunk is guarded the same way.
|
||||
const remoteHead = splitRemoteRef(run(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']));
|
||||
const onIntegrationBranch = conventional.includes(branch) || branch === remoteHead?.name;
|
||||
let base = null;
|
||||
let baseRev = null;
|
||||
if (!onIntegrationBranch) {
|
||||
const upstream = asUpstream(run(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}']));
|
||||
const remoteHead = splitRemoteRef(run(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']));
|
||||
const candidates = [];
|
||||
const seen = new Set();
|
||||
const addCandidate = (name, revs) => {
|
||||
|
||||
@@ -376,6 +376,26 @@ describe('gatherSignals', () => {
|
||||
assert.deepEqual(s.git.changedFiles, ['src/Hero.tsx']);
|
||||
});
|
||||
|
||||
it('sitting on a non-standard default branch keeps the working-tree scope (#302)', async () => {
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
const git = (...args) => execFileSync('git', args, { cwd: scratch, stdio: 'ignore' });
|
||||
git('init', '-q', '-b', 'trunk');
|
||||
git('config', 'user.email', 't@example.com');
|
||||
git('config', 'user.name', 'Test');
|
||||
write('src/App.tsx', 'export default 1;\n');
|
||||
git('add', '.');
|
||||
git('commit', '-qm', 'init');
|
||||
git('branch', '-q', 'develop'); // a conventional name also exists
|
||||
git('update-ref', 'refs/remotes/origin/trunk', 'HEAD');
|
||||
git('symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/trunk');
|
||||
write('src/App.tsx', 'export default 2;\n'); // dirty on trunk
|
||||
const s = await gatherSignals(scratch);
|
||||
// trunk IS the integration branch (origin/HEAD says so); develop must
|
||||
// not win the candidate scan and produce a trunk-vs-develop diff.
|
||||
assert.equal(s.git.base, null);
|
||||
assert.deepEqual(s.git.changedFiles, ['src/App.tsx']);
|
||||
});
|
||||
|
||||
it('never diffs one integration branch against another (#302)', async () => {
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
const git = (...args) => execFileSync('git', args, { cwd: scratch, stdio: 'ignore' });
|
||||
|
||||
Reference in New Issue
Block a user