fix(git): use local-first base ref resolution in getLog, port to VS Code (#1284)
* chore: add .worktrees/ to gitignore for worktree workflow * fix: resolve remote-tracking base ref in getLog for PR description generation getLog was calling git log <base>..<head> with a bare branch name that often doesn't exist locally (e.g. main when only origin/main is present), causing a fatal 'unknown revision' error and HTTP 500. Apply the same origin/<base> resolution already used in getRangeDiff and getRangeFiles: check refs/remotes/origin/<base> first and prefer that ref if it exists. Also fix getGitLog in gitApiHttp.ts to read the JSON error body on failure instead of falling back to response.statusText, so the actual git error message surfaces in the toast instead of 'Internal Server Error'. * fix(git): use local-first ref resolution in getLog and port to VS Code - Replace unconditional origin/<from> preference in getLog() with a local-first fallback: prefer the local ref, only use origin/<from> when the local ref cannot be resolved, and pass through unchanged when neither resolves so git surfaces a meaningful error. - Extract the logic into an exported resolveBaseRefForLog(from, checkRef) helper so it is unit-testable without a real git repo. - Add service.test.js with 6 cases covering local-wins, origin-fallback, neither-exists passthrough, and falsy/empty inputs. - Port the same local-first resolution to packages/vscode/src/gitService.ts getGitLog() to close the cross-runtime parity gap; also handles from-only ranges as from..HEAD, matching the web service contract. * fix(vscode): add missing to-only range branch in getGitLog When only 'to' is supplied (no 'from'), the web service appends it as a positional git-log argument. The VS Code port was missing this branch and silently returned unbounded history instead. Adds the else-if to restore full cross-runtime parity. * fix(vscode): surface git log errors --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
77b4f27053
commit
fa8fac2590
@@ -2515,6 +2515,34 @@ export interface GitLogEntry {
|
||||
deletions: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a log base ref using local-first semantics (mirrors web service.js).
|
||||
*
|
||||
* - Returns undefined when `from` is falsy/whitespace.
|
||||
* - Returns `from` unchanged when the local ref resolves.
|
||||
* - Returns `origin/<from>` when local is absent but the remote-tracking ref exists.
|
||||
* - Returns `from` unchanged when neither resolves (lets git surface the error).
|
||||
*/
|
||||
async function resolveBaseRefForLog(
|
||||
from: string | undefined,
|
||||
directory: string
|
||||
): Promise<string | undefined> {
|
||||
const normalized = typeof from === 'string' ? from.trim() : undefined;
|
||||
if (!normalized) return undefined;
|
||||
|
||||
const checkRef = async (ref: string): Promise<boolean> => {
|
||||
const result = await execGit(['rev-parse', '--verify', ref], directory);
|
||||
return result.exitCode === 0 && Boolean(result.stdout.trim());
|
||||
};
|
||||
|
||||
if (await checkRef(normalized)) return normalized;
|
||||
|
||||
const originRef = `refs/remotes/origin/${normalized}`;
|
||||
if (await checkRef(originRef)) return `origin/${normalized}`;
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git log
|
||||
*/
|
||||
@@ -2523,6 +2551,11 @@ export async function getGitLog(
|
||||
options?: { maxCount?: number; from?: string; to?: string; file?: string }
|
||||
): Promise<{ all: GitLogEntry[]; latest: GitLogEntry | null; total: number }> {
|
||||
const maxCount = options?.maxCount || 50;
|
||||
|
||||
// Prefer the local ref; fall back to origin/<from> only when the local ref
|
||||
// cannot be resolved (e.g. user has never checked out the base branch).
|
||||
const resolvedFrom = await resolveBaseRefForLog(options?.from, directory);
|
||||
|
||||
const args = [
|
||||
'log',
|
||||
`--max-count=${maxCount}`,
|
||||
@@ -2530,8 +2563,12 @@ export async function getGitLog(
|
||||
'--shortstat',
|
||||
];
|
||||
|
||||
if (options?.from && options?.to) {
|
||||
args.push(`${options.from}..${options.to}`);
|
||||
if (resolvedFrom && options?.to) {
|
||||
args.push(`${resolvedFrom}..${options.to}`);
|
||||
} else if (resolvedFrom) {
|
||||
args.push(`${resolvedFrom}..HEAD`);
|
||||
} else if (options?.to) {
|
||||
args.push(options.to);
|
||||
}
|
||||
|
||||
if (options?.file) {
|
||||
@@ -2541,7 +2578,7 @@ export async function getGitLog(
|
||||
const result = await execGit(args, directory);
|
||||
|
||||
if (result.exitCode !== 0) {
|
||||
return { all: [], latest: null, total: 0 };
|
||||
throw new Error(result.stderr.trim() || result.stdout.trim() || 'Failed to get git log');
|
||||
}
|
||||
|
||||
const entries: GitLogEntry[] = [];
|
||||
|
||||
Reference in New Issue
Block a user