use std::{ io::{stdin, BufReader}, path::PathBuf, sync::{ atomic::{AtomicBool, Ordering}, Arc, },}; use anyhow::Result;use clap::Clap;use gitoxide_core as core;use gitoxide_core::pack::verify; use crate::{ plumbing::pretty::options::{Args, Subcommands}, shared::pretty::prepare_and_run,}; pub fn main() -> Result<()> { let Args { threads: thread_limit, verbose, progress, progress_keep_open, format, cmd, } = Args::parse(); let should_interrupt = Arc::new(AtomicBool::new(false)); git_repository::interrupt::init_handler({ let should_interrupt = Arc::clone(&should_interrupt); move || should_interrupt.store(true, Ordering::SeqCst) })?; match cmd { Subcommands::PackCreate { repository, expansion, statistics, nondeterministic_count, tips, output_directory, } => { let has_tips = !tips.is_empty(); prepare_and_run( "pack-create", verbose, progress, progress_keep_open, core::pack::create::PROGRESS_RANGE, move |progress, out, _err| { let input = if has_tips { None } else { if atty::is(atty::Stream::Stdin) { anyhow::bail!( "Refusing to read from standard input as no path is given, but it's a terminal." ) } Some(BufReader::new(stdin())) }; let repository = repository.unwrap_or_else(|| PathBuf::from(".")); let context = core::pack::create::Context { thread_limit, nondeterministic_count, statistics: if statistics { Some(format) } else { None }, out, expansion: expansion.unwrap_or_else(|| { if has_tips { core::pack::create::ObjectExpansion::TreeTraversal } else { core::pack::create::ObjectExpansion::None } }), }; let progress = git_features::progress::DoOrDiscard::from(progress); core::pack::create(repository, tips, input, output_directory, progress, context) }, ) } #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] Subcommands::PackReceive { protocol, url, directory, refs_directory, } => prepare_and_run( "pack-receive", verbose, progress, progress_keep_open, core::pack::receive::PROGRESS_RANGE, move |progress, out, _err| { core::pack::receive( protocol, &url, directory, refs_directory, git_features::progress::DoOrDiscard::from(progress), core::pack::receive::Context { thread_limit, format, should_interrupt, out, }, ) }, ), #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] Subcommands::RemoteRefList { protocol, url } => prepare_and_run( "remote-ref-list", verbose, progress, progress_keep_open, core::remote::refs::PROGRESS_RANGE, move |progress, out, _err| { core::remote::refs::list( protocol, &url, git_features::progress::DoOrDiscard::from(progress), core::remote::refs::Context { thread_limit, format, out, }, ) }, ), Subcommands::PackIndexFromData { iteration_mode, pack_path, directory, } => prepare_and_run( "pack-index-from-data", verbose, progress, progress_keep_open, core::pack::index::PROGRESS_RANGE, move |progress, out, _err| { use gitoxide_core::pack::index::PathOrRead; let input = if let Some(path) = pack_path { PathOrRead::Path(path) } else { if atty::is(atty::Stream::Stdin) { anyhow::bail!("Refusing to read from standard input as no path is given, but it's a terminal.") } PathOrRead::Read(Box::new(std::io::stdin())) }; core::pack::index::from_pack( input, directory, git_features::progress::DoOrDiscard::from(progress), core::pack::index::Context { thread_limit, iteration_mode, format, out, should_interrupt: &git_repository::interrupt::IS_INTERRUPTED, }, ) }, ), Subcommands::PackExplode { check, sink_compress, delete_pack, pack_path, object_path, verify, } => prepare_and_run( "pack-explode", verbose, progress, progress_keep_open, None, move |progress, _out, _err| { core::pack::explode::pack_or_pack_index( pack_path, object_path, check, progress, core::pack::explode::Context { thread_limit, delete_pack, sink_compress, verify, should_interrupt, }, ) }, ), Subcommands::PackVerify { path, algorithm, decode, re_encode, statistics, } => prepare_and_run( "pack-verify", verbose, progress, progress_keep_open, None, move |progress, out, err| { let mode = match (decode, re_encode) { (true, false) => verify::Mode::Sha1Crc32Decode, (true, true) | (false, true) => verify::Mode::Sha1Crc32DecodeEncode, (false, false) => verify::Mode::Sha1Crc32, }; let output_statistics = if statistics { Some(format) } else { None }; verify::pack_or_pack_index( path, progress, verify::Context { output_statistics, out, err, thread_limit, mode, algorithm, should_interrupt, }, ) }, ) .map(|_| ()), Subcommands::CommitGraphVerify { path, statistics } => prepare_and_run( "commit-graph-verify", verbose, progress, progress_keep_open, None, move |_progress, out, err| { let output_statistics = if statistics { Some(format) } else { None }; core::commitgraph::verify::graph_or_file( path, core::commitgraph::verify::Context { err, out, output_statistics, }, ) }, ) .map(|_| ()), }?; Ok(())}
use std::{
io::{stdin, BufReader},
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use anyhow::Result;
use clap::Clap;
use gitoxide_core as core;
use gitoxide_core::pack::verify;
use crate::{
plumbing::pretty::options::{Args, Subcommands},
shared::pretty::prepare_and_run,
};
pub fn main() -> Result<()> {
let Args {
threads: thread_limit,
verbose,
progress,
progress_keep_open,
format,
cmd,
} = Args::parse();
let should_interrupt = Arc::new(AtomicBool::new(false));
git_repository::interrupt::init_handler({
let should_interrupt = Arc::clone(&should_interrupt);
move || should_interrupt.store(true, Ordering::SeqCst)
})?;
match cmd {
Subcommands::PackCreate {
repository,
expansion,
statistics,
nondeterministic_count,
tips,
output_directory,
} => {
let has_tips = !tips.is_empty();
prepare_and_run(
"pack-create",
verbose,
progress,
progress_keep_open,
core::pack::create::PROGRESS_RANGE,
move |progress, out, _err| {
let input = if has_tips {
None
} else {
if atty::is(atty::Stream::Stdin) {
anyhow::bail!(
"Refusing to read from standard input as no path is given, but it's a terminal."
)
}
Some(BufReader::new(stdin()))
};
let repository = repository.unwrap_or_else(|| PathBuf::from("."));
let context = core::pack::create::Context {
thread_limit,
nondeterministic_count,
statistics: if statistics { Some(format) } else { None },
out,
expansion: expansion.unwrap_or_else(|| {
if has_tips {
core::pack::create::ObjectExpansion::TreeTraversal
} else {
core::pack::create::ObjectExpansion::None
}
}),
};
let progress = git_features::progress::DoOrDiscard::from(progress);
core::pack::create(repository, tips, input, output_directory, progress, context)
},
)
}
#[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
Subcommands::PackReceive {
protocol,
url,
directory,
refs_directory,
} => prepare_and_run(
"pack-receive",
verbose,
progress,
progress_keep_open,
core::pack::receive::PROGRESS_RANGE,
move |progress, out, _err| {
core::pack::receive(
protocol,
&url,
directory,
refs_directory,
git_features::progress::DoOrDiscard::from(progress),
core::pack::receive::Context {
thread_limit,
format,
should_interrupt,
out,
},
)
},
),
#[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
Subcommands::RemoteRefList { protocol, url } => prepare_and_run(
"remote-ref-list",
verbose,
progress,
progress_keep_open,
core::remote::refs::PROGRESS_RANGE,
move |progress, out, _err| {
core::remote::refs::list(
protocol,
&url,
git_features::progress::DoOrDiscard::from(progress),
core::remote::refs::Context {
thread_limit,
format,
out,
},
)
},
),
Subcommands::PackIndexFromData {
iteration_mode,
pack_path,
directory,
} => prepare_and_run(
"pack-index-from-data",
verbose,
progress,
progress_keep_open,
core::pack::index::PROGRESS_RANGE,
move |progress, out, _err| {
use gitoxide_core::pack::index::PathOrRead;
let input = if let Some(path) = pack_path {
PathOrRead::Path(path)
} else {
if atty::is(atty::Stream::Stdin) {
anyhow::bail!("Refusing to read from standard input as no path is given, but it's a terminal.")
}
PathOrRead::Read(Box::new(std::io::stdin()))
};
core::pack::index::from_pack(
input,
directory,
git_features::progress::DoOrDiscard::from(progress),
core::pack::index::Context {
thread_limit,
iteration_mode,
format,
out,
should_interrupt: &git_repository::interrupt::IS_INTERRUPTED,
},
)
},
),
Subcommands::PackExplode {
check,
sink_compress,
delete_pack,
pack_path,
object_path,
verify,
} => prepare_and_run(
"pack-explode",
verbose,
progress,
progress_keep_open,
None,
move |progress, _out, _err| {
core::pack::explode::pack_or_pack_index(
pack_path,
object_path,
check,
progress,
core::pack::explode::Context {
thread_limit,
delete_pack,
sink_compress,
verify,
should_interrupt,
},
)
},
),
Subcommands::PackVerify {
path,
algorithm,
decode,
re_encode,
statistics,
} => prepare_and_run(
"pack-verify",
verbose,
progress,
progress_keep_open,
None,
move |progress, out, err| {
let mode = match (decode, re_encode) {
(true, false) => verify::Mode::Sha1Crc32Decode,
(true, true) | (false, true) => verify::Mode::Sha1Crc32DecodeEncode,
(false, false) => verify::Mode::Sha1Crc32,
};
let output_statistics = if statistics { Some(format) } else { None };
verify::pack_or_pack_index(
path,
progress,
verify::Context {
output_statistics,
out,
err,
thread_limit,
mode,
algorithm,
should_interrupt,
},
)
},
)
.map(|_| ()),
Subcommands::CommitGraphVerify { path, statistics } => prepare_and_run(
"commit-graph-verify",
verbose,
progress,
progress_keep_open,
None,
move |_progress, out, err| {
let output_statistics = if statistics { Some(format) } else { None };
core::commitgraph::verify::graph_or_file(
path,
core::commitgraph::verify::Context {
err,
out,
output_statistics,
},
)
},
)
.map(|_| ()),
}?;
Ok(())
}