History

move 'pack' to 'free' (#331)

Sebastian Thiel committed 4 years ago

Commit 1cdecbc1 parent 141c5f12 files · +503 −497Browse files

Unified · Split

2 files
  1. src/plumbing/main.rs +262 −256
  2. src/plumbing/options.rs +241 −241
src/plumbing/main.rs+262−256
@@ -16,7 +16,7 @@ use gitoxide_core::pack::verify; · 15 unmodified lines
1616 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
1717 use crate::plumbing::options::remote;
1818 use crate::{
19− plumbing::options::{commitgraph, free, index, pack, pack::multi_index, repo, Args, Subcommands},
19+ plumbing::options::{commitgraph, free, index, repo, Args, Subcommands},
2020 shared::pretty::prepare_and_run,
2121 };
2222
@@ -149,16 +149,270 @@ pub fn main() -> Result<()> { · 126 unmodified lines
149149 },
150150 ),
151151 },
152− Subcommands::Free(free::Subcommands::Mailmap { cmd }) => match cmd {
153− free::mailmap::Platform { path, cmd } => match cmd {
154− free::mailmap::Subcommands::Verify => prepare_and_run(
155− "mailmap-verify",
152+ Subcommands::Free(subcommands) => match subcommands {
153+ free::Subcommands::Mailmap { cmd } => match cmd {
154+ free::mailmap::Platform { path, cmd } => match cmd {
155+ free::mailmap::Subcommands::Verify => prepare_and_run(
156+ "mailmap-verify",
157+ verbose,
158+ progress,
159+ progress_keep_open,
160+ core::mailmap::PROGRESS_RANGE,
161+ move |_progress, out, _err| core::mailmap::verify(path, format, out),
162+ ),
163+ },
164+ },
165+ free::Subcommands::Pack(subcommands) => match subcommands {
166+ free::pack::Subcommands::Create {
167+ repository,
168+ expansion,
169+ thin,
170+ statistics,
171+ nondeterministic_count,
172+ tips,
173+ pack_cache_size_mb,
174+ counting_threads,
175+ object_cache_size_mb,
176+ output_directory,
177+ } => {
178+ let has_tips = !tips.is_empty();
179+ prepare_and_run(
180+ "pack-create",
181+ verbose,
182+ progress,
183+ progress_keep_open,
184+ core::pack::create::PROGRESS_RANGE,
185+ move |progress, out, _err| {
186+ let input = if has_tips { None } else { stdin_or_bail()?.into() };
187+ let repository = repository.unwrap_or_else(|| PathBuf::from("."));
188+ let context = core::pack::create::Context {
189+ thread_limit,
190+ thin,
191+ nondeterministic_thread_count: nondeterministic_count.then(|| counting_threads),
192+ pack_cache_size_in_bytes: pack_cache_size_mb.unwrap_or(0) * 1_000_000,
193+ object_cache_size_in_bytes: object_cache_size_mb.unwrap_or(0) * 1_000_000,
194+ statistics: if statistics { Some(format) } else { None },
195+ out,
196+ expansion: expansion.unwrap_or(if has_tips {
197+ core::pack::create::ObjectExpansion::TreeTraversal
198+ } else {
199+ core::pack::create::ObjectExpansion::None
200+ }),
201+ };
202+ core::pack::create(repository, tips, input, output_directory, progress, context)
203+ },
204+ )
205+ }
206+ #[cfg(feature = "gitoxide-core-async-client")]
207+ pack::Subcommands::Receive {
208+ protocol,
209+ url,
210+ directory,
211+ refs,
212+ refs_directory,
213+ } => {
214+ let (_handle, progress) =
215+ async_util::prepare(verbose, "pack-receive", core::pack::receive::PROGRESS_RANGE);
216+ let fut = core::pack::receive(
217+ protocol,
218+ &url,
219+ directory,
220+ refs_directory,
221+ refs.into_iter().map(|s| s.into()).collect(),
222+ git_features::progress::DoOrDiscard::from(progress),
223+ core::pack::receive::Context {
224+ thread_limit,
225+ format,
226+ out: std::io::stdout(),
227+ should_interrupt,
228+ object_hash,
229+ },
230+ );
231+ return futures_lite::future::block_on(fut);
232+ }
233+ #[cfg(feature = "gitoxide-core-blocking-client")]
234+ free::pack::Subcommands::Receive {
235+ protocol,
236+ url,
237+ directory,
238+ refs,
239+ refs_directory,
240+ } => prepare_and_run(
241+ "pack-receive",
156242 verbose,
157243 progress,
158244 progress_keep_open,
159− core::mailmap::PROGRESS_RANGE,
160− move |_progress, out, _err| core::mailmap::verify(path, format, out),
245+ core::pack::receive::PROGRESS_RANGE,
246+ move |progress, out, _err| {
247+ core::pack::receive(
248+ protocol,
249+ &url,
250+ directory,
251+ refs_directory,
252+ refs.into_iter().map(|r| r.into()).collect(),
253+ progress,
254+ core::pack::receive::Context {
255+ thread_limit,
256+ format,
257+ should_interrupt,
258+ out,
259+ object_hash,
260+ },
261+ )
262+ },
263+ ),
264+ free::pack::Subcommands::Explode {
265+ check,
266+ sink_compress,
267+ delete_pack,
268+ pack_path,
269+ object_path,
270+ verify,
271+ } => prepare_and_run(
272+ "pack-explode",
273+ verbose,
274+ progress,
275+ progress_keep_open,
276+ None,
277+ move |progress, _out, _err| {
278+ core::pack::explode::pack_or_pack_index(
279+ pack_path,
280+ object_path,
281+ check,
282+ progress,
283+ core::pack::explode::Context {
284+ thread_limit,
285+ delete_pack,
286+ sink_compress,
287+ verify,
288+ should_interrupt,
289+ object_hash,
290+ },
291+ )
292+ },
161293 ),
294+ free::pack::Subcommands::Verify {
295+ args:
296+ free::pack::VerifyOptions {
297+ algorithm,
298+ decode,
299+ re_encode,
300+ statistics,
301+ },
302+ path,
303+ } => prepare_and_run(
304+ "pack-verify",
305+ verbose,
306+ progress,
307+ progress_keep_open,
308+ verify::PROGRESS_RANGE,
309+ move |progress, out, err| {
310+ let mode = verify_mode(decode, re_encode);
311+ let output_statistics = if statistics { Some(format) } else { None };
312+ verify::pack_or_pack_index(
313+ path,
314+ progress,
315+ verify::Context {
316+ output_statistics,
317+ out,
318+ err,
319+ thread_limit,
320+ mode,
321+ algorithm,
322+ should_interrupt: &should_interrupt,
323+ object_hash,
324+ },
325+ )
326+ },
327+ )
328+ .map(|_| ()),
329+ free::pack::Subcommands::MultiIndex(free::pack::multi_index::Platform { multi_index_path, cmd }) => {
330+ match cmd {
331+ free::pack::multi_index::Subcommands::Entries => prepare_and_run(
332+ "pack-multi-index-entries",
333+ verbose,
334+ progress,
335+ progress_keep_open,
336+ core::pack::multi_index::PROGRESS_RANGE,
337+ move |_progress, out, _err| core::pack::multi_index::entries(multi_index_path, format, out),
338+ ),
339+ free::pack::multi_index::Subcommands::Info => prepare_and_run(
340+ "pack-multi-index-info",
341+ verbose,
342+ progress,
343+ progress_keep_open,
344+ core::pack::multi_index::PROGRESS_RANGE,
345+ move |_progress, out, err| {
346+ core::pack::multi_index::info(multi_index_path, format, out, err)
347+ },
348+ ),
349+ free::pack::multi_index::Subcommands::Verify => prepare_and_run(
350+ "pack-multi-index-verify",
351+ verbose,
352+ progress,
353+ progress_keep_open,
354+ core::pack::multi_index::PROGRESS_RANGE,
355+ move |progress, _out, _err| {
356+ core::pack::multi_index::verify(multi_index_path, progress, &should_interrupt)
357+ },
358+ ),
359+ free::pack::multi_index::Subcommands::Create { index_paths } => prepare_and_run(
360+ "pack-multi-index-create",
361+ verbose,
362+ progress,
363+ progress_keep_open,
364+ core::pack::multi_index::PROGRESS_RANGE,
365+ move |progress, _out, _err| {
366+ core::pack::multi_index::create(
367+ index_paths,
368+ multi_index_path,
369+ progress,
370+ &should_interrupt,
371+ object_hash,
372+ )
373+ },
374+ ),
375+ }
376+ }
377+ free::pack::Subcommands::Index(subcommands) => match subcommands {
378+ free::pack::index::Subcommands::Create {
379+ iteration_mode,
380+ pack_path,
381+ directory,
382+ } => prepare_and_run(
383+ "pack-index-create",
384+ verbose,
385+ progress,
386+ progress_keep_open,
387+ core::pack::index::PROGRESS_RANGE,
388+ move |progress, out, _err| {
389+ use gitoxide_core::pack::index::PathOrRead;
390+ let input = if let Some(path) = pack_path {
391+ PathOrRead::Path(path)
392+ } else {
393+ if atty::is(atty::Stream::Stdin) {
394+ anyhow::bail!(
395+ "Refusing to read from standard input as no path is given, but it's a terminal."
396+ )
397+ }
398+ PathOrRead::Read(Box::new(std::io::stdin()))
399+ };
400+ core::pack::index::from_pack(
401+ input,
402+ directory,
403+ progress,
404+ core::pack::index::Context {
405+ thread_limit,
406+ iteration_mode,
407+ format,
408+ out,
409+ object_hash,
410+ should_interrupt: &git_repository::interrupt::IS_INTERRUPTED,
411+ },
412+ )
413+ },
414+ ),
415+ },
162416 },
163417 },
164418 Subcommands::Repository(repo::Platform { cmd }) => match cmd {
@@ -314,7 +568,7 @@ pub fn main() -> Result<()> { · 149 unmodified lines
314568 },
315569 repo::Subcommands::Verify {
316570 args:
317− pack::VerifyOptions {
571+ free::pack::VerifyOptions {
318572 statistics,
319573 algorithm,
320574 decode,
@@ -342,254 +596,6 @@ pub fn main() -> Result<()> { · 21 unmodified lines
342596 },
343597 ),
344598 },
345− Subcommands::Pack(subcommands) => match subcommands {
346− pack::Subcommands::Create {
347− repository,
348− expansion,
349− thin,
350− statistics,
351− nondeterministic_count,
352− tips,
353− pack_cache_size_mb,
354− counting_threads,
355− object_cache_size_mb,
356− output_directory,
357− } => {
358− let has_tips = !tips.is_empty();
359− prepare_and_run(
360− "pack-create",
361− verbose,
362− progress,
363− progress_keep_open,
364− core::pack::create::PROGRESS_RANGE,
365− move |progress, out, _err| {
366− let input = if has_tips { None } else { stdin_or_bail()?.into() };
367− let repository = repository.unwrap_or_else(|| PathBuf::from("."));
368− let context = core::pack::create::Context {
369− thread_limit,
370− thin,
371− nondeterministic_thread_count: nondeterministic_count.then(|| counting_threads),
372− pack_cache_size_in_bytes: pack_cache_size_mb.unwrap_or(0) * 1_000_000,
373− object_cache_size_in_bytes: object_cache_size_mb.unwrap_or(0) * 1_000_000,
374− statistics: if statistics { Some(format) } else { None },
375− out,
376− expansion: expansion.unwrap_or(if has_tips {
377− core::pack::create::ObjectExpansion::TreeTraversal
378− } else {
379− core::pack::create::ObjectExpansion::None
380− }),
381− };
382− core::pack::create(repository, tips, input, output_directory, progress, context)
383− },
384− )
385− }
386− #[cfg(feature = "gitoxide-core-async-client")]
387− pack::Subcommands::Receive {
388− protocol,
389− url,
390− directory,
391− refs,
392− refs_directory,
393− } => {
394− let (_handle, progress) =
395− async_util::prepare(verbose, "pack-receive", core::pack::receive::PROGRESS_RANGE);
396− let fut = core::pack::receive(
397− protocol,
398− &url,
399− directory,
400− refs_directory,
401− refs.into_iter().map(|s| s.into()).collect(),
402− git_features::progress::DoOrDiscard::from(progress),
403− core::pack::receive::Context {
404− thread_limit,
405− format,
406− out: std::io::stdout(),
407− should_interrupt,
408− object_hash,
409− },
410− );
411− return futures_lite::future::block_on(fut);
412− }
413− #[cfg(feature = "gitoxide-core-blocking-client")]
414− pack::Subcommands::Receive {
415− protocol,
416− url,
417− directory,
418− refs,
419− refs_directory,
420− } => prepare_and_run(
421− "pack-receive",
422− verbose,
423− progress,
424− progress_keep_open,
425− core::pack::receive::PROGRESS_RANGE,
426− move |progress, out, _err| {
427− core::pack::receive(
428− protocol,
429− &url,
430− directory,
431− refs_directory,
432− refs.into_iter().map(|r| r.into()).collect(),
433− progress,
434− core::pack::receive::Context {
435− thread_limit,
436− format,
437− should_interrupt,
438− out,
439− object_hash,
440− },
441− )
442− },
443− ),
444− pack::Subcommands::Explode {
445− check,
446− sink_compress,
447− delete_pack,
448− pack_path,
449− object_path,
450− verify,
451− } => prepare_and_run(
452− "pack-explode",
453− verbose,
454− progress,
455− progress_keep_open,
456− None,
457− move |progress, _out, _err| {
458− core::pack::explode::pack_or_pack_index(
459− pack_path,
460− object_path,
461− check,
462− progress,
463− core::pack::explode::Context {
464− thread_limit,
465− delete_pack,
466− sink_compress,
467− verify,
468− should_interrupt,
469− object_hash,
470− },
471− )
472− },
473− ),
474− pack::Subcommands::Verify {
475− args:
476− pack::VerifyOptions {
477− algorithm,
478− decode,
479− re_encode,
480− statistics,
481− },
482− path,
483− } => prepare_and_run(
484− "pack-verify",
485− verbose,
486− progress,
487− progress_keep_open,
488− verify::PROGRESS_RANGE,
489− move |progress, out, err| {
490− let mode = verify_mode(decode, re_encode);
491− let output_statistics = if statistics { Some(format) } else { None };
492− verify::pack_or_pack_index(
493− path,
494− progress,
495− verify::Context {
496− output_statistics,
497− out,
498− err,
499− thread_limit,
500− mode,
501− algorithm,
502− should_interrupt: &should_interrupt,
503− object_hash,
504− },
505− )
506− },
507− )
508− .map(|_| ()),
509− pack::Subcommands::MultiIndex(multi_index::Platform { multi_index_path, cmd }) => match cmd {
510− pack::multi_index::Subcommands::Entries => prepare_and_run(
511− "pack-multi-index-entries",
512− verbose,
513− progress,
514− progress_keep_open,
515− core::pack::multi_index::PROGRESS_RANGE,
516− move |_progress, out, _err| core::pack::multi_index::entries(multi_index_path, format, out),
517− ),
518− pack::multi_index::Subcommands::Info => prepare_and_run(
519− "pack-multi-index-info",
520− verbose,
521− progress,
522− progress_keep_open,
523− core::pack::multi_index::PROGRESS_RANGE,
524− move |_progress, out, err| core::pack::multi_index::info(multi_index_path, format, out, err),
525− ),
526− pack::multi_index::Subcommands::Verify => prepare_and_run(
527− "pack-multi-index-verify",
528− verbose,
529− progress,
530− progress_keep_open,
531− core::pack::multi_index::PROGRESS_RANGE,
532− move |progress, _out, _err| {
533− core::pack::multi_index::verify(multi_index_path, progress, &should_interrupt)
534− },
535− ),
536− pack::multi_index::Subcommands::Create { index_paths } => prepare_and_run(
537− "pack-multi-index-create",
538− verbose,
539− progress,
540− progress_keep_open,
541− core::pack::multi_index::PROGRESS_RANGE,
542− move |progress, _out, _err| {
543− core::pack::multi_index::create(
544− index_paths,
545− multi_index_path,
546− progress,
547− &should_interrupt,
548− object_hash,
549− )
550− },
551− ),
552− },
553− pack::Subcommands::Index(subcommands) => match subcommands {
554− pack::index::Subcommands::Create {
555− iteration_mode,
556− pack_path,
557− directory,
558− } => prepare_and_run(
559− "pack-index-create",
560− verbose,
561− progress,
562− progress_keep_open,
563− core::pack::index::PROGRESS_RANGE,
564− move |progress, out, _err| {
565− use gitoxide_core::pack::index::PathOrRead;
566− let input = if let Some(path) = pack_path {
567− PathOrRead::Path(path)
568− } else {
569− if atty::is(atty::Stream::Stdin) {
570− anyhow::bail!(
571− "Refusing to read from standard input as no path is given, but it's a terminal."
572− )
573− }
574− PathOrRead::Read(Box::new(std::io::stdin()))
575− };
576− core::pack::index::from_pack(
577− input,
578− directory,
579− progress,
580− core::pack::index::Context {
581− thread_limit,
582− iteration_mode,
583− format,
584− out,
585− object_hash,
586− should_interrupt: &git_repository::interrupt::IS_INTERRUPTED,
587− },
588− )
589− },
590− ),
591− },
592− },
593599 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
594600 Subcommands::Remote(subcommands) => match subcommands {
595601 #[cfg(feature = "gitoxide-core-async-client")]
src/plumbing/options.rs+241−241
@@ -51,9 +51,6 @@ pub struct Args { · 50 unmodified lines
5151
5252 #[derive(Debug, clap::Subcommand)]
5353 pub enum Subcommands {
54− /// Subcommands for interacting with packs and their indices.
55− #[clap(subcommand)]
56− Pack(pack::Subcommands),
5754 /// Subcommands for interacting with git remote server.
5855 #[clap(subcommand)]
5956 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
@@ -71,277 +68,280 @@ pub enum Subcommands { · 11 unmodified lines
7168 }
7269
7370 ///
74−pub mod pack {
75− use std::{ffi::OsString, path::PathBuf};
76−
77− use gitoxide_core as core;
78−
71+pub mod free {
7972 #[derive(Debug, clap::Subcommand)]
8073 pub enum Subcommands {
81− /// Subcommands for interacting with pack indices (.idx)
74+ /// Subcommands for interacting with mailmaps
75+ Mailmap {
76+ #[clap(flatten)]
77+ cmd: mailmap::Platform,
78+ },
79+ /// Subcommands for interacting with pack files and indices
8280 #[clap(subcommand)]
83− Index(index::Subcommands),
84− /// Subcommands for interacting with multi-pack indices (named "multi-pack-index")
85− MultiIndex(multi_index::Platform),
86− /// Create a new pack with a set of objects.
87− Create {
88− #[clap(long, short = 'r')]
89− /// the directory containing the '.git' repository from which objects should be read.
90− repository: Option<PathBuf>,
81+ Pack(pack::Subcommands),
82+ }
9183
92− #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))]
93− /// the way objects are expanded. They differ in costs.
94− ///
95− /// Possible values are "none" and "tree-traversal". Default is "none".
96− expansion: Option<core::pack::create::ObjectExpansion>,
84+ ///
85+ pub mod pack {
86+ use std::{ffi::OsString, path::PathBuf};
9787
98− #[clap(long, default_value_t = 3, requires = "nondeterministic-count")]
99− /// The amount of threads to use when counting and the `--nondeterminisitc-count` flag is set, defaulting
100− /// to the globally configured threads.
101− ///
102− /// Use it to have different trade-offs between counting performance and cost in terms of CPU, as the scaling
103− /// here is everything but linear. The effectiveness of each core seems to be no more than 30%.
104− counting_threads: usize,
88+ use gitoxide_core as core;
10589
106− #[clap(long)]
107− /// if set, the counting phase may be accelerated using multithreading.
108− ///
109− /// On the flip side, however, one will loose deterministic counting results which affects the
110− /// way the resulting pack is structured.
111− nondeterministic_count: bool,
90+ #[derive(Debug, clap::Subcommand)]
91+ pub enum Subcommands {
92+ /// Subcommands for interacting with pack indices (.idx)
93+ #[clap(subcommand)]
94+ Index(index::Subcommands),
95+ /// Subcommands for interacting with multi-pack indices (named "multi-pack-index")
96+ MultiIndex(multi_index::Platform),
97+ /// Create a new pack with a set of objects.
98+ Create {
99+ #[clap(long, short = 'r')]
100+ /// the directory containing the '.git' repository from which objects should be read.
101+ repository: Option<PathBuf>,
112102
113− #[clap(long, short = 's')]
114− /// If set statistical information will be presented to inform about pack creation details.
115− /// It's a form of instrumentation for developers to help improve pack generation.
116− statistics: bool,
103+ #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))]
104+ /// the way objects are expanded. They differ in costs.
105+ ///
106+ /// Possible values are "none" and "tree-traversal". Default is "none".
107+ expansion: Option<core::pack::create::ObjectExpansion>,
117108
118− #[clap(long)]
119− /// The size in megabytes for a cache to speed up pack access for packs with long delta chains.
120− /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.
121− ///
122− /// If unset, no cache will be used.
123− pack_cache_size_mb: Option<usize>,
109+ #[clap(long, default_value_t = 3, requires = "nondeterministic-count")]
110+ /// The amount of threads to use when counting and the `--nondeterminisitc-count` flag is set, defaulting
111+ /// to the globally configured threads.
112+ ///
113+ /// Use it to have different trade-offs between counting performance and cost in terms of CPU, as the scaling
114+ /// here is everything but linear. The effectiveness of each core seems to be no more than 30%.
115+ counting_threads: usize,
124116
125− #[clap(long)]
126− /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit.
127− /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.
128− ///
129− /// This cache type is currently only effective when using the 'diff-tree' object expansion.
130− ///
131− /// If unset, no cache will be used.
132− object_cache_size_mb: Option<usize>,
117+ #[clap(long)]
118+ /// if set, the counting phase may be accelerated using multithreading.
119+ ///
120+ /// On the flip side, however, one will loose deterministic counting results which affects the
121+ /// way the resulting pack is structured.
122+ nondeterministic_count: bool,
133123
134− #[clap(long)]
135− /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead
136− /// refer to its base object using its object id.
137− ///
138− /// This allows for smaller packs but requires the receiver of the pack to resolve these ids before storing the pack.
139− /// Packs produced with this option enabled are only valid in transit, but not at rest.
140− thin: bool,
124+ #[clap(long, short = 's')]
125+ /// If set statistical information will be presented to inform about pack creation details.
126+ /// It's a form of instrumentation for developers to help improve pack generation.
127+ statistics: bool,
141128
142− /// The directory into which to write the pack file.
143− #[clap(long, short = 'o')]
144− output_directory: Option<PathBuf>,
129+ #[clap(long)]
130+ /// The size in megabytes for a cache to speed up pack access for packs with long delta chains.
131+ /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.
132+ ///
133+ /// If unset, no cache will be used.
134+ pack_cache_size_mb: Option<usize>,
145135
146− /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes
147− /// or as branch names.
148− ///
149− /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.
150− /// Otherwise the expansion mode is 'tree-traversal' by default.
151− tips: Vec<OsString>,
152− },
153− /// Use the git-protocol to receive a pack, emulating a clone.
154− #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
155− Receive {
156− /// The protocol version to use. Valid values are 1 and 2
157− #[clap(long, short = 'p')]
158− protocol: Option<core::net::Protocol>,
136+ #[clap(long)]
137+ /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit.
138+ /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.
139+ ///
140+ /// This cache type is currently only effective when using the 'diff-tree' object expansion.
141+ ///
142+ /// If unset, no cache will be used.
143+ object_cache_size_mb: Option<usize>,
159144
160− /// the directory into which to write references. Existing files will be overwritten.
161− ///
162− /// Note that the directory will be created if needed.
163− #[clap(long, short = 'd')]
164− refs_directory: Option<PathBuf>,
145+ #[clap(long)]
146+ /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead
147+ /// refer to its base object using its object id.
148+ ///
149+ /// This allows for smaller packs but requires the receiver of the pack to resolve these ids before storing the pack.
150+ /// Packs produced with this option enabled are only valid in transit, but not at rest.
151+ thin: bool,
165152
166− /// The URLs or path from which to receive the pack.
167− ///
168− /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls>
169− url: String,
153+ /// The directory into which to write the pack file.
154+ #[clap(long, short = 'o')]
155+ output_directory: Option<PathBuf>,
170156
171− /// If set once or more times, these references will be fetched instead of all advertised ones.
172− ///
173− /// Note that this requires a reasonably modern git server.
174− #[clap(long = "reference", short = 'r')]
175− refs: Vec<String>,
157+ /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes
158+ /// or as branch names.
159+ ///
160+ /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.
161+ /// Otherwise the expansion mode is 'tree-traversal' by default.
162+ tips: Vec<OsString>,
163+ },
164+ /// Use the git-protocol to receive a pack, emulating a clone.
165+ #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
166+ Receive {
167+ /// The protocol version to use. Valid values are 1 and 2
168+ #[clap(long, short = 'p')]
169+ protocol: Option<core::net::Protocol>,
176170
177− /// The directory into which to write the received pack and index.
178− ///
179− /// If unset, they will be discarded.
180− directory: Option<PathBuf>,
181− },
182− /// Dissolve a pack into its loose objects.
183− ///
184− /// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process.
185− /// Thus this should only be done to dissolve small packs after a fetch.
186− Explode {
187− #[clap(long)]
188− /// Read written objects back and assert they match their source. Fail the operation otherwise.
189− ///
190− /// Only relevant if an object directory is set.
191− verify: bool,
171+ /// the directory into which to write references. Existing files will be overwritten.
172+ ///
173+ /// Note that the directory will be created if needed.
174+ #[clap(long, short = 'd')]
175+ refs_directory: Option<PathBuf>,
192176
193− /// delete the pack and index file after the operation is successful
194− #[clap(long)]
195− delete_pack: bool,
177+ /// The URLs or path from which to receive the pack.
178+ ///
179+ /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls>
180+ url: String,
196181
197− /// The amount of checks to run
198− #[clap(
199− long,
200− short = 'c',
201− default_value = "all",
202− possible_values(core::pack::explode::SafetyCheck::variants())
203− )]
204− check: core::pack::explode::SafetyCheck,
182+ /// If set once or more times, these references will be fetched instead of all advertised ones.
183+ ///
184+ /// Note that this requires a reasonably modern git server.
185+ #[clap(long = "reference", short = 'r')]
186+ refs: Vec<String>,
205187
206− /// Compress bytes even when using the sink, i.e. no object directory is specified
188+ /// The directory into which to write the received pack and index.
189+ ///
190+ /// If unset, they will be discarded.
191+ directory: Option<PathBuf>,
192+ },
193+ /// Dissolve a pack into its loose objects.
207194 ///
208− /// This helps to determine overhead related to compression. If unset, the sink will
209− /// only create hashes from bytes, which is usually limited by the speed at which input
210− /// can be obtained.
211− #[clap(long)]
212− sink_compress: bool,
213−
214− /// The '.pack' or '.idx' file to explode into loose objects
215− pack_path: PathBuf,
216−
217− /// The path into which all objects should be written. Commonly '.git/objects'
218− object_path: Option<PathBuf>,
219− },
220− /// Verify the integrity of a pack, index or multi-index file
221− Verify {
222− #[clap(flatten)]
223− args: VerifyOptions,
224−
225− /// The '.pack', '.idx' or 'multi-pack-index' file to validate.
226− path: PathBuf,
227− },
228− }
195+ /// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process.
196+ /// Thus this should only be done to dissolve small packs after a fetch.
197+ Explode {
198+ #[clap(long)]
199+ /// Read written objects back and assert they match their source. Fail the operation otherwise.
200+ ///
201+ /// Only relevant if an object directory is set.
202+ verify: bool,
229203
230− #[derive(Debug, clap::Parser)]
231− pub struct VerifyOptions {
232− /// output statistical information
233− #[clap(long, short = 's')]
234− pub statistics: bool,
235− /// The algorithm used to verify packs. They differ in costs.
236− #[clap(
237− long,
238− short = 'a',
239− default_value = "less-time",
240− possible_values(core::pack::verify::Algorithm::variants())
241− )]
242− pub algorithm: core::pack::verify::Algorithm,
243−
244− #[clap(long, conflicts_with("re-encode"))]
245− /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly.
246− ///
247− /// Malformed objects should not usually occur, but could be injected on purpose or accident.
248− /// This will reduce overall performance.
249− pub decode: bool,
204+ /// delete the pack and index file after the operation is successful
205+ #[clap(long)]
206+ delete_pack: bool,
250207
251− #[clap(long)]
252− /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them.
253− ///
254− /// This flag is primarily to test the implementation of encoding, and requires to decode the object first.
255− /// Encoding an object after decoding it should yield exactly the same bytes.
256− /// This will reduce overall performance even more, as re-encoding requires to transform zero-copy objects into
257− /// owned objects, causing plenty of allocation to occour.
258− pub re_encode: bool,
259− }
208+ /// The amount of checks to run
209+ #[clap(
210+ long,
211+ short = 'c',
212+ default_value = "all",
213+ possible_values(core::pack::explode::SafetyCheck::variants())
214+ )]
215+ check: core::pack::explode::SafetyCheck,
260216
261− ///
262− pub mod multi_index {
263− use std::path::PathBuf;
217+ /// Compress bytes even when using the sink, i.e. no object directory is specified
218+ ///
219+ /// This helps to determine overhead related to compression. If unset, the sink will
220+ /// only create hashes from bytes, which is usually limited by the speed at which input
221+ /// can be obtained.
222+ #[clap(long)]
223+ sink_compress: bool,
264224
265− #[derive(Debug, clap::Parser)]
266− pub struct Platform {
267− /// The path to the index file.
268− #[clap(short = 'i', long, default_value = ".git/objects/pack/multi-pack-index")]
269− pub multi_index_path: PathBuf,
225+ /// The '.pack' or '.idx' file to explode into loose objects
226+ pack_path: PathBuf,
270227
271− /// Subcommands
272− #[clap(subcommand)]
273− pub cmd: Subcommands,
274− }
228+ /// The path into which all objects should be written. Commonly '.git/objects'
229+ object_path: Option<PathBuf>,
230+ },
231+ /// Verify the integrity of a pack, index or multi-index file
232+ Verify {
233+ #[clap(flatten)]
234+ args: VerifyOptions,
275235
276− #[derive(Debug, clap::Subcommand)]
277− pub enum Subcommands {
278− /// Display all entries of a multi-index: <oid> <pack-id> <pack-offset>
279− Entries,
280− /// Print general information about a multi-index file
281− Info,
282− /// Verify a multi-index quickly without inspecting objects themselves
283− Verify,
284− /// Create a multi-pack index from one or more pack index files, overwriting possibloy existing files.
285− Create {
286− /// Paths to the pack index files to read (with .idx extension).
287− ///
288− /// Note for the multi-index to be useful, it should be side-by-side with the supplied `.idx` files.
289− #[clap(required = true)]
290− index_paths: Vec<PathBuf>,
236+ /// The '.pack', '.idx' or 'multi-pack-index' file to validate.
237+ path: PathBuf,
291238 },
292239 }
293− }
294−
295− ///
296− pub mod index {
297− use std::path::PathBuf;
298240
299− use gitoxide_core as core;
241+ #[derive(Debug, clap::Parser)]
242+ pub struct VerifyOptions {
243+ /// output statistical information
244+ #[clap(long, short = 's')]
245+ pub statistics: bool,
246+ /// The algorithm used to verify packs. They differ in costs.
247+ #[clap(
248+ long,
249+ short = 'a',
250+ default_value = "less-time",
251+ possible_values(core::pack::verify::Algorithm::variants())
252+ )]
253+ pub algorithm: core::pack::verify::Algorithm,
300254
301− #[derive(Debug, clap::Subcommand)]
302− pub enum Subcommands {
303− /// create a pack index from a pack data file.
304− Create {
305− /// Specify how to iterate the pack, defaults to 'verify'
306− ///
307− /// Valid values are
308− ///
309− /// **as-is** do not do anything and expect the pack file to be valid as per the trailing hash,
310− /// **verify** the input ourselves and validate that it matches with the hash provided in the pack,
311− /// **restore** hash the input ourselves and ignore failing entries, instead finish the pack with the hash we computed
312− /// to keep as many objects as possible.
313− #[clap(
314− long,
315− short = 'i',
316− default_value = "verify",
317− possible_values(core::pack::index::IterationMode::variants())
318− )]
319− iteration_mode: core::pack::index::IterationMode,
255+ #[clap(long, conflicts_with("re-encode"))]
256+ /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly.
257+ ///
258+ /// Malformed objects should not usually occur, but could be injected on purpose or accident.
259+ /// This will reduce overall performance.
260+ pub decode: bool,
320261
321− /// Path to the pack file to read (with .pack extension).
322− ///
323− /// If unset, the pack file is expected on stdin.
324− #[clap(long, short = 'p')]
325− pack_path: Option<PathBuf>,
262+ #[clap(long)]
263+ /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them.
264+ ///
265+ /// This flag is primarily to test the implementation of encoding, and requires to decode the object first.
266+ /// Encoding an object after decoding it should yield exactly the same bytes.
267+ /// This will reduce overall performance even more, as re-encoding requires to transform zero-copy objects into
268+ /// owned objects, causing plenty of allocation to occour.
269+ pub re_encode: bool,
270+ }
326271
327− /// The folder into which to place the pack and the generated index file
328− ///
329− /// If unset, only informational output will be provided to standard output.
330− directory: Option<PathBuf>,
331− },
272+ ///
273+ pub mod multi_index {
274+ use std::path::PathBuf;
275+
276+ #[derive(Debug, clap::Parser)]
277+ pub struct Platform {
278+ /// The path to the index file.
279+ #[clap(short = 'i', long, default_value = ".git/objects/pack/multi-pack-index")]
280+ pub multi_index_path: PathBuf,
281+
282+ /// Subcommands
283+ #[clap(subcommand)]
284+ pub cmd: Subcommands,
285+ }
286+
287+ #[derive(Debug, clap::Subcommand)]
288+ pub enum Subcommands {
289+ /// Display all entries of a multi-index: <oid> <pack-id> <pack-offset>
290+ Entries,
291+ /// Print general information about a multi-index file
292+ Info,
293+ /// Verify a multi-index quickly without inspecting objects themselves
294+ Verify,
295+ /// Create a multi-pack index from one or more pack index files, overwriting possibloy existing files.
296+ Create {
297+ /// Paths to the pack index files to read (with .idx extension).
298+ ///
299+ /// Note for the multi-index to be useful, it should be side-by-side with the supplied `.idx` files.
300+ #[clap(required = true)]
301+ index_paths: Vec<PathBuf>,
302+ },
303+ }
332304 }
333− }
334−}
335305
336−///
337−pub mod free {
338− #[derive(Debug, clap::Subcommand)]
339− pub enum Subcommands {
340− /// Subcommands for interacting with mailmaps
341− Mailmap {
342− #[clap(flatten)]
343− cmd: mailmap::Platform,
344− },
306+ ///
307+ pub mod index {
308+ use std::path::PathBuf;
309+
310+ use gitoxide_core as core;
311+
312+ #[derive(Debug, clap::Subcommand)]
313+ pub enum Subcommands {
314+ /// create a pack index from a pack data file.
315+ Create {
316+ /// Specify how to iterate the pack, defaults to 'verify'
317+ ///
318+ /// Valid values are
319+ ///
320+ /// **as-is** do not do anything and expect the pack file to be valid as per the trailing hash,
321+ /// **verify** the input ourselves and validate that it matches with the hash provided in the pack,
322+ /// **restore** hash the input ourselves and ignore failing entries, instead finish the pack with the hash we computed
323+ /// to keep as many objects as possible.
324+ #[clap(
325+ long,
326+ short = 'i',
327+ default_value = "verify",
328+ possible_values(core::pack::index::IterationMode::variants())
329+ )]
330+ iteration_mode: core::pack::index::IterationMode,
331+
332+ /// Path to the pack file to read (with .pack extension).
333+ ///
334+ /// If unset, the pack file is expected on stdin.
335+ #[clap(long, short = 'p')]
336+ pack_path: Option<PathBuf>,
337+
338+ /// The folder into which to place the pack and the generated index file
339+ ///
340+ /// If unset, only informational output will be provided to standard output.
341+ directory: Option<PathBuf>,
342+ },
343+ }
344+ }
345345 }
346346
347347 ///
@@ -382,7 +382,7 @@ pub mod repo { · 34 unmodified lines
382382 /// Verify the integrity of the entire repository
383383 Verify {
384384 #[clap(flatten)]
385− args: super::pack::VerifyOptions,
385+ args: super::free::pack::VerifyOptions,
386386 },
387387 /// Interact with commit objects.
388388 Commit {