Skip to content

Commit c8caabb

Browse files
Merge pull request #4797 from gitbutlerapp/Resolve-tree-in-less-stupid-manner
Resolve merge in less stupid manner
2 parents 425136d + 0802d1c commit c8caabb

File tree

2 files changed

+13
-39
lines changed

2 files changed

+13
-39
lines changed

crates/gitbutler-cherry-pick/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use std::ops::Deref;
88

99
use anyhow::Context;
10+
use git2::MergeOptions;
1011
use gitbutler_commit::commit_ext::CommitExt;
1112

1213
#[derive(Default)]
@@ -43,6 +44,7 @@ pub trait RepositoryExt {
4344
&self,
4445
head: &git2::Commit,
4546
to_rebase: &git2::Commit,
47+
merge_options: Option<&MergeOptions>,
4648
) -> Result<git2::Index, anyhow::Error>;
4749
fn find_real_tree(
4850
&self,
@@ -60,6 +62,7 @@ impl RepositoryExt for git2::Repository {
6062
&self,
6163
head: &git2::Commit,
6264
to_rebase: &git2::Commit,
65+
merge_options: Option<&MergeOptions>,
6366
) -> Result<git2::Index, anyhow::Error> {
6467
// we need to do a manual 3-way patch merge
6568
// find the base, which is the parent of to_rebase
@@ -76,7 +79,7 @@ impl RepositoryExt for git2::Repository {
7679
// Get the original theirs
7780
let thiers = self.find_real_tree(to_rebase, ConflictedTreeKey::Theirs)?;
7881

79-
self.merge_trees(&base, &ours, &thiers, None)
82+
self.merge_trees(&base, &ours, &thiers, merge_options)
8083
.context("failed to merge trees for cherry pick")
8184
}
8285

crates/gitbutler-repo/src/rebase.rs

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use anyhow::{anyhow, Context, Result};
22
use bstr::ByteSlice;
3-
use git2::build::TreeUpdateBuilder;
43
use gitbutler_cherry_pick::{ConflictedTreeKey, RepositoryExt};
54
use gitbutler_command_context::CommandContext;
65
use gitbutler_commit::{
@@ -9,7 +8,7 @@ use gitbutler_commit::{
98
};
109
use gitbutler_error::error::Marker;
1110

12-
use crate::{temporary_workdir::TemporaryWorkdir, LogUntil, RepoActionsExt};
11+
use crate::{LogUntil, RepoActionsExt};
1312

1413
/// cherry-pick based rebase, which handles empty commits
1514
/// this function takes a commit range and generates a Vector of commit oids
@@ -63,7 +62,7 @@ pub fn cherry_rebase_group(
6362
let head = head?;
6463

6564
let cherrypick_index = repository
66-
.cherry_pick_gitbutler(&head, &to_rebase)
65+
.cherry_pick_gitbutler(&head, &to_rebase, None)
6766
.context("failed to cherry pick")?;
6867

6968
if cherrypick_index.has_conflicts() {
@@ -131,7 +130,7 @@ fn commit_conflicted_cherry_result<'repository>(
131130
ctx: &'repository CommandContext,
132131
head: git2::Commit,
133132
to_rebase: git2::Commit,
134-
mut cherrypick_index: git2::Index,
133+
cherrypick_index: git2::Index,
135134
) -> Result<git2::Commit<'repository>> {
136135
let repository = ctx.repository();
137136
let commit_headers = to_rebase.gitbutler_headers();
@@ -149,54 +148,26 @@ fn commit_conflicted_cherry_result<'repository>(
149148
b"You have checked out a GitButler Conflicted commit. You probably didn't mean to do this.";
150149
let readme_blob = repository.blob(readme_content)?;
151150

152-
// Open a temporary workdir that gets cleaned up when it leaves scope.
153-
// We need to have our cherrypick_index set to a real repository so we can
154-
// manipluate it.
155-
let temporary_workdir = TemporaryWorkdir::open(repository)?;
156-
157-
temporary_workdir
158-
.repository()
159-
.set_index(&mut cherrypick_index)
160-
.context("Failed to set cherrypick index as worktree index")?;
161-
162151
let mut conflicted_files = Vec::new();
163152

164153
// get a list of conflicted files from the index
165154
let index_conflicts = cherrypick_index.conflicts()?.flatten().collect::<Vec<_>>();
166-
let mut ours: Vec<git2::IndexEntry> = vec![];
167-
168155
for conflict in index_conflicts {
169156
// For some reason we have to resolve the index with the "their" side
170157
// rather than the "our" side, so we then go and later overwrite the
171158
// output tree with the "our" side.
172159
if let Some(their) = conflict.their {
173160
let path = std::str::from_utf8(&their.path).unwrap().to_string();
174161
conflicted_files.push(path);
175-
176-
let data = repository.find_blob(their.id)?;
177-
let data = data.content();
178-
179-
cherrypick_index
180-
.add_frombuffer(&their, data)
181-
.context("Failed to add resolution")?;
182162
}
183-
184-
if let Some(our) = conflict.our {
185-
ours.push(our)
186-
}
187-
}
188-
189-
let resolved_tree = cherrypick_index
190-
.write_tree_to(repository)
191-
.context("Failed to write cherry index")?;
192-
let resolved_tree = repository.find_tree(resolved_tree)?;
193-
let mut resolved_tree_updater = TreeUpdateBuilder::new();
194-
195-
for our in ours {
196-
resolved_tree_updater.upsert(our.path, our.id, git2::FileMode::Blob);
197163
}
198164

199-
let resolved_tree_id = resolved_tree_updater.create_updated(repository, &resolved_tree)?;
165+
let mut resolved_index = repository.cherry_pick_gitbutler(
166+
&head,
167+
&to_rebase,
168+
Some(git2::MergeOptions::default().file_favor(git2::FileFavor::Ours)),
169+
)?;
170+
let resolved_tree_id = resolved_index.write_tree_to(repository)?;
200171

201172
// convert files into a string and save as a blob
202173
let conflicted_files_string = conflicted_files.join("\n");

0 commit comments

Comments
 (0)