From 51f9769024e4446ceb7b1509beda574f8b235ffc Mon Sep 17 00:00:00 2001 From: Scott Chacon Date: Tue, 7 May 2024 15:15:25 +0200 Subject: [PATCH] sign commits with real git in the strangest possible way --- Cargo.lock | 1 + crates/gitbutler-core/src/git/repository.rs | 23 ++++ .../src/project_repository/repository.rs | 15 +-- .../src/virtual_branches/base.rs | 3 - .../src/virtual_branches/controller.rs | 110 ++-------------- .../src/virtual_branches/virtual.rs | 22 +--- .../tests/suite/virtual_branches/init.rs | 3 +- .../tests/suite/virtual_branches/mod.rs | 5 +- .../tests/virtual_branches/mod.rs | 34 +---- crates/gitbutler-git/Cargo.toml | 1 + crates/gitbutler-git/src/lib.rs | 2 +- crates/gitbutler-git/src/repository.rs | 120 +++++++++++++++++- crates/gitbutler-tauri/src/main.rs | 1 - crates/gitbutler-watcher/tests/handler/mod.rs | 1 - 14 files changed, 168 insertions(+), 173 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 442ee0c7e..92d1ee6c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2190,6 +2190,7 @@ dependencies = [ "sysinfo", "thiserror", "tokio", + "uuid", "winapi 0.3.9", "windows-named-pipe", ] diff --git a/crates/gitbutler-core/src/git/repository.rs b/crates/gitbutler-core/src/git/repository.rs index 492aa351f..26e3f2a2e 100644 --- a/crates/gitbutler-core/src/git/repository.rs +++ b/crates/gitbutler-core/src/git/repository.rs @@ -274,6 +274,29 @@ impl Repository { .write(git2::ObjectType::Commit, commit_buffer.as_bytes())?; // check git config for gpg.signingkey + let signing_key = self.0.config()?.get_string("commit.gpgSign"); + dbg!(&signing_key); + if let Ok(_should_sign) = signing_key { + dbg!("SIGN IT"); + /* + SOMETHING SOMETHING DARK SIDE... + let path = self.path().to_path_buf(); + let res = std::thread::spawn(move || { + tokio::runtime::Runtime::new() + .unwrap() + .block_on(gitbutler_git::sign_commit( + path, + gitbutler_git::tokio::TokioExecutor, + oid.to_string(), + handle_git_prompt_sign, + extra, + )) + }) + .join() + .unwrap() + .map_err(|e| Err(anyhow::anyhow!("fuck you"))); + */ + } // update reference if let Some(refname) = update_ref { diff --git a/crates/gitbutler-core/src/project_repository/repository.rs b/crates/gitbutler-core/src/project_repository/repository.rs index fe8695b57..1e014878d 100644 --- a/crates/gitbutler-core/src/project_repository/repository.rs +++ b/crates/gitbutler-core/src/project_repository/repository.rs @@ -13,7 +13,6 @@ use crate::{ askpass::AskpassBroker, error, git::{self, credentials::HelpError, Url}, - keys, projects::{self, AuthKey}, ssh, users, virtual_branches::{Branch, BranchId}, @@ -344,20 +343,12 @@ impl Repository { message: &str, tree: &git::Tree, parents: &[&git::Commit], - signing_key: Option<&keys::PrivateKey>, change_id: Option<&str>, ) -> Result { let (author, committer) = self.git_signatures(user)?; - - if let Some(key) = signing_key { - self.git_repository - .commit_signed(&author, message, tree, parents, key, change_id) - .context("failed to commit signed") - } else { - self.git_repository - .commit(None, &author, &committer, message, tree, parents, change_id) - .context("failed to commit") - } + self.git_repository + .commit(None, &author, &committer, message, tree, parents, change_id) + .context("failed to commit") } pub fn push_to_gitbutler_server( diff --git a/crates/gitbutler-core/src/virtual_branches/base.rs b/crates/gitbutler-core/src/virtual_branches/base.rs index 7664e977a..806e95831 100644 --- a/crates/gitbutler-core/src/virtual_branches/base.rs +++ b/crates/gitbutler-core/src/virtual_branches/base.rs @@ -12,7 +12,6 @@ use super::{ }; use crate::{ git::{self, diff}, - keys, project_repository::{self, LogUntil}, projects::FetchResult, users, @@ -342,7 +341,6 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> { pub fn update_base_branch( project_repository: &project_repository::Repository, user: Option<&users::User>, - signing_key: Option<&keys::PrivateKey>, ) -> Result<(), errors::UpdateBaseBranchError> { if project_repository.is_resolving() { return Err(errors::UpdateBaseBranchError::Conflict( @@ -513,7 +511,6 @@ pub fn update_base_branch( .as_str(), &branch_head_merge_tree, &[&branch_head_commit, &new_target_commit], - signing_key, None, ) .context("failed to commit merge")?; diff --git a/crates/gitbutler-core/src/virtual_branches/controller.rs b/crates/gitbutler-core/src/virtual_branches/controller.rs index 62c592c46..37eee628a 100644 --- a/crates/gitbutler-core/src/virtual_branches/controller.rs +++ b/crates/gitbutler-core/src/virtual_branches/controller.rs @@ -17,7 +17,7 @@ use super::{ }; use crate::{ askpass::AskpassBroker, - git, keys, project_repository, + git, project_repository, projects::{self, ProjectId}, users, }; @@ -26,7 +26,6 @@ use crate::{ pub struct Controller { projects: projects::Controller, users: users::Controller, - keys: keys::Controller, helper: git::credentials::Helper, by_project_id: Arc>>, @@ -36,7 +35,6 @@ impl Controller { pub fn new( projects: projects::Controller, users: users::Controller, - keys: keys::Controller, helper: git::credentials::Helper, ) -> Self { Self { @@ -44,7 +42,6 @@ impl Controller { projects, users, - keys, helper, } } @@ -54,9 +51,7 @@ impl Controller { .lock() .await .entry(*project_id) - .or_insert_with(|| { - ControllerInner::new(&self.projects, &self.users, &self.keys, &self.helper) - }) + .or_insert_with(|| ControllerInner::new(&self.projects, &self.users, &self.helper)) .clone() } @@ -430,7 +425,6 @@ struct ControllerInner { projects: projects::Controller, users: users::Controller, - keys: keys::Controller, helper: git::credentials::Helper, } @@ -438,14 +432,12 @@ impl ControllerInner { pub fn new( projects: &projects::Controller, users: &users::Controller, - keys: &keys::Controller, helper: &git::credentials::Helper, ) -> Self { Self { semaphore: Arc::new(Semaphore::new(1)), projects: projects.clone(), users: users.clone(), - keys: keys.clone(), helper: helper.clone(), } } @@ -461,23 +453,11 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - let result = super::commit( project_repository, branch_id, message, ownership, - signing_key.as_ref(), user, run_hooks, ) @@ -548,22 +528,8 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - let result = super::create_virtual_branch_from_branch( - project_repository, - branch, - signing_key.as_ref(), - user, - )?; + let result = + super::create_virtual_branch_from_branch(project_repository, branch, user)?; let _ = project_repository .project() .create_snapshot(SnapshotDetails::new(OperationType::CreateBranch)); @@ -624,24 +590,8 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - - let result = super::merge_virtual_branch_upstream( - project_repository, - branch_id, - signing_key.as_ref(), - user, - ) - .map_err(Into::into); + let result = super::merge_virtual_branch_upstream(project_repository, branch_id, user) + .map_err(Into::into); let _ = project_repository .project() .create_snapshot(SnapshotDetails::new(OperationType::MergeUpstream)); @@ -653,19 +603,7 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - - let result = super::update_base_branch(project_repository, user, signing_key.as_ref()) - .map_err(Into::into); + let result = super::update_base_branch(project_repository, user).map_err(Into::into); let _ = project_repository .project() .create_snapshot(SnapshotDetails::new(OperationType::UpdateWorkspaceBase)); @@ -726,20 +664,8 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - let result = - super::apply_branch(project_repository, branch_id, signing_key.as_ref(), user) - .map_err(Into::into); + super::apply_branch(project_repository, branch_id, user).map_err(Into::into); let _ = project_repository .project() .create_snapshot(SnapshotDetails::new(OperationType::ApplyBranch)); @@ -1083,24 +1009,8 @@ impl ControllerInner { let _permit = self.semaphore.acquire().await; self.with_verify_branch(project_id, |project_repository, user| { - let signing_key = project_repository - .config() - .sign_commits() - .context("failed to get sign commits option")? - .then(|| { - self.keys - .get_or_create() - .context("failed to get private key") - }) - .transpose()?; - let result = super::move_commit( - project_repository, - target_branch_id, - commit_oid, - user, - signing_key.as_ref(), - ) - .map_err(Into::into); + let result = super::move_commit(project_repository, target_branch_id, commit_oid, user) + .map_err(Into::into); let _ = project_repository .project() .create_snapshot(SnapshotDetails::new(OperationType::MoveCommit)); diff --git a/crates/gitbutler-core/src/virtual_branches/virtual.rs b/crates/gitbutler-core/src/virtual_branches/virtual.rs index 8751f9568..f3d150001 100644 --- a/crates/gitbutler-core/src/virtual_branches/virtual.rs +++ b/crates/gitbutler-core/src/virtual_branches/virtual.rs @@ -34,7 +34,6 @@ use crate::{ diff::{self}, Commit, Refname, RemoteRefname, }, - keys, project_repository::{self, conflicts, LogUntil}, reader, users, }; @@ -101,6 +100,7 @@ pub struct VirtualBranchCommit { pub branch_id: BranchId, pub change_id: Option, pub is_signed: bool, + pub stack_points: Option>>, } // this struct is a mapping to the view `File` type in Typescript @@ -215,7 +215,6 @@ pub fn normalize_branch_name(name: &str) -> String { pub fn apply_branch( project_repository: &project_repository::Repository, branch_id: &BranchId, - signing_key: Option<&keys::PrivateKey>, user: Option<&users::User>, ) -> Result<(), errors::ApplyBranchError> { if project_repository.is_resolving() { @@ -359,7 +358,6 @@ pub fn apply_branch( .as_str(), &merged_branch_tree, &[&head_commit, &target_commit], - signing_key, None, )?; @@ -429,7 +427,6 @@ pub fn apply_branch( .as_str(), &merge_tree, &[&head_commit, &target_commit], - signing_key, None, ) .context("failed to commit merge")?; @@ -1053,6 +1050,7 @@ fn commit_to_vbranch_commit( branch_id: branch.id, change_id: commit.change_id(), is_signed: commit.is_signed(), + stack_points: Some(stack_points), }; Ok(commit) @@ -1171,7 +1169,6 @@ pub fn create_virtual_branch( pub fn merge_virtual_branch_upstream( project_repository: &project_repository::Repository, branch_id: &BranchId, - signing_key: Option<&keys::PrivateKey>, user: Option<&users::User>, ) -> Result<(), errors::MergeVirtualBranchUpstreamError> { if conflicts::is_conflicting::<&Path>(project_repository, None)? { @@ -1364,7 +1361,6 @@ pub fn merge_virtual_branch_upstream( .as_str(), &merge_tree, &[&head_commit, &upstream_commit], - signing_key, None, )?; @@ -2312,7 +2308,6 @@ pub fn commit( branch_id: &BranchId, message: &str, ownership: Option<&branch::BranchOwnershipClaims>, - signing_key: Option<&keys::PrivateKey>, user: Option<&users::User>, run_hooks: bool, ) -> Result { @@ -2415,15 +2410,12 @@ pub fn commit( message, &tree, &[&parent_commit, &merge_parent], - signing_key, None, )?; conflicts::clear(project_repository).context("failed to clear conflicts")?; commit_oid } - None => { - project_repository.commit(user, message, &tree, &[&parent_commit], signing_key, None)? - } + None => project_repository.commit(user, message, &tree, &[&parent_commit], None)?, }; if run_hooks { @@ -3340,8 +3332,7 @@ pub fn insert_blank_commit( } let commit_tree = commit.tree().unwrap(); - let blank_commit_oid = - project_repository.commit(user, "", &commit_tree, &[&commit], None, None)?; + let blank_commit_oid = project_repository.commit(user, "", &commit_tree, &[&commit], None)?; if commit.id() == branch.head && offset < 0 { // inserting before the first commit @@ -3983,7 +3974,6 @@ pub fn move_commit( target_branch_id: &BranchId, commit_oid: git::Oid, user: Option<&users::User>, - signing_key: Option<&keys::PrivateKey>, ) -> Result<(), errors::MoveCommitError> { if project_repository.is_resolving() { return Err(errors::MoveCommitError::Conflicted( @@ -4140,7 +4130,6 @@ pub fn move_commit( .git_repository .find_commit(destination_branch.head) .context("failed to get dst branch head commit")?], - signing_key, change_id.as_deref(), ) .context("failed to commit")?; @@ -4158,7 +4147,6 @@ pub fn move_commit( pub fn create_virtual_branch_from_branch( project_repository: &project_repository::Repository, upstream: &git::Refname, - signing_key: Option<&keys::PrivateKey>, user: Option<&users::User>, ) -> Result { if !matches!(upstream, git::Refname::Local(_) | git::Refname::Remote(_)) { @@ -4297,7 +4285,7 @@ pub fn create_virtual_branch_from_branch( project_repository.add_branch_reference(&branch)?; - match apply_branch(project_repository, &branch.id, signing_key, user) { + match apply_branch(project_repository, &branch.id, user) { Ok(()) => Ok(branch.id), Err(errors::ApplyBranchError::BranchConflicts(_)) => { // if branch conflicts with the workspace, it's ok. keep it unapplied diff --git a/crates/gitbutler-core/tests/suite/virtual_branches/init.rs b/crates/gitbutler-core/tests/suite/virtual_branches/init.rs index ba39156fc..1be497e78 100644 --- a/crates/gitbutler-core/tests/suite/virtual_branches/init.rs +++ b/crates/gitbutler-core/tests/suite/virtual_branches/init.rs @@ -3,14 +3,13 @@ use super::*; #[tokio::test] async fn twice() { let data_dir = paths::data_dir(); - let keys = keys::Controller::from_path(data_dir.path()); let projects = projects::Controller::from_path(data_dir.path()); let users = users::Controller::from_path(data_dir.path()); let helper = git::credentials::Helper::from_path(data_dir.path()); let test_project = TestProject::default(); - let controller = Controller::new(projects.clone(), users, keys, helper); + let controller = Controller::new(projects.clone(), users, helper); { let project = projects diff --git a/crates/gitbutler-core/tests/suite/virtual_branches/mod.rs b/crates/gitbutler-core/tests/suite/virtual_branches/mod.rs index cd211e436..90fa8ea14 100644 --- a/crates/gitbutler-core/tests/suite/virtual_branches/mod.rs +++ b/crates/gitbutler-core/tests/suite/virtual_branches/mod.rs @@ -1,7 +1,7 @@ use std::{fs, path, str::FromStr}; use gitbutler_core::{ - git, keys, + git, projects::{self, ProjectId}, users, virtual_branches::{branch, errors, Controller}, @@ -29,7 +29,6 @@ impl Drop for Test { impl Default for Test { fn default() -> Self { let data_dir = paths::data_dir(); - let keys = keys::Controller::from_path(data_dir.path()); let projects = projects::Controller::from_path(data_dir.path()); let users = users::Controller::from_path(data_dir.path()); let helper = git::credentials::Helper::from_path(data_dir.path()); @@ -42,7 +41,7 @@ impl Default for Test { Self { repository: test_project, project_id: project.id, - controller: Controller::new(projects.clone(), users, keys, helper), + controller: Controller::new(projects.clone(), users, helper), projects, data_dir: Some(data_dir), } diff --git a/crates/gitbutler-core/tests/virtual_branches/mod.rs b/crates/gitbutler-core/tests/virtual_branches/mod.rs index f73356d6f..190e837ef 100644 --- a/crates/gitbutler-core/tests/virtual_branches/mod.rs +++ b/crates/gitbutler-core/tests/virtual_branches/mod.rs @@ -64,7 +64,6 @@ fn commit_on_branch_then_change_file_then_get_status() -> Result<()> { "test commit", None, None, - None, false, )?; @@ -123,7 +122,6 @@ fn signed_commit() -> Result<()> { &branch1_id, "test commit", None, - Some(suite.keys.get_or_create()?).as_ref(), None, false, )?; @@ -212,7 +210,6 @@ fn track_binary_files() -> Result<()> { "test commit", None, None, - None, false, )?; @@ -244,7 +241,6 @@ fn track_binary_files() -> Result<()> { "test commit", None, None, - None, false, )?; @@ -811,12 +807,7 @@ fn merge_vbranch_upstream_clean_rebase() -> Result<()> { assert_eq!(branch1.commits.len(), 1); // assert_eq!(branch1.upstream.as_ref().unwrap().commits.len(), 1); - merge_virtual_branch_upstream( - project_repository, - &branch1.id, - Some(suite.keys.get_or_create()?).as_ref(), - None, - )?; + merge_virtual_branch_upstream(project_repository, &branch1.id, None)?; let (branches, _) = virtual_branches::list_virtual_branches(project_repository)?; let branch1 = &branches[0]; @@ -931,7 +922,7 @@ fn merge_vbranch_upstream_conflict() -> Result<()> { assert_eq!(branch1.commits.len(), 1); // assert_eq!(branch1.upstream.as_ref().unwrap().commits.len(), 1); - merge_virtual_branch_upstream(project_repository, &branch1.id, None, None)?; + merge_virtual_branch_upstream(project_repository, &branch1.id, None)?; let (branches, _) = virtual_branches::list_virtual_branches(project_repository)?; let branch1 = &branches[0]; @@ -963,7 +954,6 @@ fn merge_vbranch_upstream_conflict() -> Result<()> { "fix merge conflict", None, None, - None, false, )?; @@ -1095,7 +1085,7 @@ fn unapply_branch() -> Result<()> { assert_eq!(branch.files.len(), 1); assert!(!branch.active); - apply_branch(project_repository, &branch1_id, None, None)?; + apply_branch(project_repository, &branch1_id, None)?; let contents = std::fs::read(Path::new(&project.path).join(file_path))?; assert_eq!( "line1\nline2\nline3\nline4\nbranch1\n", @@ -1168,11 +1158,11 @@ fn apply_unapply_added_deleted_files() -> Result<()> { // check that file3 is gone assert!(!Path::new(&project.path).join(file_path3).exists()); - apply_branch(project_repository, &branch2_id, None, None)?; + apply_branch(project_repository, &branch2_id, None)?; // check that file2 is gone assert!(!Path::new(&project.path).join(file_path2).exists()); - apply_branch(project_repository, &branch3_id, None, None)?; + apply_branch(project_repository, &branch3_id, None)?; // check that file3 is back let contents = std::fs::read(Path::new(&project.path).join(file_path3))?; assert_eq!("file3\n", String::from_utf8(contents)?); @@ -1461,7 +1451,6 @@ fn upstream_integrated_vbranch() -> Result<()> { "integrated commit", None, None, - None, false, )?; commit( @@ -1470,7 +1459,6 @@ fn upstream_integrated_vbranch() -> Result<()> { "non-integrated commit", None, None, - None, false, )?; @@ -1531,7 +1519,6 @@ fn commit_same_hunk_twice() -> Result<()> { "first commit to test.txt", None, None, - None, false, )?; @@ -1567,7 +1554,6 @@ fn commit_same_hunk_twice() -> Result<()> { "second commit to test.txt", None, None, - None, false, )?; @@ -1626,7 +1612,6 @@ fn commit_same_file_twice() -> Result<()> { "first commit to test.txt", None, None, - None, false, )?; @@ -1662,7 +1647,6 @@ fn commit_same_file_twice() -> Result<()> { "second commit to test.txt", None, None, - None, false, )?; @@ -1721,7 +1705,6 @@ fn commit_partial_by_hunk() -> Result<()> { "first commit to test.txt", Some(&"test.txt:1-6".parse::().unwrap()), None, - None, false, )?; @@ -1740,7 +1723,6 @@ fn commit_partial_by_hunk() -> Result<()> { "second commit to test.txt", Some(&"test.txt:16-22".parse::().unwrap()), None, - None, false, )?; @@ -1799,7 +1781,6 @@ fn commit_partial_by_file() -> Result<()> { "branch1 commit", None, None, - None, false, )?; @@ -1867,7 +1848,6 @@ fn commit_add_and_delete_files() -> Result<()> { "branch1 commit", None, None, - None, false, )?; @@ -1933,7 +1913,6 @@ fn commit_executable_and_symlinks() -> Result<()> { "branch1 commit", None, None, - None, false, )?; @@ -2110,7 +2089,6 @@ fn pre_commit_hook_rejection() -> Result<()> { &branch1_id, "test commit", None, - Some(suite.keys.get_or_create()?).as_ref(), None, true, ); @@ -2175,7 +2153,6 @@ fn post_commit_hook() -> Result<()> { &branch1_id, "test commit", None, - Some(suite.keys.get_or_create()?).as_ref(), None, true, )?; @@ -2224,7 +2201,6 @@ fn commit_msg_hook_rejection() -> Result<()> { &branch1_id, "test commit", None, - Some(suite.keys.get_or_create()?).as_ref(), None, true, ); diff --git a/crates/gitbutler-git/Cargo.toml b/crates/gitbutler-git/Cargo.toml index 2c8e384c0..d124aaf6b 100644 --- a/crates/gitbutler-git/Cargo.toml +++ b/crates/gitbutler-git/Cargo.toml @@ -29,6 +29,7 @@ test-askpass-path = [] thiserror.workspace = true serde = { workspace = true, optional = true } tokio = { workspace = true, optional = true, features = ["process", "time", "io-util", "net", "fs"] } +uuid.workspace = true rand = "0.8.5" futures = "0.3.30" sysinfo = "0.30.11" diff --git a/crates/gitbutler-git/src/lib.rs b/crates/gitbutler-git/src/lib.rs index ef34cc903..847fc302b 100644 --- a/crates/gitbutler-git/src/lib.rs +++ b/crates/gitbutler-git/src/lib.rs @@ -24,5 +24,5 @@ pub use self::executor::tokio; pub use self::{ error::Error, refspec::{Error as RefSpecError, RefSpec}, - repository::{fetch, push}, + repository::{fetch, push, sign_commit}, }; diff --git a/crates/gitbutler-git/src/repository.rs b/crates/gitbutler-git/src/repository.rs index 288331e52..eacd1b3d6 100644 --- a/crates/gitbutler-git/src/repository.rs +++ b/crates/gitbutler-git/src/repository.rs @@ -59,7 +59,7 @@ pub type Error = RepositoryError< #[cold] async fn execute_with_auth_harness( repo_path: P, - executor: E, + executor: &E, args: &[&str], envs: Option>, mut on_prompt: F, @@ -155,7 +155,7 @@ where .or_else(|| std::env::var("GIT_SSH").ok()) { Some(v) => v, - None => get_core_sshcommand(&executor, &repo_path) + None => get_core_sshcommand(executor, &repo_path) .await .unwrap_or_else(|| "ssh".into()), }; @@ -300,7 +300,7 @@ where args.push(&refspec); let (status, stdout, stderr) = - execute_with_auth_harness(repo_path, executor, &args, None, on_prompt, extra).await?; + execute_with_auth_harness(repo_path, &executor, &args, None, on_prompt, extra).await?; if status == 0 { Ok(()) @@ -362,7 +362,7 @@ where } let (status, stdout, stderr) = - execute_with_auth_harness(repo_path, executor, &args, None, on_prompt, extra).await?; + execute_with_auth_harness(repo_path, &executor, &args, None, on_prompt, extra).await?; if status == 0 { Ok(()) @@ -392,6 +392,118 @@ where } } +/// Signs the given commit-ish in the repository at the given path. +/// Returns the newly signed commit SHA. +/// +/// Any prompts for the user are passed to the asynchronous callback `on_prompt`, +/// which should return the user's response or `None` if the operation should be +/// aborted, in which case an `Err` value is returned from this function. +pub async fn sign_commit( + repo_path: P, + executor: E, + base_commitish: String, + on_prompt: F, + extra: Extra, +) -> Result>> +where + P: AsRef, + E: GitExecutor, + F: FnMut(String, Extra) -> Fut, + Fut: std::future::Future>, + Extra: Send + Clone, +{ + let repo_path = repo_path.as_ref(); + + // First, create a worktree to perform the commit. + let worktree_path = repo_path + .join(".git") + .join("gitbutler") + .join(".wt") + .join(uuid::Uuid::new_v4().to_string()); + let args = [ + "worktree", + "add", + "--detach", + "--no-checkout", + worktree_path.to_str().unwrap(), + base_commitish.as_str(), + ]; + let (status, stdout, stderr) = executor + .execute(&args, repo_path, None) + .await + .map_err(Error::::Exec)?; + if status != 0 { + return Err(Error::::Failed { + status, + args: args.into_iter().map(Into::into).collect(), + stdout, + stderr, + })?; + } + + // Now, perform the commit. + let args = [ + "commit", + "--amend", + "-S", + "-o", + "--no-edit", + "--no-verify", + "--no-post-rewrite", + "--allow-empty", + "--allow-empty-message", + ]; + let (status, stdout, stderr) = + execute_with_auth_harness(&worktree_path, &executor, &args, None, on_prompt, extra).await?; + if status != 0 { + return Err(Error::::Failed { + status, + args: args.into_iter().map(Into::into).collect(), + stdout, + stderr, + })?; + } + + // Get the commit hash that was generated + let args = ["rev-parse", "--verify", "HEAD"]; + let (status, stdout, stderr) = executor + .execute(&args, &worktree_path, None) + .await + .map_err(Error::::Exec)?; + if status != 0 { + return Err(Error::::Failed { + status, + args: args.into_iter().map(Into::into).collect(), + stdout, + stderr, + })?; + } + + let commit_hash = stdout.trim().to_string(); + + // Finally, remove the worktree + let args = [ + "worktree", + "remove", + "--force", + worktree_path.to_str().unwrap(), + ]; + let (status, stdout, stderr) = executor + .execute(&args, repo_path, None) + .await + .map_err(Error::::Exec)?; + if status != 0 { + return Err(Error::::Failed { + status, + args: args.into_iter().map(Into::into).collect(), + stdout, + stderr, + })?; + } + + Ok(commit_hash) +} + async fn get_core_sshcommand>( executor: &E, cwd: P, diff --git a/crates/gitbutler-tauri/src/main.rs b/crates/gitbutler-tauri/src/main.rs index 18258c2f3..ca981ca13 100644 --- a/crates/gitbutler-tauri/src/main.rs +++ b/crates/gitbutler-tauri/src/main.rs @@ -140,7 +140,6 @@ fn main() { app_handle.manage(gitbutler_core::virtual_branches::controller::Controller::new( projects_controller.clone(), users_controller.clone(), - keys_controller.clone(), git_credentials_controller.clone(), )); diff --git a/crates/gitbutler-watcher/tests/handler/mod.rs b/crates/gitbutler-watcher/tests/handler/mod.rs index 0dd6b9c12..727ee1c51 100644 --- a/crates/gitbutler-watcher/tests/handler/mod.rs +++ b/crates/gitbutler-watcher/tests/handler/mod.rs @@ -37,7 +37,6 @@ mod support { let vbranch_controller = virtual_branches::Controller::new( inner.projects.clone(), inner.users.clone(), - inner.keys.clone(), git_credentials_helper, ); let assets_proxy = assets::Proxy::new(tmp.path().to_owned());