Skip to content

Commit 8d36713

Browse files
committed
support for repo to write actual objects (#301)
1 parent dfb95e3 commit 8d36713

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

gitoxide-core/src/index/mod.rs

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use anyhow::bail;
2-
use std::path::Path;
2+
use std::path::{Path, PathBuf};
33

44
use git_repository as git;
5-
use git_repository::Progress;
5+
use git_repository::{odb::FindExt, Progress};
66

77
pub struct Options {
88
pub object_hash: git::hash::Kind,
@@ -104,9 +104,14 @@ fn parse_file(index_path: impl AsRef<Path>, object_hash: git::hash::Kind) -> any
104104
pub fn checkout_exclusive(
105105
index_path: impl AsRef<Path>,
106106
dest_directory: impl AsRef<Path>,
107+
repo: Option<PathBuf>,
107108
mut progress: impl Progress,
108109
Options { object_hash, .. }: Options,
109110
) -> anyhow::Result<()> {
111+
let repo = repo
112+
.map(|dir| git_repository::discover(dir).map(|r| r.apply_environment()))
113+
.transpose()?;
114+
110115
let dest_directory = dest_directory.as_ref();
111116
if dest_directory.exists() {
112117
bail!(
@@ -119,9 +124,14 @@ pub fn checkout_exclusive(
119124
let mut index = parse_file(index_path, object_hash)?;
120125

121126
let mut num_skipped = 0;
127+
let maybe_symlink_mode = if repo.is_some() {
128+
git::index::entry::Mode::DIR
129+
} else {
130+
git::index::entry::Mode::SYMLINK
131+
};
122132
for entry in index.entries_mut().iter_mut().filter(|e| {
123133
e.mode
124-
.contains(git::index::entry::Mode::DIR | git::index::entry::Mode::SYMLINK | git::index::entry::Mode::COMMIT)
134+
.contains(maybe_symlink_mode | git::index::entry::Mode::DIR | git::index::entry::Mode::COMMIT)
125135
}) {
126136
entry.flags.insert(git::index::entry::Flags::SKIP_WORKTREE);
127137
num_skipped += 1;
@@ -147,21 +157,35 @@ pub fn checkout_exclusive(
147157
bytes.init(Some(entries_for_checkout), git::progress::bytes());
148158

149159
let start = std::time::Instant::now();
150-
git::worktree::index::checkout(
151-
&mut index,
152-
dest_directory,
153-
|_, buf| {
154-
buf.clear();
155-
Some(git::objs::BlobRef { data: buf })
156-
},
157-
&mut files,
158-
&mut bytes,
159-
opts,
160-
)?;
160+
match &repo {
161+
Some(repo) => git::worktree::index::checkout(
162+
&mut index,
163+
dest_directory,
164+
|oid, buf| repo.objects.find_blob(oid, buf).ok(),
165+
&mut files,
166+
&mut bytes,
167+
opts,
168+
),
169+
None => git::worktree::index::checkout(
170+
&mut index,
171+
dest_directory,
172+
|_, buf| {
173+
buf.clear();
174+
Some(git::objs::BlobRef { data: buf })
175+
},
176+
&mut files,
177+
&mut bytes,
178+
opts,
179+
),
180+
}?;
161181

162182
files.show_throughput(start);
163183
bytes.show_throughput(start);
164184

165-
progress.done(format!("Created {} empty files", entries_for_checkout));
185+
progress.done(format!(
186+
"Created {} {} files",
187+
entries_for_checkout,
188+
repo.is_none().then(|| "empty").unwrap_or_default()
189+
));
166190
Ok(())
167191
}

src/plumbing/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub fn main() -> Result<()> {
7878
index_path,
7979
cmd,
8080
}) => match cmd {
81-
index::Subcommands::CheckoutExclusive { directory } => prepare_and_run(
81+
index::Subcommands::CheckoutExclusive { directory, repository } => prepare_and_run(
8282
"index-checkout",
8383
verbose,
8484
progress,
@@ -88,6 +88,7 @@ pub fn main() -> Result<()> {
8888
core::index::checkout_exclusive(
8989
index_path,
9090
directory,
91+
repository,
9192
progress,
9293
core::index::Options { object_hash, format },
9394
)

src/plumbing/options.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,10 @@ pub mod index {
369369
},
370370
/// Checkout the index into a directory with exclusive write access, similar to what would happen during clone.
371371
CheckoutExclusive {
372+
/// The path to `.git` repository from which objects can be obtained to write the actual files referenced
373+
/// in the index. Use this measure the impact on extracting objects on overall performance.
374+
#[clap(long, short = 'r')]
375+
repository: Option<PathBuf>,
372376
/// The directory into which to write all index entries.
373377
directory: PathBuf,
374378
},

0 commit comments

Comments
 (0)