From 0b88bac82c4be3d2536949c7679d7c0bac3f6f18 Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Fri, 24 Nov 2023 16:20:31 +0000 Subject: [PATCH] Set the default target branch based on `init.defaultBranch` Fixes #6. --- src/config.rs | 26 ++++++++++++++++++++++++++ src/lib.rs | 19 ++++++++++++++++--- src/main.rs | 9 +++++---- 3 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 src/config.rs diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..745b67f --- /dev/null +++ b/src/config.rs @@ -0,0 +1,26 @@ +use std::path::Path; + +use anyhow::Result; +use git_commands::git; + +use crate::trim::TrimAsciiWhitespace; + +/// Get the default branch name from Git config's `init.defaultBranch` setting, +/// falling back to 'master' if it isn't set. This should help handle default +/// branch names that are more awoke. +pub fn default_branch_name(for_path: &Path) -> Result { + let output = git( + &[ + "--no-pager", + "config", + "--default", + "master", + "--get", + "init.defaultBranch", + ], + for_path, + )? + .stdout; + let output = std::str::from_utf8(output.trim_ascii_whitespace())?; + Ok(output.to_owned()) +} diff --git a/src/lib.rs b/src/lib.rs index 31f4c9a..f52e3cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; +mod config; +use config::*; mod conflicts; use conflicts::*; mod glob; @@ -42,7 +44,7 @@ fn set_committer_date_to_now() { /// pub fn autorebase( path: &Path, - onto_branch: &str, + onto_branch: Option<&str>, slow_conflict_detection: bool, include_non_local: bool, match_branches: Option<&str>, @@ -52,6 +54,16 @@ pub fn autorebase( bail!("Your Git installation is too old - version 2.23 or later is required"); } + // Get the target branch name in this priority order: + // + // 1. Set explicitly via `--onto` + // 2. The `init.defaultBranch` git config setting. + // 3. "master" + let onto_branch = match onto_branch { + Some(b) => b.to_owned(), + None => default_branch_name(path)?, + }; + // The first thing we do is set the commiter date to now. If we don't do this // then when we have two branch labels on the same commit, when they get // rebased they will be given different commiter dates which will mean they @@ -91,7 +103,8 @@ pub fn autorebase( let onto_branch_info = all_branches .iter() .find(|b| b.branch == onto_branch) - .ok_or_else(|| anyhow!("Couldn't find target branch '{}'", onto_branch))?; + .ok_or_else(|| anyhow!("Couldn't find target branch '{}'. You can set the default target \ + branch via 'git config init.defaultBranch' or use the --onto flag.", onto_branch))?; eprintln!("\r{}", "• Getting branches...".green()); // Print a summary of the branches, and simultaneously filter them. @@ -140,7 +153,7 @@ pub fn autorebase( &git_common_dir, &mut conflicts, &conflicts_path, - onto_branch, + &onto_branch, &autorebase_worktree_path, slow_conflict_detection, )?; diff --git a/src/main.rs b/src/main.rs index 2b6d35b..c60823f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,9 +11,10 @@ use std::env::current_dir; /// Automatically pull the master branch and rebase all branches without /// upstreams onto it. struct CliOptions { - /// the target branch to pull and rebase onto (typically "master" or "develop") - #[argh(option, default = "String::from(\"master\")")] - onto: String, + /// the target branch to pull and rebase onto; + /// defaults to `git config --get init.defaultBranch` or `master` if unset + #[argh(option)] + onto: Option, /// if there are conflicts, try rebasing commit by commit backwards from the /// target, instead of trying to determind the conflicting commit on the @@ -53,7 +54,7 @@ fn run() -> Result<()> { autorebase( ¤t_dir()?, - &options.onto, + options.onto.as_deref(), options.slow, options.include_non_local, options.match_branches.as_deref(),