Skip to content

Commit 2318c99

Browse files
authored
Merge pull request #7280 from gitbutlerapp/advanced-committing
commit with rebase-engine integration
2 parents b2abc07 + dc2b61d commit 2318c99

File tree

38 files changed

+2787
-917
lines changed

38 files changed

+2787
-917
lines changed

Cargo.lock

+95-73
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ resolver = "2"
55
[workspace.dependencies]
66
bstr = "1.11.1"
77
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.
8-
gix = { git = "https://github.com/GitoxideLabs/gitoxide", branch = "improvements", default-features = false, features = [
8+
gix = { git = "https://github.com/GitoxideLabs/gitoxide", rev = "b4fe425a1a7823790fab592c84aa8494d295640d", default-features = false, features = [
99
] }
1010
gix-testtools = "0.15.0"
1111
insta = "1.41.1"
@@ -67,8 +67,8 @@ gitbutler-forge = { path = "crates/gitbutler-forge" }
6767
gitbutler-hunk-dependency = { path = "crates/gitbutler-hunk-dependency" }
6868
gitbutler-settings = { path = "crates/gitbutler-settings" }
6969
gitbutler-workspace = { path = "crates/gitbutler-workspace" }
70-
but-debugging = { path = "crates/but-debugging" }
71-
but-rebase = { path = "crates/but-debugging" }
70+
but-testsupport = { path = "crates/but-testsupport" }
71+
but-rebase = { path = "crates/but-rebase" }
7272
but-core = { path = "crates/but-core" }
7373
but-workspace = { path = "crates/but-workspace" }
7474
but-hunk-dependency = { path = "crates/but-hunk-dependency" }

crates/but-core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ gitbutler-error.workspace = true
2323
uuid.workspace = true
2424

2525
[dev-dependencies]
26-
gix-testtools.workspace = true
26+
but-testsupport.workspace = true
2727
gix = { workspace = true, features = ["revision"] }
2828
serde_json = "1.0"
2929
insta.workspace = true

crates/but-core/src/lib.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ pub use repo_ext::RepositoryExt;
7070
pub struct Commit<'repo> {
7171
/// The id of the commit itself.
7272
pub id: gix::Id<'repo>,
73-
inner: gix::objs::Commit,
73+
/// The decoded commit for direct access.
74+
pub inner: gix::objs::Commit,
7475
}
7576

7677
/// A patch in unified diff format to show how a resource changed or now looks like (in case it was newly added),
@@ -93,6 +94,16 @@ pub enum UnifiedDiff {
9394
},
9495
}
9596

97+
/// Either git reference or a virtual reference (i.e. a reference not visible in Git).
98+
#[derive(Debug, Clone, PartialEq)]
99+
pub enum Reference {
100+
/// A git reference or lightweight tag.
101+
Git(gix::refs::FullName),
102+
/// A reference not visible in Git, managed by GitButler.
103+
// TODO: ideally this isn't needed anymore in the final version as all refs are 'real'.
104+
Virtual(String),
105+
}
106+
96107
/// An entry in the worktree that changed and thus is eligible to being committed.
97108
///
98109
/// It either lives (or lived) in the in `.git/index`, or in the `worktree`.

crates/but-core/tests/core/commit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use but_testsupport::gix_testtools;
2+
13
#[test]
24
fn is_conflicted() -> anyhow::Result<()> {
35
let repo = conflict_repo("normal-and-artificial")?;

crates/but-core/tests/core/diff/ui.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use but_core::UnifiedDiff;
2+
use but_testsupport::gix_testtools;
23

34
#[test]
45
fn worktree_changes() -> anyhow::Result<()> {

crates/but-core/tests/core/diff/worktree_changes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::Result;
22
use but_core::diff;
33
use but_core::{UnifiedDiff, WorktreeChanges};
4+
use but_testsupport::gix_testtools;
45

56
#[test]
67
#[cfg(unix)]

crates/but-core/tests/core/settings.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod git {
22
use but_core::{GitConfigSettings, RepositoryExt};
3+
use but_testsupport::gix_testtools;
34

45
#[test]
56
fn set_git_settings() -> anyhow::Result<()> {

crates/but-hunk-dependency/src/input.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use but_core::TreeStatusKind;
33
use but_workspace::StackId;
44
use gix::bstr::BString;
55

6-
/// A whole stack for the purpose of generating hunk locking information from it, for use in [Dependencies::calculate()](crate::Dependencies::calculate()).
6+
/// A whole stack for the purpose of generating hunk locking information from it, for use in [`WorkspaceRanges::try_from_stacks()`](crate::WorkspaceRanges::try_from_stacks()) .
77
#[derive(Debug, Clone)]
88
pub struct InputStack {
9-
/// The stack that contains [`commits`](InputStack::commits).
9+
/// The stack that contains [commits](InputStack::commits_from_base_to_tip).
1010
pub stack_id: StackId,
1111
/// The commits in the stack.
1212
///

crates/but-rebase/Cargo.toml

+11-8
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@ publish = false
99
doctest = false
1010

1111
[dependencies]
12-
gix.workspace = true
12+
gix = { workspace = true, features = ["revision", "merge"]}
1313
anyhow.workspace = true
14+
tracing.workspace = true
15+
but-core.workspace = true
1416
gitbutler-repo.workspace = true
1517
gitbutler-oxidize.workspace = true
18+
gitbutler-error.workspace = true
1619
bstr.workspace = true
1720
git2.workspace = true
18-
itertools = "0.14"
19-
smallvec = "1.13.2"
20-
21-
[[test]]
22-
name = "rebase"
23-
path = "tests/mod.rs"
21+
tempfile.workspace = true
2422

2523
[dev-dependencies]
26-
gix-testtools.workspace = true
24+
but-testsupport.workspace = true
25+
insta = "1.42.1"
26+
but-core = { workspace = true, features = ["testing"] }
27+
# for stable hashes in `gitbuter-` crates while we use them.
28+
# TODO: remove once `gitbutler-repo` isn't needed anymore.
29+
gitbutler-commit = { workspace = true, features = ["testing"] }

crates/but-workspace/src/commit_engine/plumbing.rs crates/but-rebase/src/commit.rs

+5-69
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,21 @@ use but_core::cmd::prepare_with_shell_on_windows;
44
use but_core::{GitConfigSettings, RepositoryExt};
55
use gitbutler_error::error::Code;
66
use gix::objs::WriteTo;
7-
use gix::refs::transaction::{Change, LogChange, PreviousValue, RefLog};
8-
use gix::refs::Target;
97
use std::borrow::Cow;
108
use std::io::Write;
119
use std::path::Path;
1210
use std::process::Stdio;
1311

14-
/// Create a commit exactly as specified, and sign it depending on Git and GitButler specific Git configuration.
15-
#[allow(clippy::too_many_arguments)]
16-
pub fn create_commit(
17-
repo: &gix::Repository,
18-
update_ref: Option<gix::refs::FullName>,
19-
author: gix::actor::Signature,
20-
committer: gix::actor::Signature,
21-
message: &str,
22-
tree: gix::ObjectId,
23-
parents: impl IntoIterator<Item = impl Into<gix::ObjectId>>,
24-
commit_headers: Option<but_core::commit::HeadersV2>,
25-
) -> anyhow::Result<(gix::ObjectId, Option<gix::refs::transaction::RefEdit>)> {
26-
let commit = gix::objs::Commit {
27-
message: message.into(),
28-
tree,
29-
author,
30-
committer,
31-
encoding: None,
32-
parents: parents.into_iter().map(Into::into).collect(),
33-
extra_headers: commit_headers.unwrap_or_default().into(),
34-
};
35-
create_given_commit(repo, update_ref, commit)
36-
}
37-
38-
/// Use the given commit and possibly sign it, replacing a possibly existing signature,
12+
/// Use the given `commit` and possibly sign it, replacing a possibly existing signature,
3913
/// or removing the signature if GitButler is not configured to keep it.
4014
///
4115
/// Signatures will be removed automatically if signing is disabled to prevent an amended commit
42-
/// to use the old signature. They will also be added or replace existing signatures.
16+
/// to use the old signature.
4317
#[allow(clippy::too_many_arguments)]
44-
pub fn create_given_commit(
18+
pub fn create(
4519
repo: &gix::Repository,
46-
update_ref: Option<gix::refs::FullName>,
4720
mut commit: gix::objs::Commit,
48-
) -> anyhow::Result<(gix::ObjectId, Option<gix::refs::transaction::RefEdit>)> {
21+
) -> anyhow::Result<gix::ObjectId> {
4922
if let Some(pos) = commit
5023
.extra_headers()
5124
.find_pos(gix::objs::commit::SIGNATURE_FIELD_NAME)
@@ -74,44 +47,7 @@ pub fn create_given_commit(
7447
}
7548
}
7649

77-
let new_commit_id = repo.write_object(&commit)?.detach();
78-
let refedit = if let Some(refname) = update_ref {
79-
// TODO:(ST) should this be something more like what Git does (also in terms of reflog message)?
80-
// Probably should support making a commit in full with `gix`.
81-
let log_message = commit.message;
82-
let edit = update_reference(repo, refname, new_commit_id, log_message)?;
83-
Some(edit)
84-
} else {
85-
None
86-
};
87-
Ok((new_commit_id, refedit))
88-
}
89-
90-
fn update_reference(
91-
repo: &gix::Repository,
92-
name: gix::refs::FullName,
93-
target: gix::ObjectId,
94-
log_message: BString,
95-
) -> anyhow::Result<gix::refs::transaction::RefEdit> {
96-
let mut edits = repo.edit_reference(gix::refs::transaction::RefEdit {
97-
change: Change::Update {
98-
log: LogChange {
99-
mode: RefLog::AndReference,
100-
force_create_reflog: false,
101-
message: log_message,
102-
},
103-
expected: PreviousValue::Any,
104-
new: Target::Object(target),
105-
},
106-
name,
107-
deref: false,
108-
})?;
109-
debug_assert_eq!(
110-
edits.len(),
111-
1,
112-
"only one reference can be created, splits aren't possible"
113-
);
114-
Ok(edits.pop().expect("exactly one edit"))
50+
Ok(repo.write_object(&commit)?.detach())
11551
}
11652

11753
fn sign_buffer(repo: &gix::Repository, buffer: &[u8]) -> anyhow::Result<BString> {

0 commit comments

Comments
 (0)