diff --git a/CHANGELOG.md b/CHANGELOG.md index 6049d54019..b7f5a4da1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Added - add `trace-libgit` feature to make git tracing optional [[@dm9pZCAq](https://github.com/dm9pZCAq)] ([#902](https://github.com/extrawurst/gitui/issues/902)) +- support merging and rebasing remote branches ([#920](https://github.com/extrawurst/gitui/issues/920)) ## [0.18] - 2021-10-11 diff --git a/asyncgit/src/sync/merge.rs b/asyncgit/src/sync/merge.rs index 10d74d6415..dd31656592 100644 --- a/asyncgit/src/sync/merge.rs +++ b/asyncgit/src/sync/merge.rs @@ -46,12 +46,16 @@ pub fn abort_merge(repo_path: &str) -> Result<()> { } /// -pub fn merge_branch(repo_path: &str, branch: &str) -> Result<()> { +pub fn merge_branch( + repo_path: &str, + branch: &str, + branch_type: BranchType, +) -> Result<()> { scope_time!("merge_branch"); let repo = utils::repo(repo_path)?; - merge_branch_repo(&repo, branch)?; + merge_branch_repo(&repo, branch, branch_type)?; Ok(()) } @@ -89,8 +93,9 @@ pub fn abort_pending_rebase(repo_path: &str) -> Result<()> { pub fn merge_branch_repo( repo: &Repository, branch: &str, + branch_type: BranchType, ) -> Result<()> { - let branch = repo.find_branch(branch, BranchType::Local)?; + let branch = repo.find_branch(branch, branch_type)?; let annotated = repo.reference_to_annotated_commit(&branch.into_reference())?; @@ -162,7 +167,7 @@ mod tests { write_commit_file(&repo, "test.txt", "test2", "commit2"); - merge_branch(repo_path, "master").unwrap(); + merge_branch(repo_path, "master", BranchType::Local).unwrap(); let msg = merge_msg(repo_path).unwrap(); diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index 2eb32bb34b..6c9ca156e7 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -51,6 +51,7 @@ pub use config::{ ShowUntrackedFilesConfig, }; pub use diff::get_diff_commit; +pub use git2::BranchType; pub use hooks::{ hooks_commit_msg, hooks_post_commit, hooks_pre_commit, HookResult, }; diff --git a/asyncgit/src/sync/rebase.rs b/asyncgit/src/sync/rebase.rs index b98bda0814..fdccafda69 100644 --- a/asyncgit/src/sync/rebase.rs +++ b/asyncgit/src/sync/rebase.rs @@ -12,19 +12,21 @@ use super::CommitId; pub fn rebase_branch( repo_path: &str, branch: &str, + branch_type: BranchType, ) -> Result { scope_time!("rebase_branch"); let repo = utils::repo(repo_path)?; - rebase_branch_repo(&repo, branch) + rebase_branch_repo(&repo, branch, branch_type) } fn rebase_branch_repo( repo: &Repository, branch_name: &str, + branch_type: BranchType, ) -> Result { - let branch = repo.find_branch(branch_name, BranchType::Local)?; + let branch = repo.find_branch(branch_name, branch_type)?; let annotated = repo.reference_to_annotated_commit(&branch.into_reference())?; @@ -268,7 +270,8 @@ mod test_conflict_free_rebase { checkout_branch(repo_path, "refs/heads/foo").unwrap(); - let res = rebase_branch(repo_path, "master"); + let res = + rebase_branch(repo_path, "master", BranchType::Local); assert!(matches!(res.unwrap(), RebaseState::Conflicted)); @@ -288,6 +291,7 @@ mod test_rebase { tests::{repo_init, write_commit_file}, RepoState, }; + use git2::BranchType; #[test] fn test_conflicted_abort() { @@ -312,7 +316,8 @@ mod test_rebase { // rebase - let r = rebase_branch(repo_path, "master").unwrap(); + let r = rebase_branch(repo_path, "master", BranchType::Local) + .unwrap(); assert_eq!(r, RebaseState::Conflicted); assert_eq!(repo_state(repo_path).unwrap(), RepoState::Rebase); diff --git a/src/components/branchlist.rs b/src/components/branchlist.rs index 64a25cf574..d804621da7 100644 --- a/src/components/branchlist.rs +++ b/src/components/branchlist.rs @@ -18,8 +18,8 @@ use asyncgit::{ checkout_remote_branch, BranchDetails, LocalBranch, RemoteBranch, }, - checkout_branch, get_branches_info, BranchInfo, CommitId, - RepoState, + checkout_branch, get_branches_info, BranchInfo, BranchType, + CommitId, RepoState, }, AsyncGitNotification, CWD, }; @@ -178,7 +178,7 @@ impl Component for BranchListComponent { &self.key_config, ), !self.selection_is_cur_branch(), - self.local, + true, )); out.push(CommandInfo::new( @@ -186,7 +186,7 @@ impl Component for BranchListComponent { &self.key_config, ), !self.selection_is_cur_branch(), - self.local, + true, )); out.push(CommandInfo::new( @@ -368,7 +368,11 @@ impl BranchListComponent { if let Some(branch) = self.branches.get(usize::from(self.selection)) { - sync::merge_branch(CWD, &branch.name)?; + sync::merge_branch( + CWD, + &branch.name, + self.get_branch_type(), + )?; self.hide_and_switch_tab()?; } @@ -380,7 +384,11 @@ impl BranchListComponent { if let Some(branch) = self.branches.get(usize::from(self.selection)) { - sync::rebase_branch(CWD, &branch.name)?; + sync::rebase_branch( + CWD, + &branch.name, + self.get_branch_type(), + )?; self.hide_and_switch_tab()?; } @@ -388,6 +396,14 @@ impl BranchListComponent { Ok(()) } + const fn get_branch_type(&self) -> BranchType { + if self.local { + BranchType::Local + } else { + BranchType::Remote + } + } + fn hide_and_switch_tab(&mut self) -> Result<()> { self.hide(); self.queue.push(InternalEvent::Update(NeedsUpdate::ALL));