From 098b0258fdd581c750099cb463adbddb57843388 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 8 Mar 2024 16:49:03 +0000 Subject: feat(send): compare against origin/main vs main catch more errors when proposed commits are not connected to origin/main branch improve default selected commits when on main branch --- src/git.rs | 92 ++++++++++++++++++++++++++++++++++++++++-------- src/sub_commands/list.rs | 2 +- src/sub_commands/pull.rs | 2 +- src/sub_commands/push.rs | 2 +- src/sub_commands/send.rs | 29 ++++++++------- 5 files changed, 97 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/git.rs b/src/git.rs index 42297be..bb2b8e7 100644 --- a/src/git.rs +++ b/src/git.rs @@ -32,10 +32,13 @@ impl Repo { pub trait RepoActions { fn get_path(&self) -> Result<&Path>; fn get_origin_url(&self) -> Result; + fn get_remote_branch_names(&self) -> Result>; fn get_local_branch_names(&self) -> Result>; + fn get_origin_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)>; + fn get_local_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)>; fn get_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)>; fn get_checked_out_branch_name(&self) -> Result; - fn get_tip_of_local_branch(&self, branch_name: &str) -> Result; + fn get_tip_of_branch(&self, branch_name: &str) -> Result; fn get_root_commit(&self) -> Result; fn does_commit_exist(&self, commit: &str) -> Result; fn get_head_commit(&self) -> Result; @@ -91,7 +94,30 @@ impl RepoActions for Repo { .to_string()) } - fn get_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)> { + fn get_origin_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)> { + let main_branch_name = { + let remote_branches = self + .get_remote_branch_names() + .context("cannot find any local branches")?; + if remote_branches.contains(&"origin/main".to_string()) { + "origin/main" + } else if remote_branches.contains(&"origin/master".to_string()) { + "origin/master" + } else { + bail!("no main or master branch locally in this git repository to initiate from",) + } + }; + + let tip = self + .get_tip_of_branch(main_branch_name) + .context(format!( + "branch {main_branch_name} was listed as a remote branch but cannot get its tip commit id", + ))?; + + Ok((main_branch_name, tip)) + } + + fn get_local_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)> { let main_branch_name = { let local_branches = self .get_local_branch_names() @@ -106,7 +132,7 @@ impl RepoActions for Repo { }; let tip = self - .get_tip_of_local_branch(main_branch_name) + .get_tip_of_branch(main_branch_name) .context(format!( "branch {main_branch_name} was listed as a local branch but cannot get its tip commit id", ))?; @@ -114,6 +140,18 @@ impl RepoActions for Repo { Ok((main_branch_name, tip)) } + fn get_main_or_master_branch(&self) -> Result<(&str, Sha1Hash)> { + if let Ok(main_tuple) = self + .get_origin_main_or_master_branch() + .context("the default branches (main or master) do not exist") + { + Ok(main_tuple) + } else { + self.get_main_or_master_branch() + .context("the default branches (main or master) do not exist") + } + } + fn get_local_branch_names(&self) -> Result> { let local_branches = self .git_repo @@ -131,6 +169,23 @@ impl RepoActions for Repo { Ok(branch_names) } + fn get_remote_branch_names(&self) -> Result> { + let remote_branches = self + .git_repo + .branches(Some(git2::BranchType::Remote)) + .context("getting GitRepo branches should not error even for a blank repository")?; + + let mut branch_names = vec![]; + + for iter in remote_branches { + let branch = iter?.0; + if let Some(name) = branch.name()? { + branch_names.push(name.to_string()); + } + } + Ok(branch_names) + } + fn get_checked_out_branch_name(&self) -> Result { Ok(self .git_repo @@ -140,11 +195,18 @@ impl RepoActions for Repo { .to_string()) } - fn get_tip_of_local_branch(&self, branch_name: &str) -> Result { - let branch = self + fn get_tip_of_branch(&self, branch_name: &str) -> Result { + let branch = if let Ok(branch) = self .git_repo .find_branch(branch_name, git2::BranchType::Local) - .context(format!("cannot find branch {branch_name}"))?; + .context(format!("cannot find local branch {branch_name}")) + { + branch + } else { + self.git_repo + .find_branch(branch_name, git2::BranchType::Remote) + .context(format!("cannot find local or remote branch {branch_name}"))? + }; Ok(oid_to_sha1(&branch.into_reference().peel_to_commit()?.id())) } @@ -407,7 +469,7 @@ impl RepoActions for Repo { branch_name: &str, patch_and_ancestors: Vec, ) -> Result> { - let branch_tip_result = self.get_tip_of_local_branch(branch_name); + let branch_tip_result = self.get_tip_of_branch(branch_name); // filter out existing ancestors in branch let mut patches_to_apply: Vec = patch_and_ancestors @@ -1663,7 +1725,7 @@ mod tests { let git_repo = Repo::from_path(&test_repo.dir)?; git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( - git_repo.get_tip_of_local_branch(BRANCH_NAME)?, + git_repo.get_tip_of_branch(BRANCH_NAME)?, oid_to_sha1(&original_repo.git_repo.head()?.peel_to_commit()?.id(),), ); Ok(()) @@ -1677,11 +1739,11 @@ mod tests { let existing_branch = test_repo.get_checked_out_branch_name()?; let git_repo = Repo::from_path(&test_repo.dir)?; let previous_tip_of_existing_branch = - git_repo.get_tip_of_local_branch(existing_branch.as_str())?; + git_repo.get_tip_of_branch(existing_branch.as_str())?; git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( previous_tip_of_existing_branch, - git_repo.get_tip_of_local_branch(existing_branch.as_str())?, + git_repo.get_tip_of_branch(existing_branch.as_str())?, ); Ok(()) } @@ -1744,7 +1806,7 @@ mod tests { let git_repo = Repo::from_path(&test_repo.dir)?; git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( - git_repo.get_tip_of_local_branch(BRANCH_NAME)?, + git_repo.get_tip_of_branch(BRANCH_NAME)?, oid_to_sha1(&original_repo.git_repo.head()?.peel_to_commit()?.id(),), ); Ok(()) @@ -1760,11 +1822,11 @@ mod tests { let existing_branch = test_repo.get_checked_out_branch_name()?; let git_repo = Repo::from_path(&test_repo.dir)?; let previous_tip_of_existing_branch = - git_repo.get_tip_of_local_branch(existing_branch.as_str())?; + git_repo.get_tip_of_branch(existing_branch.as_str())?; git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( previous_tip_of_existing_branch, - git_repo.get_tip_of_local_branch(existing_branch.as_str())?, + git_repo.get_tip_of_branch(existing_branch.as_str())?, ); Ok(()) } @@ -1800,7 +1862,7 @@ mod tests { git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( - git_repo.get_tip_of_local_branch(BRANCH_NAME)?, + git_repo.get_tip_of_branch(BRANCH_NAME)?, oid_to_sha1(&original_repo.git_repo.head()?.peel_to_commit()?.id(),), ); Ok(()) @@ -1832,7 +1894,7 @@ mod tests { git_repo.apply_patch_chain(BRANCH_NAME, patch_events)?; assert_eq!( - git_repo.get_tip_of_local_branch(BRANCH_NAME)?, + git_repo.get_tip_of_branch(BRANCH_NAME)?, oid_to_sha1(&original_repo.git_repo.head()?.peel_to_commit()?.id(),), ); Ok(()) diff --git a/src/sub_commands/list.rs b/src/sub_commands/list.rs index ad5a28d..102c3bd 100644 --- a/src/sub_commands/list.rs +++ b/src/sub_commands/list.rs @@ -274,7 +274,7 @@ pub async fn launch(_cli_args: &Cli, _args: &SubCommandArgs) -> Result<()> { }; } - let local_branch_tip = git_repo.get_tip_of_local_branch(&cover_letter.branch_name)?; + let local_branch_tip = git_repo.get_tip_of_branch(&cover_letter.branch_name)?; // up-to-date if proposal_tip.eq(&local_branch_tip) { diff --git a/src/sub_commands/pull.rs b/src/sub_commands/pull.rs index daae37f..716e6c5 100644 --- a/src/sub_commands/pull.rs +++ b/src/sub_commands/pull.rs @@ -60,7 +60,7 @@ pub async fn launch() -> Result<()> { get_most_recent_patch_with_ancestors(commit_events.clone()) .context("cannot get most recent patch for proposal")?; - let local_branch_tip = git_repo.get_tip_of_local_branch(&branch_name)?; + let local_branch_tip = git_repo.get_tip_of_branch(&branch_name)?; let (main_branch_name, master_tip) = git_repo.get_main_or_master_branch()?; diff --git a/src/sub_commands/push.rs b/src/sub_commands/push.rs index fdaab8e..651b250 100644 --- a/src/sub_commands/push.rs +++ b/src/sub_commands/push.rs @@ -75,7 +75,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { let most_recent_proposal_patch_chain = get_most_recent_patch_with_ancestors(commit_events) .context("cannot get most recent patch for proposal")?; - let branch_tip = git_repo.get_tip_of_local_branch(&branch_name)?; + let branch_tip = git_repo.get_tip_of_branch(&branch_name)?; let most_recent_patch_commit_id = str_to_sha1( &get_commit_id_from_patch( diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs index 9b44cc3..81cecd8 100644 --- a/src/sub_commands/send.rs +++ b/src/sub_commands/send.rs @@ -53,13 +53,13 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { println!("creating proposal revision for: {id}"); } + let (main_branch_name, main_tip) = git_repo + .get_main_or_master_branch() + .context("the default branches (main or master) do not exist")?; + let mut commits: Vec = { if args.since_or_range.is_empty() { let branch_name = git_repo.get_checked_out_branch_name()?; - let (main_branch_name, main_tip) = git_repo - .get_main_or_master_branch() - .context("the default branches (main or master) do not exist")?; - let proposed_commits = if branch_name.eq(main_branch_name) { vec![main_tip] } else { @@ -88,9 +88,6 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { ); } - let (main_branch_name, main_tip) = git_repo - .get_main_or_master_branch() - .context("the default branches (main or master) do not exist")?; let (first_commit_ahead, behind) = git_repo.get_commits_ahead_behind(&main_tip, commits.last().context("no commits")?)?; @@ -385,7 +382,7 @@ fn choose_commits(git_repo: &Repo, proposed_commits: Vec) -> Result ( name.to_string(), git_repo - .get_tip_of_local_branch(name) + .get_tip_of_branch(name) .context(format!("cannot find from_branch '{name}'"))?, ), None => ( @@ -937,7 +942,7 @@ fn identify_ahead_behind( Some(name) => ( name.to_string(), git_repo - .get_tip_of_local_branch(name) + .get_tip_of_branch(name) .context(format!("cannot find to_branch '{name}'"))?, ), None => { -- cgit v1.2.3