diff --git a/Cargo.lock b/Cargo.lock index 584c283f848..39ac0fa2777 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1458,6 +1458,7 @@ dependencies = [ "is_ci", "log", "once_cell", + "serde", "signal-hook", "tempfile", "thiserror", diff --git a/gitoxide-core/src/repository/revision/explain.rs b/gitoxide-core/src/repository/revision/explain.rs index a8aae2ab1f8..23cce5b2a29 100644 --- a/gitoxide-core/src/repository/revision/explain.rs +++ b/gitoxide-core/src/repository/revision/explain.rs @@ -8,7 +8,7 @@ use git::revision::{ use git_repository as git; use std::ffi::OsString; -pub fn explain(_repo: git::Repository, spec: OsString, mut out: impl std::io::Write) -> anyhow::Result<()> { +pub fn explain(spec: OsString, mut out: impl std::io::Write) -> anyhow::Result<()> { let mut explain = Explain::new(&mut out); let spec = git::path::os_str_into_bstr(&spec)?; git::revision::spec::parse(spec, &mut explain)?; diff --git a/gitoxide-core/src/repository/revision/mod.rs b/gitoxide-core/src/repository/revision/mod.rs index 5e1065cbb34..d60ba7eb43f 100644 --- a/gitoxide-core/src/repository/revision/mod.rs +++ b/gitoxide-core/src/repository/revision/mod.rs @@ -1,2 +1,5 @@ mod explain; pub use explain::explain; + +pub mod parse; +pub use parse::function::parse; diff --git a/gitoxide-core/src/repository/revision/parse.rs b/gitoxide-core/src/repository/revision/parse.rs index e69de29bb2d..af4e54e3a09 100644 --- a/gitoxide-core/src/repository/revision/parse.rs +++ b/gitoxide-core/src/repository/revision/parse.rs @@ -0,0 +1,48 @@ +use crate::OutputFormat; + +pub struct Options { + pub format: OutputFormat, +} + +pub(crate) mod function { + use super::Options; + use crate::OutputFormat; + use git_repository as git; + use std::ffi::OsString; + + pub fn parse( + repo: git::Repository, + spec: OsString, + mut out: impl std::io::Write, + Options { format }: Options, + ) -> anyhow::Result<()> { + let spec = git::path::os_str_into_bstr(&spec)?; + let spec = git::RevSpec::from_bstr(spec.as_ref(), &repo)?.detach(); + + match format { + OutputFormat::Human => { + if let Some((kind, from, to)) = spec.range() { + writeln!(&mut out, "{}", from)?; + writeln!( + &mut out, + "{}{}", + matches!(kind, git::revision::spec::Kind::Range) + .then(|| "^") + .unwrap_or_default(), + to + )?; + if matches!(kind, git::revision::spec::Kind::Range) { + writeln!(out, "^TBD: compute and display merge base hash")?; + } + } else if let Some(rev) = spec.single() { + writeln!(&mut out, "{}", rev)?; + } + } + #[cfg(feature = "serde1")] + OutputFormat::Json => { + serde_json::to_writer_pretty(&mut out, &spec)?; + } + } + Ok(()) + } +} diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index b30a19098c1..4b44bda673a 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -161,13 +161,28 @@ pub fn main() -> Result<()> { let repository = git::ThreadSafeRepository::discover(repository)?; match cmd { repo::Subcommands::Revision { cmd } => match cmd { + repo::revision::Subcommands::Parse { spec } => prepare_and_run( + "repository-revision-parse", + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, _err| { + core::repository::revision::parse( + repository.into(), + spec, + out, + core::repository::revision::parse::Options { format }, + ) + }, + ), repo::revision::Subcommands::Explain { spec } => prepare_and_run( - "repository-commit-describe", + "repository-revision-explain", verbose, progress, progress_keep_open, None, - move |_progress, out, _err| core::repository::revision::explain(repository.into(), spec, out), + move |_progress, out, _err| core::repository::revision::explain(spec, out), ), }, repo::Subcommands::Commit { cmd } => match cmd { diff --git a/src/plumbing/options.rs b/src/plumbing/options.rs index 7a0f73b3e46..7dc3c31ff43 100644 --- a/src/plumbing/options.rs +++ b/src/plumbing/options.rs @@ -388,6 +388,9 @@ pub mod repo { pub enum Subcommands { /// 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 { spec: std::ffi::OsString }, } }