Skip to content

Commit 6eba875

Browse files
committed
worktree: faster refresh + handle new staged files
1 parent cb781ff commit 6eba875

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

packages/desktop/src/features/git/DiffManager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ export class GitDiffManager {
332332
argv: ['git', 'cat-file', '-e', object],
333333
op: 'read',
334334
recordTimeline: false,
335+
throwOnError: false,
335336
meta: { source: 'gitDiff', operation: 'cat-file-exists', object },
336337
timeoutMs: 15_000,
337338
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { describe, it, expect, vi } from 'vitest';
2+
import { GitDiffManager } from '../DiffManager';
3+
4+
describe('GitDiffManager - new file detection', () => {
5+
it('does not throw when HEAD:path is missing for staged added file', async () => {
6+
const gitExecutor = {
7+
run: vi.fn(),
8+
} as any;
9+
10+
const manager = new GitDiffManager(gitExecutor);
11+
12+
// status-groups (porcelain) => staged added file
13+
vi.mocked(gitExecutor.run).mockResolvedValueOnce({
14+
exitCode: 0,
15+
stdout: 'A dd.txt\n',
16+
stderr: '',
17+
});
18+
19+
// numstat-staged
20+
vi.mocked(gitExecutor.run).mockResolvedValueOnce({
21+
exitCode: 0,
22+
stdout: '1\t0\tdd.txt\n',
23+
stderr: '',
24+
});
25+
26+
// numstat-unstaged
27+
vi.mocked(gitExecutor.run).mockResolvedValueOnce({
28+
exitCode: 0,
29+
stdout: '',
30+
stderr: '',
31+
});
32+
33+
// cat-file-exists HEAD:dd.txt should fail but must not throw
34+
vi.mocked(gitExecutor.run).mockResolvedValueOnce({
35+
exitCode: 128,
36+
stdout: '',
37+
stderr: "fatal: path 'dd.txt' exists on disk, but not in 'HEAD'\n",
38+
});
39+
40+
const groups = await manager.getWorkingTreeGroups('/repo', 's1');
41+
expect(groups.staged).toHaveLength(1);
42+
expect(groups.staged[0]).toMatchObject({ path: 'dd.txt', type: 'added', isNew: true });
43+
});
44+
});
45+

packages/ui/src/components/layout/RightPanel.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ export const RightPanel: React.FC<RightPanelProps> = React.memo(({
700700
if (selectedIsUncommitted) {
701701
fetchFiles();
702702
}
703-
}, 650);
703+
}, 200);
704704
}, [session.id, fetchCommits, fetchFiles, selectedIsUncommitted]);
705705

706706
// Refresh once after a run completes (running -> waiting/error/etc).
@@ -720,8 +720,12 @@ export const RightPanel: React.FC<RightPanelProps> = React.memo(({
720720
// Only refresh on stable, state-changing signals. `state`/`lastChecked` can churn even when nothing
721721
// meaningful changed (e.g. transient errors or polling), which would cause refresh loops.
722722
const gitSig = [
723+
String(session.gitStatus?.state ?? ''),
723724
String(Number(session.gitStatus?.ahead ?? 0)),
724725
String(Number(session.gitStatus?.behind ?? 0)),
726+
String(Number(session.gitStatus?.filesChanged ?? 0)),
727+
String(Number(session.gitStatus?.additions ?? 0)),
728+
String(Number(session.gitStatus?.deletions ?? 0)),
725729
String(Boolean(session.gitStatus?.hasUncommittedChanges)),
726730
String(Boolean(session.gitStatus?.hasUntrackedFiles)),
727731
].join('|');

0 commit comments

Comments
 (0)