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

View File

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

View File

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

View File

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

View File

@@ -124,7 +124,7 @@ contentOmitted: boolean,
/** /**
* Optional precomputed stats for omitted content * 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"; export type DiffChangeKind = "added" | "deleted" | "modified" | "renamed" | "copied" | "permissionChange";