Skip to content

Commit ac252ba

Browse files
committed
tmp
1 parent 7186e44 commit ac252ba

File tree

1 file changed

+65
-41
lines changed

1 file changed

+65
-41
lines changed

crates/but-rebase/src/graph_rebase/rebase.rs

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,37 @@ use crate::{
66
ReferenceSpec,
77
cherry_pick::EmptyCommit,
88
cherry_pick_one,
9-
graph_rebase::{Editor, Step, StepGraph, StepGraphIndex},
9+
graph_rebase::{
10+
Editor, Step, StepGraph, StepGraphIndex,
11+
cherry_pick::{CherryPickOutcome, cherry_pick},
12+
},
1013
to_commit,
1114
};
12-
use anyhow::{Context, Result};
15+
use anyhow::{Context, Result, bail};
1316
use petgraph::visit::EdgeRef;
1417

15-
/// Represents the rebase output and the varying degrees of success it had.
16-
pub struct RebaseResult {
18+
/// Represents a successful rebase, and any valid, but potentially conflicting scenarios it had.
19+
#[derive(Debug, Clone)]
20+
pub struct SuccessfulRebase {
1721
references: Vec<ReferenceSpec>,
1822
commit_map: HashMap<gix::ObjectId, gix::ObjectId>,
1923
}
2024

25+
/// Represents the rebase output and the varying degrees of success it had.
26+
#[derive(Debug, Clone)]
27+
pub enum RebaseOutcome {
28+
/// The rebase
29+
Success(SuccessfulRebase),
30+
/// The graph rebase failed because we encountered a situation where we
31+
/// couldn't merge bases.
32+
///
33+
/// Holds the gix::ObjectId of the commit it failed to pick
34+
MergePickFailed(gix::ObjectId),
35+
}
36+
2137
impl Editor {
2238
/// Perform the rebase
23-
pub fn rebase(&self, repo: &gix::Repository) -> Result<RebaseResult> {
39+
pub fn rebase(&self, repo: &gix::Repository) -> Result<RebaseOutcome> {
2440
// First we want to get a list of nodes that can be reached by
2541
// traversing downwards from the heads that we care about.
2642
// Usually there would be just one "head" which is an index to access
@@ -41,41 +57,52 @@ impl Editor {
4157
let step = self.graph[step_idx].clone();
4258
match step {
4359
Step::Pick { id } => {
44-
let commit = to_commit(repo, id)?;
4560
let graph_parents = collect_ordered_parents(&self.graph, step_idx);
46-
47-
match (commit.parents.len(), graph_parents.len()) {
48-
(0, 0) => {
49-
let new_idx = output_graph.add_node(step);
61+
let ontos = graph_parents
62+
.iter()
63+
.map(|idx| {
64+
let Some(new_idx) = graph_mapping.get(idx) else {
65+
bail!("A matching parent can't be found in the output graph");
66+
};
67+
68+
match output_graph[*new_idx] {
69+
Step::Pick { id } => Ok(id),
70+
_ => bail!("A parent in the output graph is not a pick"),
71+
}
72+
})
73+
.collect::<Result<Vec<_>>>()?;
74+
75+
let outcome = cherry_pick(repo, id, &ontos)?;
76+
77+
match outcome {
78+
CherryPickOutcome::Commit(new_id)
79+
| CherryPickOutcome::ConflictedCommit(new_id)
80+
| CherryPickOutcome::Identity(new_id) => {
81+
let new_idx = output_graph.add_node(Step::Pick { id: new_id });
5082
graph_mapping.insert(step_idx, new_idx);
5183
}
52-
(1, 0) => {
53-
todo!("1 to 0 cherry pick is not implemented yet");
54-
}
55-
(0, 1) => {
56-
todo!("0 to 1 cherry pick is not implemented yet");
57-
}
58-
(1, 1) => {
59-
let (_, parent_id) = graph_parents.first().expect("Impossible");
60-
61-
let new_commit = cherry_pick_one(
62-
repo,
63-
*parent_id,
64-
id,
65-
pick_mode,
66-
EmptyCommit::Keep,
67-
)?;
68-
69-
let new_idx = output_graph.add_node(Step::Pick { id: new_commit });
70-
graph_mapping.insert(step_idx, new_idx);
71-
}
72-
(_, _) => {
73-
todo!("N to >2 parents & >2 parents to N is not implemented yet");
84+
CherryPickOutcome::FailedToMergeBases => {
85+
// Exit early - the rebase failed because it encountered a commit it couldn't pick
86+
return Ok(RebaseOutcome::MergePickFailed(id));
7487
}
7588
};
7689
}
77-
Step::Reference { refname } => {}
78-
Step::None => {}
90+
Step::Reference { refname } => {
91+
let graph_parents = collect_ordered_parents(&self.graph, step_idx);
92+
let first_parent_idx = graph_parents.first().context("References ")
93+
let Some(new_idx) = graph_mapping.get(idx) else {
94+
bail!("A matching parent can't be found in the output graph");
95+
};
96+
97+
let to_reference = match output_graph[*new_idx] {
98+
Step::Pick { id } => id,
99+
_ => bail!("A parent in the output graph is not a pick"),
100+
};
101+
}
102+
Step::None => {
103+
let new_idx = output_graph.add_node(Step::None);
104+
graph_mapping.insert(step_idx, new_idx);
105+
}
79106
};
80107
}
81108

@@ -87,10 +114,7 @@ impl Editor {
87114
/// ordering.
88115
///
89116
/// We do this via a pruned depth first search.
90-
fn collect_ordered_parents(
91-
graph: &StepGraph,
92-
target: StepGraphIndex,
93-
) -> Vec<(StepGraphIndex, gix::ObjectId)> {
117+
fn collect_ordered_parents(graph: &StepGraph, target: StepGraphIndex) -> Vec<StepGraphIndex> {
94118
let mut potential_parent_edges = graph
95119
.edges_directed(target, petgraph::Direction::Outgoing)
96120
.collect::<Vec<_>>();
@@ -106,7 +130,7 @@ fn collect_ordered_parents(
106130

107131
while let Some(candidate) = potential_parent_edges.pop() {
108132
if let Step::Pick { id } = graph[candidate.target()] {
109-
parents.push((candidate.target(), id));
133+
parents.push(candidate.target());
110134
// Don't persue the children
111135
continue;
112136
};
@@ -223,7 +247,7 @@ mod test {
223247
graph.add_edge(c, e, Edge { order: 1 });
224248

225249
let parents = collect_ordered_parents(&graph, a);
226-
assert_eq!(&parents, &[(b, b_id), (d, d_id), (e, e_id), (f, f_id)]);
250+
assert_eq!(&parents, &[b, d, e, f]);
227251

228252
Ok(())
229253
}
@@ -260,7 +284,7 @@ mod test {
260284
graph.add_edge(c, e, Edge { order: 0 });
261285

262286
let parents = collect_ordered_parents(&graph, a);
263-
assert_eq!(&parents, &[(b, b_id), (e, e_id), (d, d_id), (f, f_id)]);
287+
assert_eq!(&parents, &[b, e, d, f]);
264288

265289
Ok(())
266290
}

0 commit comments

Comments
 (0)