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
16#[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]16#[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
17use crate::plumbing::options::remote;17use crate::plumbing::options::remote;
18use crate::{18use crate::{
19 plumbing::options::{commitgraph, free, index, pack, pack::multi_index, repo, Args, Subcommands},19 plumbing::options::{commitgraph, free, index, repo, Args, Subcommands},
20 shared::pretty::prepare_and_run,20 shared::pretty::prepare_and_run,
21};21};
22 22
@@ -149,16 +149,270 @@ pub fn main() -> Result<()> { · 126 unmodified lines
149 },149 },
150 ),150 ),
151 },151 },
152 Subcommands::Free(free::Subcommands::Mailmap { cmd }) => match cmd {152 Subcommands::Free(subcommands) => match subcommands {
153 free::mailmap::Platform { path, cmd } => match cmd {153 free::Subcommands::Mailmap { cmd } => match cmd {
154 free::mailmap::Subcommands::Verify => prepare_and_run(154 free::mailmap::Platform { path, cmd } => match cmd {
155 "mailmap-verify",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",
156 verbose,242 verbose,
157 progress,243 progress,
158 progress_keep_open,244 progress_keep_open,
159 core::mailmap::PROGRESS_RANGE,245 core::pack::receive::PROGRESS_RANGE,
160 move |_progress, out, _err| core::mailmap::verify(path, format, out),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 },
161 ),293 ),
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 },
162 },416 },
163 },417 },
164 Subcommands::Repository(repo::Platform { cmd }) => match cmd {418 Subcommands::Repository(repo::Platform { cmd }) => match cmd {
@@ -314,7 +568,7 @@ pub fn main() -> Result<()> { · 149 unmodified lines
314 },568 },
315 repo::Subcommands::Verify {569 repo::Subcommands::Verify {
316 args:570 args:
317 pack::VerifyOptions {571 free::pack::VerifyOptions {
318 statistics,572 statistics,
319 algorithm,573 algorithm,
320 decode,574 decode,
@@ -342,254 +596,6 @@ pub fn main() -> Result<()> { · 21 unmodified lines
342 },596 },
343 ),597 ),
344 },598 },
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 },
593 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]599 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
594 Subcommands::Remote(subcommands) => match subcommands {600 Subcommands::Remote(subcommands) => match subcommands {
595 #[cfg(feature = "gitoxide-core-async-client")]601 #[cfg(feature = "gitoxide-core-async-client")]
src/plumbing/options.rs+241−241
@@ -51,9 +51,6 @@ pub struct Args { · 50 unmodified lines
51 51
52#[derive(Debug, clap::Subcommand)]52#[derive(Debug, clap::Subcommand)]
53pub enum Subcommands {53pub enum Subcommands {
54 /// Subcommands for interacting with packs and their indices.
55 #[clap(subcommand)]
56 Pack(pack::Subcommands),
57 /// Subcommands for interacting with git remote server.54 /// Subcommands for interacting with git remote server.
58 #[clap(subcommand)]55 #[clap(subcommand)]
59 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]56 #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
@@ -71,277 +68,280 @@ pub enum Subcommands { · 11 unmodified lines
71}68}
72 69
73///70///
74pub mod pack {71pub mod free {
75 use std::{ffi::OsString, path::PathBuf};
76
77 use gitoxide_core as core;
78
79 #[derive(Debug, clap::Subcommand)]72 #[derive(Debug, clap::Subcommand)]
80 pub enum Subcommands {73 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
82 #[clap(subcommand)]80 #[clap(subcommand)]
83 Index(index::Subcommands),81 Pack(pack::Subcommands),
84 /// Subcommands for interacting with multi-pack indices (named "multi-pack-index")82 }
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>,
91 83
92 #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))]84 ///
93 /// the way objects are expanded. They differ in costs.85 pub mod pack {
94 ///86 use std::{ffi::OsString, path::PathBuf};
95 /// Possible values are "none" and "tree-traversal". Default is "none".
96 expansion: Option<core::pack::create::ObjectExpansion>,
97 87
98 #[clap(long, default_value_t = 3, requires = "nondeterministic-count")]88 use gitoxide_core as core;
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,
105 89
106 #[clap(long)]90 #[derive(Debug, clap::Subcommand)]
107 /// if set, the counting phase may be accelerated using multithreading.91 pub enum Subcommands {
108 ///92 /// Subcommands for interacting with pack indices (.idx)
109 /// On the flip side, however, one will loose deterministic counting results which affects the93 #[clap(subcommand)]
110 /// way the resulting pack is structured.94 Index(index::Subcommands),
111 nondeterministic_count: bool,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>,
112 102
113 #[clap(long, short = 's')]103 #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))]
114 /// If set statistical information will be presented to inform about pack creation details.104 /// the way objects are expanded. They differ in costs.
115 /// It's a form of instrumentation for developers to help improve pack generation.105 ///
116 statistics: bool,106 /// Possible values are "none" and "tree-traversal". Default is "none".
107 expansion: Option<core::pack::create::ObjectExpansion>,
117 108
118 #[clap(long)]109 #[clap(long, default_value_t = 3, requires = "nondeterministic-count")]
119 /// The size in megabytes for a cache to speed up pack access for packs with long delta chains.110 /// The amount of threads to use when counting and the `--nondeterminisitc-count` flag is set, defaulting
120 /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.111 /// to the globally configured threads.
121 ///112 ///
122 /// If unset, no cache will be used.113 /// Use it to have different trade-offs between counting performance and cost in terms of CPU, as the scaling
123 pack_cache_size_mb: Option<usize>,114 /// here is everything but linear. The effectiveness of each core seems to be no more than 30%.
115 counting_threads: usize,
124 116
125 #[clap(long)]117 #[clap(long)]
126 /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit.118 /// if set, the counting phase may be accelerated using multithreading.
127 /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.119 ///
128 ///120 /// On the flip side, however, one will loose deterministic counting results which affects the
129 /// This cache type is currently only effective when using the 'diff-tree' object expansion.121 /// way the resulting pack is structured.
130 ///122 nondeterministic_count: bool,
131 /// If unset, no cache will be used.
132 object_cache_size_mb: Option<usize>,
133 123
134 #[clap(long)]124 #[clap(long, short = 's')]
135 /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead125 /// If set statistical information will be presented to inform about pack creation details.
136 /// refer to its base object using its object id.126 /// It's a form of instrumentation for developers to help improve pack generation.
137 ///127 statistics: bool,
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,
141 128
142 /// The directory into which to write the pack file.129 #[clap(long)]
143 #[clap(long, short = 'o')]130 /// The size in megabytes for a cache to speed up pack access for packs with long delta chains.
144 output_directory: Option<PathBuf>,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>,
145 135
146 /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes136 #[clap(long)]
147 /// or as branch names.137 /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit.
148 ///138 /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size.
149 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.139 ///
150 /// Otherwise the expansion mode is 'tree-traversal' by default.140 /// This cache type is currently only effective when using the 'diff-tree' object expansion.
151 tips: Vec<OsString>,141 ///
152 },142 /// If unset, no cache will be used.
153 /// Use the git-protocol to receive a pack, emulating a clone.143 object_cache_size_mb: Option<usize>,
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>,
159 144
160 /// the directory into which to write references. Existing files will be overwritten.145 #[clap(long)]
161 ///146 /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead
162 /// Note that the directory will be created if needed.147 /// refer to its base object using its object id.
163 #[clap(long, short = 'd')]148 ///
164 refs_directory: Option<PathBuf>,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,
165 152
166 /// The URLs or path from which to receive the pack.153 /// The directory into which to write the pack file.
167 ///154 #[clap(long, short = 'o')]
168 /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls>155 output_directory: Option<PathBuf>,
169 url: String,
170 156
171 /// If set once or more times, these references will be fetched instead of all advertised ones.157 /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes
172 ///158 /// or as branch names.
173 /// Note that this requires a reasonably modern git server.159 ///
174 #[clap(long = "reference", short = 'r')]160 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.
175 refs: Vec<String>,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>,
176 170
177 /// The directory into which to write the received pack and index.171 /// the directory into which to write references. Existing files will be overwritten.
178 ///172 ///
179 /// If unset, they will be discarded.173 /// Note that the directory will be created if needed.
180 directory: Option<PathBuf>,174 #[clap(long, short = 'd')]
181 },175 refs_directory: Option<PathBuf>,
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,
192 176
193 /// delete the pack and index file after the operation is successful177 /// The URLs or path from which to receive the pack.
194 #[clap(long)]178 ///
195 delete_pack: bool,179 /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls>
180 url: String,
196 181
197 /// The amount of checks to run182 /// If set once or more times, these references will be fetched instead of all advertised ones.
198 #[clap(183 ///
199 long,184 /// Note that this requires a reasonably modern git server.
200 short = 'c',185 #[clap(long = "reference", short = 'r')]
201 default_value = "all",186 refs: Vec<String>,
202 possible_values(core::pack::explode::SafetyCheck::variants())
203 )]
204 check: core::pack::explode::SafetyCheck,
205 187
206 /// Compress bytes even when using the sink, i.e. no object directory is specified188 /// 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.
207 ///194 ///
208 /// This helps to determine overhead related to compression. If unset, the sink will195 /// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process.
209 /// only create hashes from bytes, which is usually limited by the speed at which input196 /// Thus this should only be done to dissolve small packs after a fetch.
210 /// can be obtained.197 Explode {
211 #[clap(long)]198 #[clap(long)]
212 sink_compress: bool,199 /// Read written objects back and assert they match their source. Fail the operation otherwise.
213 200 ///
214 /// The '.pack' or '.idx' file to explode into loose objects201 /// Only relevant if an object directory is set.
215 pack_path: PathBuf,202 verify: bool,
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 }
229 203
230 #[derive(Debug, clap::Parser)]204 /// delete the pack and index file after the operation is successful
231 pub struct VerifyOptions {205 #[clap(long)]
232 /// output statistical information206 delete_pack: bool,
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,
250 207
251 #[clap(long)]208 /// The amount of checks to run
252 /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them.209 #[clap(
253 ///210 long,
254 /// This flag is primarily to test the implementation of encoding, and requires to decode the object first.211 short = 'c',
255 /// Encoding an object after decoding it should yield exactly the same bytes.212 default_value = "all",
256 /// This will reduce overall performance even more, as re-encoding requires to transform zero-copy objects into213 possible_values(core::pack::explode::SafetyCheck::variants())
257 /// owned objects, causing plenty of allocation to occour.214 )]
258 pub re_encode: bool,215 check: core::pack::explode::SafetyCheck,
259 }
260 216
261 ///217 /// Compress bytes even when using the sink, i.e. no object directory is specified
262 pub mod multi_index {218 ///
263 use std::path::PathBuf;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,
264 224
265 #[derive(Debug, clap::Parser)]225 /// The '.pack' or '.idx' file to explode into loose objects
266 pub struct Platform {226 pack_path: PathBuf,
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,
270 227
271 /// Subcommands228 /// The path into which all objects should be written. Commonly '.git/objects'
272 #[clap(subcommand)]229 object_path: Option<PathBuf>,
273 pub cmd: Subcommands,230 },
274 }231 /// Verify the integrity of a pack, index or multi-index file
232 Verify {
233 #[clap(flatten)]
234 args: VerifyOptions,
275 235
276 #[derive(Debug, clap::Subcommand)]236 /// The '.pack', '.idx' or 'multi-pack-index' file to validate.
277 pub enum Subcommands {237 path: PathBuf,
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>,
291 },238 },
292 }239 }
293 }
294
295 ///
296 pub mod index {
297 use std::path::PathBuf;
298 240
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,
300 254
301 #[derive(Debug, clap::Subcommand)]255 #[clap(long, conflicts_with("re-encode"))]
302 pub enum Subcommands {256 /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly.
303 /// create a pack index from a pack data file.257 ///
304 Create {258 /// Malformed objects should not usually occur, but could be injected on purpose or accident.
305 /// Specify how to iterate the pack, defaults to 'verify'259 /// This will reduce overall performance.
306 ///260 pub decode: bool,
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,
320 261
321 /// Path to the pack file to read (with .pack extension).262 #[clap(long)]
322 ///263 /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them.
323 /// If unset, the pack file is expected on stdin.264 ///
324 #[clap(long, short = 'p')]265 /// This flag is primarily to test the implementation of encoding, and requires to decode the object first.
325 pack_path: Option<PathBuf>,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 }
326 271
327 /// The folder into which to place the pack and the generated index file272 ///
328 ///273 pub mod multi_index {
329 /// If unset, only informational output will be provided to standard output.274 use std::path::PathBuf;
330 directory: Option<PathBuf>,275
331 },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 }
332 }304 }
333 }
334}
335 305
336///306 ///
337pub mod free {307 pub mod index {
338 #[derive(Debug, clap::Subcommand)]308 use std::path::PathBuf;
339 pub enum Subcommands {309
340 /// Subcommands for interacting with mailmaps310 use gitoxide_core as core;
341 Mailmap {311
342 #[clap(flatten)]312 #[derive(Debug, clap::Subcommand)]
343 cmd: mailmap::Platform,313 pub enum Subcommands {
344 },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 }
345 }345 }
346 346
347 ///347 ///
@@ -382,7 +382,7 @@ pub mod repo { · 34 unmodified lines
382 /// Verify the integrity of the entire repository382 /// Verify the integrity of the entire repository
383 Verify {383 Verify {
384 #[clap(flatten)]384 #[clap(flatten)]
385 args: super::pack::VerifyOptions,385 args: super::free::pack::VerifyOptions,
386 },386 },
387 /// Interact with commit objects.387 /// Interact with commit objects.
388 Commit {388 Commit {