Assume merged diffs are squashed and diff against parent (#446)

This commit is contained in:
Louis Knight-Webb
2025-08-11 16:27:12 +01:00
committed by GitHub
parent 9130ac46fd
commit 7ed537d6d7
2 changed files with 21 additions and 20 deletions

View File

@@ -462,14 +462,12 @@ impl LocalContainerService {
&self,
project_repo_path: &Path,
merge_commit_id: &str,
base_branch: &str,
) -> Result<futures::stream::BoxStream<'static, Result<Event, std::io::Error>>, ContainerError>
{
let diffs = self.git().get_diffs(
DiffTarget::Commit {
repo_path: project_repo_path,
commit_sha: merge_commit_id,
base_branch,
},
None,
)?;
@@ -481,6 +479,9 @@ impl LocalContainerService {
let event = LogMsg::JsonPatch(patch).to_sse_event();
Ok::<_, std::io::Error>(event)
}))
.chain(futures::stream::once(async {
Ok::<_, std::io::Error>(LogMsg::Finished.to_sse_event())
}))
.boxed();
Ok(stream)
@@ -847,11 +848,7 @@ impl ContainerService for LocalContainerService {
// Handle merged attempts (static diff)
if let Some(merge_commit_id) = &task_attempt.merge_commit {
return self.create_merged_diff_stream(
&project_repo_path,
merge_commit_id,
&task_attempt.base_branch,
);
return self.create_merged_diff_stream(&project_repo_path, merge_commit_id);
}
let task_branch = task_attempt

View File

@@ -73,7 +73,6 @@ pub enum DiffTarget<'p> {
Commit {
repo_path: &'p Path,
commit_sha: &'p str,
base_branch: &'p str,
},
}
@@ -253,39 +252,44 @@ impl GitService {
DiffTarget::Commit {
repo_path,
commit_sha,
base_branch,
} => {
let repo = self.open_repo(repo_path)?;
let base_tree = repo
.find_branch(base_branch, BranchType::Local)
.map_err(|_| GitServiceError::BranchNotFound(base_branch.to_string()))?
.get()
.peel_to_commit()?
.tree()?;
// Resolve commit and its baseline (the parent before the squash landed)
let commit_oid = git2::Oid::from_str(commit_sha).map_err(|_| {
GitServiceError::InvalidRepository(format!("Invalid commit SHA: {commit_sha}"))
})?;
let commit_tree = repo.find_commit(commit_oid)?.tree()?;
let commit = repo.find_commit(commit_oid)?;
let parent = commit.parent(0).map_err(|_| {
GitServiceError::InvalidRepository(
"Commit has no parent; cannot diff a squash merge without a baseline"
.into(),
)
})?;
let mut diff_opts = DiffOptions::new();
let parent_tree = parent.tree()?;
let commit_tree = commit.tree()?;
// Diff options
let mut diff_opts = git2::DiffOptions::new();
diff_opts.include_typechange(true);
// Add path filtering if specified
// Optional path filtering
if let Some(paths) = path_filter {
for path in paths {
diff_opts.pathspec(*path);
}
}
// Compute the diff parent -> commit
let mut diff = repo.diff_tree_to_tree(
Some(&base_tree),
Some(&parent_tree),
Some(&commit_tree),
Some(&mut diff_opts),
)?;
// Enable rename detection
let mut find_opts = DiffFindOptions::new();
let mut find_opts = git2::DiffFindOptions::new();
diff.find_similar(Some(&mut find_opts))?;
self.convert_diff_to_file_diffs(diff, &repo)