fix: tree-only merge-base diff in the Version Gate; ls-tree --full-tree in both history readers

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-31 18:33:21 +00:00
1 parent de5691d952
commit ff14f14c63
4 files changed
+10 -4

No files matched your search

+2 -2
View File
@@ -6,7 +6,7 @@
#
# Usage: history-read.sh <ref> <path> [--absent <text>]
#
# Existence comes from the ref's tree (`git ls-tree`, local data only). A path
# Existence comes from the ref's tree (`git ls-tree --full-tree`, local data only). A path
# the tree does not list is absent: prints <text> (default: nothing), exits 0.
# A listed path is read with `git show`, tried 3 times in a partial clone
# (only a fetch can recover) and once otherwise, waiting
@@ -30,7 +30,7 @@ fail() {
exit 1
}
listed=$(git ls-tree "$ref" -- "$file" 2>"$err") || fail "git ls-tree failed: $(head -n 1 "$err")"
listed=$(git ls-tree --full-tree "$ref" -- "$file" 2>"$err") || fail "git ls-tree failed: $(head -n 1 "$err")"
if [ -z "$listed" ]; then
printf '%s' "$absent"
exit 0
+1 -1
View File
@@ -25,7 +25,7 @@ export function readHistoryFile(repoRoot: string, ref: string, file: string): st
return new HistoryReadError(`cannot read ${file} at ${ref}. ${cause} (${version}). Fix: see docs/troubleshooting.md#history-read-failed (HISTORY_READ_FAILED)`);
};
const firstLine = (r: ReturnType<typeof git>) => (r.stderr ?? '').split('\n')[0] || r.error?.message || `exit ${r.status}`;
const listed = git(['ls-tree', ref, '--', file]);
const listed = git(['ls-tree', '--full-tree', ref, '--', file]);
if (listed.status !== 0) throw fail(`git ls-tree failed: ${firstLine(listed)}`);
if (!listed.stdout.trim()) return null;
const promisors = (git(['config', '--get-regexp', '^(remote\\..+\\.promisor|extensions\\.partialclone)$']).stdout ?? '').split('\n');
+3 -1
View File
@@ -109,7 +109,9 @@ function classify(o: { repoRoot: string; baseRef: string; head: string; author?:
const npmVersion = (rev: string) => { const text = show(rev, 'package.json'); try { return JSON.parse(text ?? '{}').version ?? null; } catch { return null; } };
if (policy.bump === 'never') return show(mergeBase, 'VERSION') === show(o.head, 'VERSION') && npmVersion(mergeBase) === npmVersion(o.head) ? { kind: 'unstamped', entry: 'kept' } : { kind: 'off' };
const changed = (git(o.repoRoot, ['diff', '--name-only', mergeBase, o.head]) ?? '').split('\n').filter(Boolean);
const diff = git(o.repoRoot, ['diff', '--no-renames', '--name-only', mergeBase, o.head]);
if (diff === null) return { kind: 'invalid', reason: `cannot list the files ${o.head} changes since its merge base ${mergeBase.slice(0, 12)}. Fix: see docs/troubleshooting.md#history-read-failed (HISTORY_READ_FAILED)` };
const changed = diff.split('\n').filter(Boolean);
const releaseOutputs: string[] = Array.isArray(policy.release_outputs) ? policy.release_outputs : [];
// touched: what marks the head as stamped (the labels only feed the length check below)
const touched: string[] = changed.filter(f => f === 'VERSION');
+4
View File
@@ -108,6 +108,10 @@ describe('history-read.sh and lib/history-read.ts on a blobless clone', () => {
expect(r.stderr).toBe('');
expect([r.status, r.stdout]).toEqual([0, '1.0.0.1\n']);
expect(readHistoryFile(fx.clone, fx.one, 'VERSION')).toBe('1.0.0.0\n');
const sub = path.join(fx.clone, 'sub');
fs.mkdirSync(sub);
expect(helper(sub, fx.one, POLICY)).toMatchObject({ status: 0, stdout: JSON.stringify({ bump: 'patch' }) });
expect(readHistoryFile(sub, fx.one, POLICY)).toBe(JSON.stringify({ bump: 'patch' }));
});
test('a path the tree does not list is absent even with the remote gone', () => {