From 886289f98003f935d774a40f6db746ae70649936 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 17 Oct 2023 09:22:26 +0200 Subject: [PATCH] feat: add `gix free discover` to inform about repository discovery. It's mainly to better understand what's causing certain failures if a repository can't be opened, in different modes of operations. --- gitoxide-core/src/discover.rs | 59 +++++++++++++++++++++++++++++++++++ gitoxide-core/src/lib.rs | 3 ++ src/plumbing/main.rs | 10 ++++++ src/plumbing/options/free.rs | 2 ++ 4 files changed, 74 insertions(+) create mode 100644 gitoxide-core/src/discover.rs diff --git a/gitoxide-core/src/discover.rs b/gitoxide-core/src/discover.rs new file mode 100644 index 00000000000..d1ab7d3d23c --- /dev/null +++ b/gitoxide-core/src/discover.rs @@ -0,0 +1,59 @@ +use std::path::Path; + +pub fn discover(repo: &Path, mut out: impl std::io::Write) -> anyhow::Result<()> { + let mut has_err = false; + writeln!(out, "open (strict) {}:", repo.display())?; + has_err |= print_result( + &mut out, + gix::open_opts(repo, gix::open::Options::default().strict_config(true)), + )?; + + if has_err { + writeln!(out, "open (lenient) {}:", repo.display())?; + has_err |= print_result( + &mut out, + gix::open_opts(repo, gix::open::Options::default().strict_config(false)), + )?; + } + + writeln!(out)?; + writeln!(out, "discover from {}:", repo.display())?; + has_err |= print_result(&mut out, gix::discover(repo))?; + + writeln!(out)?; + writeln!(out, "discover (plumbing) from {}:", repo.display())?; + has_err |= print_result(&mut out, gix::discover::upwards(repo))?; + + if has_err { + writeln!(out)?; + anyhow::bail!("At least one operation failed") + } + + Ok(()) +} + +fn print_result(mut out: impl std::io::Write, res: Result) -> std::io::Result +where + T: std::fmt::Debug, + E: std::error::Error + Send + Sync + 'static, +{ + let mut has_err = false; + let to_print = match res { + Ok(good) => { + format!("{good:#?}") + } + Err(err) => { + has_err = true; + format!("{:?}", anyhow::Error::from(err)) + } + }; + indent(&mut out, to_print)?; + Ok(has_err) +} + +fn indent(mut out: impl std::io::Write, msg: impl Into) -> std::io::Result<()> { + for line in msg.into().lines() { + writeln!(out, "\t{line}")?; + } + Ok(()) +} diff --git a/gitoxide-core/src/lib.rs b/gitoxide-core/src/lib.rs index 58e688ea983..b4dc9da5365 100644 --- a/gitoxide-core/src/lib.rs +++ b/gitoxide-core/src/lib.rs @@ -79,5 +79,8 @@ pub mod pack; pub mod query; pub mod repository; +mod discover; +pub use discover::discover; + #[cfg(all(feature = "async-client", feature = "blocking-client"))] compile_error!("Cannot set both 'blocking-client' and 'async-client' features as they are mutually exclusive"); diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index 94b085dd85e..677ec60fe0c 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -72,6 +72,7 @@ pub fn main() -> Result<()> { let object_hash = args.object_hash; let config = args.config; let repository = args.repository; + let repository_path = repository.clone(); enum Mode { Strict, StrictWithGitInstallConfig, @@ -449,6 +450,15 @@ pub fn main() -> Result<()> { ) .map(|_| ()), Subcommands::Free(subcommands) => match subcommands { + free::Subcommands::Discover => prepare_and_run( + "discover", + trace, + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, _err| core::discover(&repository_path, out), + ), free::Subcommands::CommitGraph(cmd) => match cmd { free::commitgraph::Subcommands::Verify { path, statistics } => prepare_and_run( "commitgraph-verify", diff --git a/src/plumbing/options/free.rs b/src/plumbing/options/free.rs index 64aa443d4de..083dd943b34 100644 --- a/src/plumbing/options/free.rs +++ b/src/plumbing/options/free.rs @@ -14,6 +14,8 @@ pub enum Subcommands { Pack(pack::Subcommands), /// Subcommands for interacting with a worktree index, typically at .git/index Index(index::Platform), + /// Show information about repository discovery and when opening a repository at the current path. + Discover, } ///