diff --git a/README.md b/README.md index 325bf0ef107..0d5d8bc417b 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,9 @@ Please see _'Development Status'_ for a listing of all crates and their capabili * **tree** * [x] **entries** - list tree entries for a single tree or recursively * [x] **info** - display tree statistics + * **odb** + * [x] **info** - display odb statistics + * [x] **entries** - display all object ids in the object database * **index** * [x] **entries** - show detailed entry information for human or machine consumption (via JSON) * [x] **verify** - check the index for consistency diff --git a/git-odb/src/lib.rs b/git-odb/src/lib.rs index 0a9ed4eefdb..b1f557cb424 100644 --- a/git-odb/src/lib.rs +++ b/git-odb/src/lib.rs @@ -127,6 +127,16 @@ impl Store { pub fn path(&self) -> &std::path::Path { &self.path } + + /// The kind of object hash to assume when dealing with pack indices and pack data files. + pub fn object_hash(&self) -> git_hash::Kind { + self.object_hash + } + + /// Whether or not we are allowed to use multi-pack indices + pub fn use_multi_pack_index(&self) -> bool { + self.use_multi_pack_index + } } /// Create a new cached handle to the object store with support for additional options. diff --git a/git-odb/src/store_impls/dynamic/types.rs b/git-odb/src/store_impls/dynamic/types.rs index 026bd1faeb9..a055cdc961e 100644 --- a/git-odb/src/store_impls/dynamic/types.rs +++ b/git-odb/src/store_impls/dynamic/types.rs @@ -391,6 +391,7 @@ pub(crate) struct MutableIndexAndPack { /// A snapshot about resource usage. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct Metrics { /// The total amount of handles which can be used to access object information. pub num_handles: usize, diff --git a/gitoxide-core/src/repository.rs b/gitoxide-core/src/repository.rs index e568910d526..0c3948ca568 100644 --- a/gitoxide-core/src/repository.rs +++ b/gitoxide-core/src/repository.rs @@ -10,3 +10,67 @@ pub fn init(directory: Option) -> Result { pub mod tree; pub mod verify; + +pub mod odb { + use crate::OutputFormat; + use anyhow::bail; + use git_repository as git; + use std::io; + use std::path::PathBuf; + + mod info { + use git_repository::odb::store; + use std::path::PathBuf; + + #[cfg_attr(feature = "serde1", derive(serde::Serialize))] + pub struct Statistics { + pub path: PathBuf, + pub object_hash: String, + pub use_multi_pack_index: bool, + pub metrics: store::Metrics, + } + } + + #[cfg_attr(not(feature = "serde1"), allow(unused_variables))] + pub fn info( + repository: PathBuf, + format: OutputFormat, + out: impl io::Write, + mut err: impl io::Write, + ) -> anyhow::Result<()> { + if format == OutputFormat::Human { + writeln!(err, "Only JSON is implemented - using that instead")?; + } + + let repo = git::open(repository)?.apply_environment(); + let store = repo.objects.store_ref(); + let stats = info::Statistics { + path: store.path().into(), + object_hash: store.object_hash().to_string(), + use_multi_pack_index: store.use_multi_pack_index(), + metrics: store.metrics(), + }; + + #[cfg(feature = "serde1")] + { + serde_json::to_writer_pretty(out, &stats)?; + } + + Ok(()) + } + + pub fn entries(repository: PathBuf, format: OutputFormat, mut out: impl io::Write) -> anyhow::Result<()> { + if format != OutputFormat::Human { + bail!("Only human output format is supported at the moment"); + } + + let repo = git::open(repository)?.apply_environment(); + + for object in repo.objects.iter()? { + let object = object?; + writeln!(out, "{}", object)?; + } + + Ok(()) + } +} diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index d6f8562eb7b..1300a9b5575 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -145,35 +145,57 @@ pub fn main() -> Result<()> { ), }, Subcommands::Repository(repo::Platform { repository, cmd }) => match cmd { - repo::Subcommands::Tree { - cmd: - repo::tree::Subcommands::Entries { - treeish, - recursive, - extended, + repo::Subcommands::Odb { cmd } => match cmd { + repo::odb::Subcommands::Entries => prepare_and_run( + "repository-odb-entries", + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, _err| core::repository::odb::entries(repository, format, out), + ), + repo::odb::Subcommands::Info => prepare_and_run( + "repository-odb-info", + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, err| core::repository::odb::info(repository, format, out, err), + ), + }, + repo::Subcommands::Tree { cmd } => match cmd { + repo::tree::Subcommands::Entries { + treeish, + recursive, + extended, + } => prepare_and_run( + "repository-tree-entries", + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, _err| { + core::repository::tree::entries( + repository, + treeish.as_deref(), + recursive, + extended, + format, + out, + ) }, - } => prepare_and_run( - "repository-tree-entries", - verbose, - progress, - progress_keep_open, - None, - move |_progress, out, _err| { - core::repository::tree::entries(repository, treeish.as_deref(), recursive, extended, format, out) - }, - ), - repo::Subcommands::Tree { - cmd: repo::tree::Subcommands::Info { treeish, extended }, - } => prepare_and_run( - "repository-tree-info", - verbose, - progress, - progress_keep_open, - None, - move |_progress, out, err| { - core::repository::tree::info(repository, treeish.as_deref(), extended, format, out, err) - }, - ), + ), + repo::tree::Subcommands::Info { treeish, extended } => prepare_and_run( + "repository-tree-info", + verbose, + progress, + progress_keep_open, + None, + move |_progress, out, err| { + core::repository::tree::info(repository, treeish.as_deref(), extended, format, out, err) + }, + ), + }, repo::Subcommands::Verify { args: pack::VerifyOptions { diff --git a/src/plumbing/options.rs b/src/plumbing/options.rs index e222bf0ed05..4a75745dcf6 100644 --- a/src/plumbing/options.rs +++ b/src/plumbing/options.rs @@ -353,6 +353,21 @@ pub mod repo { #[clap(subcommand)] cmd: tree::Subcommands, }, + /// Interact with the object database. + Odb { + #[clap(subcommand)] + cmd: odb::Subcommands, + }, + } + + pub mod odb { + #[derive(Debug, clap::Subcommand)] + pub enum Subcommands { + /// Print all object names. + Entries, + /// Provide general information about the object database. + Info, + } } pub mod tree {