Assume merged diffs are squashed and diff against parent (#446)
This commit is contained in:
committed by
GitHub
parent
9130ac46fd
commit
7ed537d6d7
@@ -462,14 +462,12 @@ impl LocalContainerService {
|
|||||||
&self,
|
&self,
|
||||||
project_repo_path: &Path,
|
project_repo_path: &Path,
|
||||||
merge_commit_id: &str,
|
merge_commit_id: &str,
|
||||||
base_branch: &str,
|
|
||||||
) -> Result<futures::stream::BoxStream<'static, Result<Event, std::io::Error>>, ContainerError>
|
) -> Result<futures::stream::BoxStream<'static, Result<Event, std::io::Error>>, ContainerError>
|
||||||
{
|
{
|
||||||
let diffs = self.git().get_diffs(
|
let diffs = self.git().get_diffs(
|
||||||
DiffTarget::Commit {
|
DiffTarget::Commit {
|
||||||
repo_path: project_repo_path,
|
repo_path: project_repo_path,
|
||||||
commit_sha: merge_commit_id,
|
commit_sha: merge_commit_id,
|
||||||
base_branch,
|
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
@@ -481,6 +479,9 @@ impl LocalContainerService {
|
|||||||
let event = LogMsg::JsonPatch(patch).to_sse_event();
|
let event = LogMsg::JsonPatch(patch).to_sse_event();
|
||||||
Ok::<_, std::io::Error>(event)
|
Ok::<_, std::io::Error>(event)
|
||||||
}))
|
}))
|
||||||
|
.chain(futures::stream::once(async {
|
||||||
|
Ok::<_, std::io::Error>(LogMsg::Finished.to_sse_event())
|
||||||
|
}))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
Ok(stream)
|
Ok(stream)
|
||||||
@@ -847,11 +848,7 @@ impl ContainerService for LocalContainerService {
|
|||||||
|
|
||||||
// Handle merged attempts (static diff)
|
// Handle merged attempts (static diff)
|
||||||
if let Some(merge_commit_id) = &task_attempt.merge_commit {
|
if let Some(merge_commit_id) = &task_attempt.merge_commit {
|
||||||
return self.create_merged_diff_stream(
|
return self.create_merged_diff_stream(&project_repo_path, merge_commit_id);
|
||||||
&project_repo_path,
|
|
||||||
merge_commit_id,
|
|
||||||
&task_attempt.base_branch,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let task_branch = task_attempt
|
let task_branch = task_attempt
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ pub enum DiffTarget<'p> {
|
|||||||
Commit {
|
Commit {
|
||||||
repo_path: &'p Path,
|
repo_path: &'p Path,
|
||||||
commit_sha: &'p str,
|
commit_sha: &'p str,
|
||||||
base_branch: &'p str,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,39 +252,44 @@ impl GitService {
|
|||||||
DiffTarget::Commit {
|
DiffTarget::Commit {
|
||||||
repo_path,
|
repo_path,
|
||||||
commit_sha,
|
commit_sha,
|
||||||
base_branch,
|
|
||||||
} => {
|
} => {
|
||||||
let repo = self.open_repo(repo_path)?;
|
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(|_| {
|
let commit_oid = git2::Oid::from_str(commit_sha).map_err(|_| {
|
||||||
GitServiceError::InvalidRepository(format!("Invalid commit SHA: {commit_sha}"))
|
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);
|
diff_opts.include_typechange(true);
|
||||||
|
|
||||||
// Add path filtering if specified
|
// Optional path filtering
|
||||||
if let Some(paths) = path_filter {
|
if let Some(paths) = path_filter {
|
||||||
for path in paths {
|
for path in paths {
|
||||||
diff_opts.pathspec(*path);
|
diff_opts.pathspec(*path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute the diff parent -> commit
|
||||||
let mut diff = repo.diff_tree_to_tree(
|
let mut diff = repo.diff_tree_to_tree(
|
||||||
Some(&base_tree),
|
Some(&parent_tree),
|
||||||
Some(&commit_tree),
|
Some(&commit_tree),
|
||||||
Some(&mut diff_opts),
|
Some(&mut diff_opts),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Enable rename detection
|
// Enable rename detection
|
||||||
let mut find_opts = DiffFindOptions::new();
|
let mut find_opts = git2::DiffFindOptions::new();
|
||||||
diff.find_similar(Some(&mut find_opts))?;
|
diff.find_similar(Some(&mut find_opts))?;
|
||||||
|
|
||||||
self.convert_diff_to_file_diffs(diff, &repo)
|
self.convert_diff_to_file_diffs(diff, &repo)
|
||||||
|
|||||||
Reference in New Issue
Block a user