diff --git a/src/main.rs b/src/main.rs index 01bba88..857374b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,18 @@ enum Subcommand { #[clap(flatten)] files: FileSelection, }, + /// Select the (local) mainline branch and the most recent tag. + /// + /// Many Git projects use tags to manage project releases and/or milestones. This command is + /// useful for viewing the set of changes since the most recent tag. This can be helpful when + /// for example, analyzing changes for determining which SemVer version to use for a next + /// release, performing risk assessments, or writing release notes. + SinceLastTag { + #[clap(long, short)] + base: Option, + #[clap(flatten)] + files: FileSelection, + }, /// Select a custom set of commit-ish refs. Select { /// Additional branches to include. @@ -150,22 +162,27 @@ fn main() { Ok(branches) }; + + let fallback_base = || -> git_glimpse::Result<_> { + let base = git_config("glimpse.base")?; + let base = base.unwrap_or_else(|| { + let default = "main"; + log::debug!( + "no base branch specified in command line or configuration, falling back to \ + {default:?}" + ); + default.to_owned() + }); + Ok(base) + }; + let (branches, files) = match subcommand { Subcommand::Stack { base, config, files: FileSelection { files }, } => { - let specified_base = base - .map(Ok) - .or_else(|| git_config("glimpse.base").transpose()) - .transpose()?; - let base = specified_base.as_deref().unwrap_or_else(|| { - let default = "main"; - log::debug!("no base branch specified in command line or configuration, falling back to {default:?}"); - default - }); - + let base = base.map(Ok).unwrap_or_else(fallback_base)?; let branches = if let Some(current_branch) = current_branch()? { let mut config = config; if current_branch == base { @@ -173,12 +190,12 @@ fn main() { } branches(&config, &|cmd| { if base != current_branch { - cmd.arg(base); + cmd.arg(&base); } cmd.arg(¤t_branch).arg("--all") })? } else { - let mut branches = branches(&config, &|cmd| cmd.arg(base).arg("--all"))?; + let mut branches = branches(&config, &|cmd| cmd.arg(&base).arg("--all"))?; branches.push("HEAD".to_owned()); branches }; @@ -188,6 +205,21 @@ fn main() { config, files: FileSelection { files }, } => (branches(&config, &|cmd| cmd)?, files), + Subcommand::SinceLastTag { + base, + files: FileSelection { files }, + } => { + let base = base.map(Ok).unwrap_or_else(fallback_base)?; + let branches = branches( + &PresetConfig { + select_upstreams: false, + select_pushes: false, + select_last_tag: true, + }, + &|cmd| cmd.arg(&base), + )?; + (branches, files) + } Subcommand::Select { branches, files: FileSelection { files },