From c5846e05aa54f0601ac7b8e2e59bcf1ffaa305f1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 3 Aug 2022 16:13:37 +0800 Subject: [PATCH] feat!: `gix rev resolve --explain` (#427) --- README.md | 2 +- gitoxide-core/src/repository/revision/mod.rs | 30 ++----------------- .../repository/revision/previous_branches.rs | 23 ++++++++++++++ .../revision/{parse.rs => resolve.rs} | 13 ++++++-- src/plumbing/main.rs | 6 ++-- src/plumbing/options.rs | 11 +++++-- 6 files changed, 49 insertions(+), 36 deletions(-) create mode 100644 gitoxide-core/src/repository/revision/previous_branches.rs rename gitoxide-core/src/repository/revision/{parse.rs => resolve.rs} (78%) diff --git a/README.md b/README.md index 4f079e5353..01eec38a24 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Please see _'Development Status'_ for a listing of all crates and their capabili * [x] **entries** - display all entries of the aggregated mailmap git would use for substitution * **revision** * [x] **explain** - show what would be done while parsing a revision specification like `HEAD~1` - * [x] **parse** - Show which objects a revspec resolves to + * [x] **resolve** - show which objects a revspec resolves to, similar to `git rev-parse` but faster and with much better error handling * [x] **previous-branches** - list all previously checked out branches, powered by the ref-log. * **free** - no git repository necessary * **pack** diff --git a/gitoxide-core/src/repository/revision/mod.rs b/gitoxide-core/src/repository/revision/mod.rs index 5f693bbc8c..3e8937e29f 100644 --- a/gitoxide-core/src/repository/revision/mod.rs +++ b/gitoxide-core/src/repository/revision/mod.rs @@ -1,32 +1,8 @@ mod explain; pub use explain::explain; -pub mod parse; -pub use parse::function::parse; +pub mod resolve; +pub use resolve::function::resolve; -mod previous_branches { - use anyhow::Context; - use git_repository as git; - - use crate::OutputFormat; - - pub fn function(repo: git::Repository, mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> { - let branches = repo - .head()? - .prior_checked_out_branches()? - .context("The reflog for HEAD is required")?; - match format { - OutputFormat::Human => { - for (name, id) in branches { - writeln!(out, "{} {}", id, name)?; - } - } - #[cfg(feature = "serde1")] - OutputFormat::Json => { - serde_json::to_writer_pretty(&mut out, &branches)?; - } - } - Ok(()) - } -} +mod previous_branches; pub use previous_branches::function as previous_branches; diff --git a/gitoxide-core/src/repository/revision/previous_branches.rs b/gitoxide-core/src/repository/revision/previous_branches.rs new file mode 100644 index 0000000000..1cd39aa6e8 --- /dev/null +++ b/gitoxide-core/src/repository/revision/previous_branches.rs @@ -0,0 +1,23 @@ +use anyhow::Context; +use git_repository as git; + +use crate::OutputFormat; + +pub fn function(repo: git::Repository, mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> { + let branches = repo + .head()? + .prior_checked_out_branches()? + .context("The reflog for HEAD is required")?; + match format { + OutputFormat::Human => { + for (name, id) in branches { + writeln!(out, "{} {}", id, name)?; + } + } + #[cfg(feature = "serde1")] + OutputFormat::Json => { + serde_json::to_writer_pretty(&mut out, &branches)?; + } + } + Ok(()) +} diff --git a/gitoxide-core/src/repository/revision/parse.rs b/gitoxide-core/src/repository/revision/resolve.rs similarity index 78% rename from gitoxide-core/src/repository/revision/parse.rs rename to gitoxide-core/src/repository/revision/resolve.rs index 3683f358ca..ef4e89ebab 100644 --- a/gitoxide-core/src/repository/revision/parse.rs +++ b/gitoxide-core/src/repository/revision/resolve.rs @@ -2,27 +2,33 @@ use crate::OutputFormat; pub struct Options { pub format: OutputFormat, + pub explain: bool, } pub(crate) mod function { + use anyhow::bail; use std::ffi::OsString; use git_repository as git; use super::Options; + use crate::repository::revision; use crate::OutputFormat; - pub fn parse( + pub fn resolve( mut repo: git::Repository, specs: Vec, mut out: impl std::io::Write, - Options { format }: Options, + Options { format, explain }: Options, ) -> anyhow::Result<()> { repo.object_cache_size_if_unset(1024 * 1024); match format { OutputFormat::Human => { for spec in specs { + if explain { + return revision::explain(spec, out); + } let spec = git::path::os_str_into_bstr(&spec)?; let spec = repo.rev_parse(spec)?.detach(); writeln!(out, "{spec}")?; @@ -30,6 +36,9 @@ pub(crate) mod function { } #[cfg(feature = "serde1")] OutputFormat::Json => { + if explain { + bail!("Explanations are only for human consumption") + } serde_json::to_writer_pretty( &mut out, &specs diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index 1ee83043e9..029f9a071e 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -532,18 +532,18 @@ pub fn main() -> Result<()> { None, move |_progress, out, _err| core::repository::revision::explain(spec, out), ), - revision::Subcommands::Parse { specs } => prepare_and_run( + revision::Subcommands::Resolve { specs, explain } => prepare_and_run( "revision-parse", verbose, progress, progress_keep_open, None, move |_progress, out, _err| { - core::repository::revision::parse( + core::repository::revision::resolve( repository()?, specs, out, - core::repository::revision::parse::Options { format }, + core::repository::revision::resolve::Options { format, explain }, ) }, ), diff --git a/src/plumbing/options.rs b/src/plumbing/options.rs index 98faa84832..ecdcb0fb73 100644 --- a/src/plumbing/options.rs +++ b/src/plumbing/options.rs @@ -185,9 +185,14 @@ pub mod revision { /// Provide the revision specification like `@~1` to explain. Explain { spec: std::ffi::OsString }, /// Try to resolve the given revspec and print the object names. - #[clap(visible_alias = "query")] - Parse { - #[clap(min_values = 1)] + #[clap(visible_alias = "query", visible_alias = "parse")] + Resolve { + /// If set, instead of resolving a rev-spec, explain what would be done for the first spec. + /// Equivalent to the `explain` subcommand. + #[clap(short = 'e', long)] + explain: bool, + /// rev-specs like `@`, `@~1` or `HEAD^2`. + #[clap(required = true)] specs: Vec, }, /// Return the names and hashes of all previously checked-out branches.