diff --git a/gitoxide-core/src/lib.rs b/gitoxide-core/src/lib.rs index 6c3f066b4a2..88065e5fe10 100644 --- a/gitoxide-core/src/lib.rs +++ b/gitoxide-core/src/lib.rs @@ -33,5 +33,6 @@ impl FromStr for OutputFormat { } } +pub mod pack; pub mod repository; pub mod verify; diff --git a/gitoxide-core/src/pack.rs b/gitoxide-core/src/pack.rs new file mode 100644 index 00000000000..1ea015611b8 --- /dev/null +++ b/gitoxide-core/src/pack.rs @@ -0,0 +1,12 @@ +pub mod explode { + use anyhow::Result; + use git_features::progress::Progress; + use std::path::Path; + + pub fn pack_or_pack_index
(_path: impl AsRef , _delete_pack: bool) -> Result<()>
+ where
+ P: Progress,
+ {
+ Ok(())
+ }
+}
diff --git a/src/plumbing/lean.rs b/src/plumbing/lean.rs
index ab766b9e59a..3e50d18c9bf 100644
--- a/src/plumbing/lean.rs
+++ b/src/plumbing/lean.rs
@@ -25,9 +25,29 @@ mod options {
#[argh(subcommand)]
pub enum SubCommands {
PackVerify(PackVerify),
+ PackExplode(PackExplode),
}
+ /// Explode a pack into loose objects.
+ ///
+ /// This can be useful in case of partially invalidated packs to extract as much information as possible,
+ /// or because working with loose objects is easier with custom tooling.
+ #[derive(FromArgs, PartialEq, Debug)]
+ #[argh(subcommand, name = "pack-explode")]
+ pub struct PackExplode {
+ /// delete the pack and index file after the operation is successful
+ #[argh(switch)]
+ pub delete_pack: bool,
- /// Initialize the repository in the current directory.
+ /// display verbose messages and progress information
+ #[argh(switch, short = 'v')]
+ pub verbose: bool,
+
+ /// the '.pack' or '.idx' file to explode into loose objects
+ #[argh(positional)]
+ pub path: PathBuf,
+ }
+
+ /// Verify a pack
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "pack-verify")]
pub struct PackVerify {
@@ -56,10 +76,10 @@ mod options {
/// output statistical information about the pack
#[argh(switch, short = 's')]
pub statistics: bool,
- /// verbose progress messages are printed line by line
+ /// display verbose messages and progress information
#[argh(switch, short = 'v')]
pub verbose: bool,
- /// the '.pack' or '.idx' data whose checksum to validate.
+ /// the '.pack' or '.idx' file whose checksum to validate.
#[argh(positional)]
pub path: PathBuf,
}
@@ -100,6 +120,14 @@ pub fn main() -> Result<()> {
let cli: Args = crate::shared::from_env();
let thread_limit = cli.threads;
match cli.subcommand {
+ SubCommands::PackExplode(PackExplode {
+ path,
+ verbose,
+ delete_pack,
+ }) => {
+ let (_handle, progress) = prepare(verbose, "pack-explode");
+ core::pack::explode::pack_or_pack_index(path, progress, delete_pack)
+ }
SubCommands::PackVerify(PackVerify {
path,
verbose,
diff --git a/src/plumbing/pretty.rs b/src/plumbing/pretty.rs
index 6da3e81fd39..f8ac49e8c0c 100644
--- a/src/plumbing/pretty.rs
+++ b/src/plumbing/pretty.rs
@@ -26,6 +26,31 @@ mod options {
#[derive(Debug, StructOpt)]
pub enum Subcommands {
+ /// Verify the integrity of a pack or index file
+ #[structopt(setting = AppSettings::ColoredHelp)]
+ PackExplode {
+ /// Delete the pack and index file after the operation is successful
+ #[structopt(long)]
+ delete_pack: bool,
+
+ /// Display verbose messages and progress information
+ #[structopt(long, short = "v")]
+ verbose: bool,
+
+ /// Bring up a terminal user interface displaying progress visually
+ #[structopt(long, conflicts_with("verbose"))]
+ progress: bool,
+
+ /// The progress TUI will stay up even though the work is already completed.
+ ///
+ /// Use this to be able to read progress messages or additional information visible in the TUI log pane.
+ #[structopt(long, conflicts_with("verbose"), requires("progress"))]
+ progress_keep_open: bool,
+
+ /// The '.pack' or '.idx' file to explode into loose objects
+ #[structopt(parse(from_os_str))]
+ path: PathBuf,
+ },
/// Verify the integrity of a pack or index file
#[structopt(setting = AppSettings::ColoredHelp)]
PackVerify {
@@ -50,23 +75,23 @@ mod options {
)]
algorithm: core::verify::Algorithm,
- /// verbose progress messages are printed line by line
+ /// Display verbose messages and progress information
#[structopt(long, short = "v")]
verbose: bool,
- /// bring up a terminal user interface displaying progress visually
+ /// Bring up a terminal user interface displaying progress visually
#[structopt(long, conflicts_with("verbose"))]
progress: bool,
#[structopt(long, conflicts_with("re-encode"))]
- /// decode and parse tags, commits and trees to validate their correctness beyond hashing correctly.
+ /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly.
///
/// Malformed objects should not usually occur, but could be injected on purpose or accident.
/// This will reduce overall performance.
decode: bool,
#[structopt(long)]
- /// decode and parse tags, commits and trees to validate their correctness, and re-encode them.
+ /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them.
///
/// This flag is primarily to test the implementation of encoding, and requires to decode the object first.
/// Encoding an object after decoding it should yield exactly the same bytes.
@@ -74,13 +99,13 @@ mod options {
/// owned objects, causing plenty of allocation to occour.
re_encode: bool,
- /// the progress TUI will stay up even though the work is already completed.
+ /// The progress TUI will stay up even though the work is already completed.
///
/// Use this to be able to read progress messages or additional information visible in the TUI log pane.
#[structopt(long, conflicts_with("verbose"), requires("progress"))]
progress_keep_open: bool,
- /// The '.pack' or '.idx' data whose checksum to validate.
+ /// The '.pack' or '.idx' file whose checksum to validate.
#[structopt(parse(from_os_str))]
path: PathBuf,
},
@@ -180,6 +205,19 @@ pub fn main() -> Result<()> {
let args = Args::from_args();
let thread_limit = args.threads;
match args.cmd {
+ Subcommands::PackExplode {
+ verbose,
+ progress,
+ progress_keep_open,
+ delete_pack,
+ path,
+ } => prepare_and_run(
+ "pack-explode",
+ verbose,
+ progress,
+ progress_keep_open,
+ move |progress, _out, _err| core::pack::explode::pack_or_pack_index(path, progress, delete_pack),
+ ),
Subcommands::PackVerify {
path,
algorithm,
diff --git a/tasks.md b/tasks.md
index a4db75f4f64..e651ce05c65 100644
--- a/tasks.md
+++ b/tasks.md
@@ -33,10 +33,11 @@
* [x] Deflate stream
* [x] disk - with decent errors
* [x] size as u64 (properly)
- * [ ] generalize pack reading algorithm
- * [ ] write loose object to memory
* **cli**
+ * [ ] generalize pack reading algorithm
* [ ] write objects from pack (multi-threaded comes for free)
+ * [ ] to sink
+ * [ ] to disk
* [ ] progress
* [ ] statistics
diff --git a/tests/snapshots/plumbing-pack-explode-to-sink-delete-pack-success b/tests/snapshots/plumbing-pack-explode-to-sink-delete-pack-success
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/snapshots/plumbing-pack-explode-to-sink-success b/tests/snapshots/plumbing-pack-explode-to-sink-success
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/stateless-journey.sh b/tests/stateless-journey.sh
index 3e838086c03..342240f44a4 100755
--- a/tests/stateless-journey.sh
+++ b/tests/stateless-journey.sh
@@ -40,6 +40,42 @@ title "CLI ${kind}"
)
)
+(when "running 'plumbing pack-explode"
+ PACK_FILE="$fixtures/packs/pack-11fdfa9e156ab73caae3b6da867192221f2089c2"
+ (with "no directory specified"
+ it "explodes the pack successfully and with desired output" && {
+ WITH_SNAPSHOT="$snapshot/plumbing-pack-explode-to-sink-success" \
+ expect_run $SUCCESSFULLY "$exe_plumbing" pack-explode "${PACK_FILE}.idx"
+ }
+
+ (when "using the --delete-pack flag"
+ (sandbox
+ cp ${PACK_FILE}.idx ${PACK_FILE}.pack .
+ PACK_FILE="${PACK_FILE##*/}"
+ (with "a valid pack"
+ it "explodes the pack successfully and deletes the original pack and index" && {
+ WITH_SNAPSHOT="$snapshot/plumbing-pack-explode-to-sink-delete-pack-success" \
+ expect_run $SUCCESSFULLY "$exe_plumbing" pack-explode --delete-pack "${PACK_FILE}.pack"
+ }
+ it "removes the original files" && {
+ expect_run $WITH_FAILURE ls ${PACK_FILE}.pack
+ expect_run $WITH_FAILURE ls ${PACK_FILE}.idx
+ }
+ )
+ (with "TODO(how to write into the middle of a file in bash): an invalid pack"
+
+ )
+ )
+ )
+ )
+ (with "a non-existing directory specified"
+
+ )
+ (with "an existing directory specified"
+
+ )
+)
+
(when "running 'plumbing pack-verify"
(with "a valid pack file"
PACK_FILE="$fixtures/packs/pack-11fdfa9e156ab73caae3b6da867192221f2089c2.pack"