per-repo diff stats (#1961)

This commit is contained in:
Gabriel Gordon-Hall
2026-01-13 09:32:16 +00:00
committed by GitHub
parent 118650872b
commit 57e802e2c9
5 changed files with 27 additions and 6 deletions

View File

@@ -277,6 +277,7 @@ impl DiffStreamManager {
if let Some(new) = diff.new_path {
diff.new_path = Some(prefix_path(new, self.args.path_prefix.as_deref()));
}
diff.repo_id = Some(self.args.repo_id);
let patch =
ConversationPatch::add_diff(escape_json_pointer_segment(&prefixed_entry), diff);
@@ -307,6 +308,7 @@ impl DiffStreamManager {
let known_paths = self.known_paths.clone();
let stats_only = self.args.stats_only;
let prefix = self.args.path_prefix.clone();
let repo_id = self.args.repo_id;
let messages = tokio::task::spawn_blocking(move || {
process_file_changes(
@@ -319,6 +321,7 @@ impl DiffStreamManager {
&known_paths,
stats_only,
prefix.as_deref(),
repo_id,
)
})
.await??;
@@ -459,6 +462,7 @@ fn process_file_changes(
known_paths: &Arc<std::sync::RwLock<HashSet<String>>>,
stats_only: bool,
path_prefix: Option<&str>,
repo_id: Uuid,
) -> Result<Vec<LogMsg>, DiffStreamError> {
let path_filter: Vec<&str> = changed_paths.iter().map(|s| s.as_str()).collect();
@@ -499,6 +503,7 @@ fn process_file_changes(
if let Some(new) = diff.new_path {
diff.new_path = Some(prefix_path(new, path_prefix));
}
diff.repo_id = Some(repo_id);
let patch =
ConversationPatch::add_diff(escape_json_pointer_segment(&prefixed_entry_index), diff);

View File

@@ -535,6 +535,7 @@ impl GitService {
content_omitted,
additions,
deletions,
repo_id: None,
});
delta_index += 1;
@@ -756,6 +757,7 @@ impl GitService {
content_omitted,
additions,
deletions,
repo_id: None,
}
}

View File

@@ -4,6 +4,7 @@ use git2::{DiffOptions, Patch};
use serde::{Deserialize, Serialize};
use similar::TextDiff;
use ts_rs::TS;
use uuid::Uuid;
// Structs compatable with props: https://github.com/MrWangJustToDo/git-diff-view
@@ -28,6 +29,7 @@ pub struct Diff {
/// Optional precomputed stats for omitted content
pub additions: Option<usize>,
pub deletions: Option<usize>,
pub repo_id: Option<Uuid>,
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]

View File

@@ -342,7 +342,7 @@ export function WorkspacesLayout() {
[renameBranch]
);
// Compute diff stats from real diffs
// Compute aggregate diff stats from real diffs (for WorkspacesMainContainer)
const diffStats = useMemo(
() => ({
filesChanged: realDiffs.length,
@@ -380,21 +380,33 @@ export function WorkspacesLayout() {
}
}
// Compute per-repo diff stats
const repoDiffs = realDiffs.filter((d) => d.repoId === repo.id);
const filesChanged = repoDiffs.length;
const linesAdded = repoDiffs.reduce(
(sum, d) => sum + (d.additions ?? 0),
0
);
const linesRemoved = repoDiffs.reduce(
(sum, d) => sum + (d.deletions ?? 0),
0
);
return {
id: repo.id,
name: repo.display_name || repo.name,
targetBranch: repo.target_branch || 'main',
commitsAhead: repoStatus?.commits_ahead ?? 0,
remoteCommitsAhead: repoStatus?.remote_commits_ahead ?? 0,
filesChanged: diffStats.filesChanged,
linesAdded: diffStats.linesAdded,
linesRemoved: diffStats.linesRemoved,
filesChanged,
linesAdded,
linesRemoved,
prNumber,
prUrl,
prStatus,
};
}),
[repos, diffStats, branchStatus]
[repos, realDiffs, branchStatus]
);
// Content for logs panel (either process logs or tool content)

View File

@@ -124,7 +124,7 @@ contentOmitted: boolean,
/**
* Optional precomputed stats for omitted content
*/
additions: number | null, deletions: number | null, };
additions: number | null, deletions: number | null, repoId: string | null, };
export type DiffChangeKind = "added" | "deleted" | "modified" | "renamed" | "copied" | "permissionChange";