Skip to content

Commit e30c5b2

Browse files
authored
Merge pull request #12792 from gitbutlerapp/copilot/fix-issue-12791
Correct octopus merge conflict message to show both tree IDs
2 parents 17771b0 + ec9042a commit e30c5b2

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

.mailmap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<stron@me.com> <35891811+estib-vega@users.noreply.github.com>
22
Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
3-
Byron <sebastian.thiel@icloud.com> Sebastian Thiel <sebastian.thiel@icloud.com>
3+
Byron <sebastian.thiel@icloud.com> Sebastian Thiel <sebastian.thiel@icloud.com> <63622+Byron@users.noreply.github.com>
4+
Copilot <198982749+Copilot@users.noreply.github.com> copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

crates/but-rebase/src/merge.rs

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,7 @@ pub fn octopus(
6868
if merge.has_unresolved_conflicts(unresolved) {
6969
return Err(anyhow!(
7070
"Encountered conflict when merging tree {tree_to_merge}{details}",
71-
details = if successfully_merged.len() > 1 {
72-
format!(
73-
" after the trees {} were merged successfully",
74-
successfully_merged
75-
.iter()
76-
.map(|id| id.to_string())
77-
.collect::<Vec<_>>()
78-
.join(", ")
79-
)
80-
} else {
81-
format!(" and tree {tree_to_merge}")
82-
}
71+
details = merge_conflict_details(&successfully_merged)
8372
)
8473
.context(ConflictErrorContext {
8574
paths: merge
@@ -114,6 +103,25 @@ pub fn octopus(
114103
}
115104
}
116105

106+
fn merge_conflict_details(successfully_merged: &[gix::ObjectId]) -> String {
107+
if successfully_merged.len() > 1 {
108+
format!(
109+
" after the trees {} were merged successfully",
110+
successfully_merged
111+
.iter()
112+
.map(|id| id.to_string())
113+
.collect::<Vec<_>>()
114+
.join(", ")
115+
)
116+
} else {
117+
// Callers seed this list with the initial `ours` tree before any merge happens,
118+
// but we return an empty suffix defensively if the invariant is broken.
119+
successfully_merged
120+
.first()
121+
.map_or_else(String::new, |tree| format!(" and tree {tree}"))
122+
}
123+
}
124+
117125
/// A type that can be retrieved as an `anyhow` context to see if the rebase failed due to merge conflicts.
118126
#[derive(Debug, Clone)]
119127
pub struct ConflictErrorContext {
@@ -134,3 +142,37 @@ impl std::fmt::Display for ConflictErrorContext {
134142
)
135143
}
136144
}
145+
146+
#[cfg(test)]
147+
mod test_merge_confict_details {
148+
use std::str::FromStr;
149+
150+
use super::merge_conflict_details;
151+
152+
#[test]
153+
fn single_merged_tree() {
154+
let successfully_merged_tree =
155+
gix::ObjectId::from_str("1111111111111111111111111111111111111111").unwrap();
156+
157+
assert_eq!(
158+
merge_conflict_details(&[successfully_merged_tree]),
159+
format!(" and tree {successfully_merged_tree}")
160+
);
161+
}
162+
163+
#[test]
164+
fn two_merged_trees() {
165+
let first = gix::ObjectId::from_str("1111111111111111111111111111111111111111").unwrap();
166+
let second = gix::ObjectId::from_str("2222222222222222222222222222222222222222").unwrap();
167+
168+
assert_eq!(
169+
merge_conflict_details(&[first, second]),
170+
format!(" after the trees {first}, {second} were merged successfully")
171+
);
172+
}
173+
174+
#[test]
175+
fn empty_merged_trees() {
176+
assert_eq!(merge_conflict_details(&[]), "");
177+
}
178+
}

0 commit comments

Comments
 (0)