fix: git errors on startup / check
This commit is contained in:
@@ -392,6 +392,11 @@ export class GitEngine {
|
|||||||
return normalized.includes('no upstream branch') || normalized.includes('has no upstream branch');
|
return normalized.includes('no upstream branch') || normalized.includes('has no upstream branch');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isSpawnBadFileDescriptorError(message: string): boolean {
|
||||||
|
const normalized = message.toLowerCase();
|
||||||
|
return normalized.includes('spawn ebadf');
|
||||||
|
}
|
||||||
|
|
||||||
private async getCurrentBranchName(git: ReturnType<typeof simpleGit>): Promise<string | null> {
|
private async getCurrentBranchName(git: ReturnType<typeof simpleGit>): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
const status = await git.status();
|
const status = await git.status();
|
||||||
@@ -717,12 +722,11 @@ export class GitEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getHistory(projectPath: string, limit = 20): Promise<GitHistoryEntry[]> {
|
async getHistory(projectPath: string, limit = 20): Promise<GitHistoryEntry[]> {
|
||||||
const git = simpleGit(projectPath);
|
const git = this.createNonInteractiveGit(projectPath);
|
||||||
const status = await git.status();
|
const status = await git.status();
|
||||||
const localHistory = await git.log({ maxCount: limit });
|
const localHistory = await git.log({ maxCount: limit });
|
||||||
|
|
||||||
if (!status.tracking) {
|
const mapLocalHistory = (): GitHistoryEntry[] => localHistory.all.map((entry) => ({
|
||||||
return localHistory.all.map((entry) => ({
|
|
||||||
hash: entry.hash,
|
hash: entry.hash,
|
||||||
shortHash: entry.hash.slice(0, 7),
|
shortHash: entry.hash.slice(0, 7),
|
||||||
date: entry.date,
|
date: entry.date,
|
||||||
@@ -730,11 +734,24 @@ export class GitEngine {
|
|||||||
author: entry.author_name,
|
author: entry.author_name,
|
||||||
syncStatus: 'local-only',
|
syncStatus: 'local-only',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (!status.tracking) {
|
||||||
|
return mapLocalHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
const behindCount = typeof status.behind === 'number' ? status.behind : Number(status.behind ?? 0);
|
const behindCount = typeof status.behind === 'number' ? status.behind : Number(status.behind ?? 0);
|
||||||
const remoteHistoryLimit = Math.max(limit, limit + Math.max(behindCount, 0));
|
const remoteHistoryLimit = Math.max(limit, limit + Math.max(behindCount, 0));
|
||||||
const remoteHistory = await git.log([status.tracking, '--max-count', String(remoteHistoryLimit)]);
|
let remoteHistory;
|
||||||
|
|
||||||
|
try {
|
||||||
|
remoteHistory = await git.log([status.tracking, '--max-count', String(remoteHistoryLimit)]);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error ?? '');
|
||||||
|
if (this.isSpawnBadFileDescriptorError(message)) {
|
||||||
|
return mapLocalHistory();
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
type CommitLike = {
|
type CommitLike = {
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|||||||
@@ -434,6 +434,37 @@ describe('GitEngine', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fall back to local history when remote history lookup fails with spawn EBADF', async () => {
|
||||||
|
mockStatus.mockResolvedValue({ current: 'main', tracking: 'origin/main' });
|
||||||
|
mockLog
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
all: [
|
||||||
|
{
|
||||||
|
hash: 'abc123def456',
|
||||||
|
date: '2026-02-16T10:00:00.000Z',
|
||||||
|
message: 'feat: local commit',
|
||||||
|
author_name: 'Local Dev',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.mockRejectedValueOnce(new Error('Error: spawn EBADF'));
|
||||||
|
|
||||||
|
const result = await gitEngine.getHistory('/tmp/project', 20);
|
||||||
|
|
||||||
|
expect(mockLog).toHaveBeenNthCalledWith(1, { maxCount: 20 });
|
||||||
|
expect(mockLog).toHaveBeenNthCalledWith(2, ['origin/main', '--max-count', '20']);
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
hash: 'abc123def456',
|
||||||
|
shortHash: 'abc123d',
|
||||||
|
date: '2026-02-16T10:00:00.000Z',
|
||||||
|
subject: 'feat: local commit',
|
||||||
|
author: 'Local Dev',
|
||||||
|
syncStatus: 'local-only',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getFileHistory', () => {
|
describe('getFileHistory', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user