Skip to content

Commit

Permalink
support for repo to write actual objects (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Mar 4, 2022
1 parent f23b8d2 commit 5494fb3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 16 deletions.
54 changes: 39 additions & 15 deletions gitoxide-core/src/index/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -104,9 +104,14 @@ fn parse_file(index_path: impl AsRef<Path>, object_hash: git::hash::Kind) -> any
pub fn checkout_exclusive(
index_path: impl AsRef<Path>,
dest_directory: impl AsRef<Path>,
repo: Option<PathBuf>,
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!(
Expand All @@ -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;
Expand All @@ -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(())
}
3 changes: 2 additions & 1 deletion src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -88,6 +88,7 @@ pub fn main() -> Result<()> {
core::index::checkout_exclusive(
index_path,
directory,
repository,
progress,
core::index::Options { object_hash, format },
)
Expand Down
4 changes: 4 additions & 0 deletions src/plumbing/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<PathBuf>,
/// The directory into which to write all index entries.
directory: PathBuf,
},
Expand Down

0 comments on commit 5494fb3

Please sign in to comment.