From 5494fb3e1de1234dde8c47336597283dbd8bcb29 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 3 Mar 2022 15:52:46 +0800 Subject: [PATCH] support for repo to write actual objects (#301) --- gitoxide-core/src/index/mod.rs | 54 ++++++++++++++++++++++++---------- src/plumbing/main.rs | 3 +- src/plumbing/options.rs | 4 +++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/gitoxide-core/src/index/mod.rs b/gitoxide-core/src/index/mod.rs index d22eabcf650..bd4f946807a 100644 --- a/gitoxide-core/src/index/mod.rs +++ b/gitoxide-core/src/index/mod.rs @@ -1,8 +1,8 @@ use anyhow::bail; -use std::path::Path; +use std::path::{Path, PathBuf}; use git_repository as git; -use git_repository::Progress; +use git_repository::{odb::FindExt, Progress}; pub struct Options { pub object_hash: git::hash::Kind, @@ -104,9 +104,14 @@ fn parse_file(index_path: impl AsRef, object_hash: git::hash::Kind) -> any pub fn checkout_exclusive( index_path: impl AsRef, dest_directory: impl AsRef, + repo: Option, mut progress: impl Progress, Options { object_hash, .. }: Options, ) -> anyhow::Result<()> { + let repo = repo + .map(|dir| git_repository::discover(dir).map(|r| r.apply_environment())) + .transpose()?; + let dest_directory = dest_directory.as_ref(); if dest_directory.exists() { bail!( @@ -119,9 +124,14 @@ pub fn checkout_exclusive( let mut index = parse_file(index_path, object_hash)?; let mut num_skipped = 0; + let maybe_symlink_mode = if repo.is_some() { + git::index::entry::Mode::DIR + } else { + git::index::entry::Mode::SYMLINK + }; for entry in index.entries_mut().iter_mut().filter(|e| { e.mode - .contains(git::index::entry::Mode::DIR | git::index::entry::Mode::SYMLINK | git::index::entry::Mode::COMMIT) + .contains(maybe_symlink_mode | git::index::entry::Mode::DIR | git::index::entry::Mode::COMMIT) }) { entry.flags.insert(git::index::entry::Flags::SKIP_WORKTREE); num_skipped += 1; @@ -147,21 +157,35 @@ pub fn checkout_exclusive( bytes.init(Some(entries_for_checkout), git::progress::bytes()); let start = std::time::Instant::now(); - git::worktree::index::checkout( - &mut index, - dest_directory, - |_, buf| { - buf.clear(); - Some(git::objs::BlobRef { data: buf }) - }, - &mut files, - &mut bytes, - opts, - )?; + match &repo { + Some(repo) => git::worktree::index::checkout( + &mut index, + dest_directory, + |oid, buf| repo.objects.find_blob(oid, buf).ok(), + &mut files, + &mut bytes, + opts, + ), + None => git::worktree::index::checkout( + &mut index, + dest_directory, + |_, buf| { + buf.clear(); + Some(git::objs::BlobRef { data: buf }) + }, + &mut files, + &mut bytes, + opts, + ), + }?; files.show_throughput(start); bytes.show_throughput(start); - progress.done(format!("Created {} empty files", entries_for_checkout)); + progress.done(format!( + "Created {} {} files", + entries_for_checkout, + repo.is_none().then(|| "empty").unwrap_or_default() + )); Ok(()) } diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index 3d9e7ea37c6..c2300926628 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -78,7 +78,7 @@ pub fn main() -> Result<()> { index_path, cmd, }) => match cmd { - index::Subcommands::CheckoutExclusive { directory } => prepare_and_run( + index::Subcommands::CheckoutExclusive { directory, repository } => prepare_and_run( "index-checkout", verbose, progress, @@ -88,6 +88,7 @@ pub fn main() -> Result<()> { core::index::checkout_exclusive( index_path, directory, + repository, progress, core::index::Options { object_hash, format }, ) diff --git a/src/plumbing/options.rs b/src/plumbing/options.rs index 68973190ddd..8d01894c3a1 100644 --- a/src/plumbing/options.rs +++ b/src/plumbing/options.rs @@ -369,6 +369,10 @@ pub mod index { }, /// Checkout the index into a directory with exclusive write access, similar to what would happen during clone. CheckoutExclusive { + /// The path to `.git` repository from which objects can be obtained to write the actual files referenced + /// in the index. Use this measure the impact on extracting objects on overall performance. + #[clap(long, short = 'r')] + repository: Option, /// The directory into which to write all index entries. directory: PathBuf, },