Skip to content

Commit 89428b2

Browse files
committed
Basic multi-pack index creation (#279)
Could imagine providing statistics as part of the creation result.
1 parent c4c5678 commit 89428b2

File tree

7 files changed

+117
-8
lines changed

7 files changed

+117
-8
lines changed

Diff for: git-hash/src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
mod borrowed;
88

99
use std::convert::TryFrom;
10+
use std::str::FromStr;
1011

1112
pub use borrowed::oid;
1213

@@ -85,6 +86,17 @@ impl TryFrom<u8> for Kind {
8586
}
8687
}
8788

89+
impl FromStr for Kind {
90+
type Err = String;
91+
92+
fn from_str(s: &str) -> Result<Self, Self::Err> {
93+
Ok(match s {
94+
"sha1" | "SHA1" => Kind::Sha1,
95+
other => return Err(other.into()),
96+
})
97+
}
98+
}
99+
88100
impl Kind {
89101
/// Returns the shortest hash we support
90102
#[inline]

Diff for: gitoxide-core/src/pack/index.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct Context<'a, W: io::Write> {
5555
pub format: OutputFormat,
5656
pub should_interrupt: &'a AtomicBool,
5757
pub out: W,
58+
pub object_hash: git_repository::hash::Kind,
5859
}
5960

6061
pub fn stream_len(mut s: impl io::Seek) -> io::Result<u64> {
@@ -85,7 +86,7 @@ pub fn from_pack(
8586
thread_limit: ctx.thread_limit,
8687
iteration_mode: ctx.iteration_mode.into(),
8788
index_kind: pack::index::Version::default(),
88-
object_hash: git_repository::hash::Kind::Sha1, // TODO: make this configurable via CLI, context
89+
object_hash: ctx.object_hash,
8990
};
9091
let out = ctx.out;
9192
let format = ctx.format;

Diff for: gitoxide-core/src/pack/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod explode;
22
pub mod index;
3+
pub mod multi_index;
34
pub mod verify;
45

56
#[cfg(any(feature = "async-client", feature = "blocking-client"))]

Diff for: gitoxide-core/src/pack/multi_index.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use git_repository::Progress;
2+
use std::io::BufWriter;
3+
use std::path::PathBuf;
4+
use std::sync::atomic::AtomicBool;
5+
6+
use git_repository as git;
7+
8+
pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 2..=3;
9+
10+
pub fn create(
11+
index_paths: Vec<PathBuf>,
12+
output_path: PathBuf,
13+
progress: impl Progress,
14+
should_interrupt: &AtomicBool,
15+
object_hash: git::hash::Kind,
16+
) -> anyhow::Result<()> {
17+
let mut out = BufWriter::new(git::lock::File::acquire_to_update_resource(
18+
output_path,
19+
git::lock::acquire::Fail::Immediately,
20+
None,
21+
)?);
22+
git::odb::pack::multi_index::File::write_from_index_paths(
23+
index_paths,
24+
&mut out,
25+
progress,
26+
should_interrupt,
27+
git::odb::pack::multi_index::write::Options { object_hash },
28+
)?;
29+
out.into_inner()?.commit()?;
30+
Ok(())
31+
}

Diff for: src/plumbing/main.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub fn main() -> Result<()> {
5151
let verbose = args.verbose;
5252
let format = args.format;
5353
let cmd = args.cmd;
54+
let object_hash = args.object_hash;
5455

5556
let progress;
5657
let progress_keep_open;
@@ -241,13 +242,34 @@ pub fn main() -> Result<()> {
241242
},
242243
)
243244
.map(|_| ()),
245+
pack::Subcommands::MultiIndex(subcommands) => match subcommands {
246+
pack::multi_index::Subcommands::Create {
247+
output_path,
248+
index_paths,
249+
} => prepare_and_run(
250+
"pack-multi-index-create",
251+
verbose,
252+
progress,
253+
progress_keep_open,
254+
core::pack::multi_index::PROGRESS_RANGE,
255+
move |progress, _out, _err| {
256+
core::pack::multi_index::create(
257+
index_paths,
258+
output_path,
259+
progress,
260+
&git_repository::interrupt::IS_INTERRUPTED,
261+
object_hash,
262+
)
263+
},
264+
),
265+
},
244266
pack::Subcommands::Index(subcommands) => match subcommands {
245267
pack::index::Subcommands::Create {
246268
iteration_mode,
247269
pack_path,
248270
directory,
249271
} => prepare_and_run(
250-
"pack-index-from-data",
272+
"pack-index-create",
251273
verbose,
252274
progress,
253275
progress_keep_open,
@@ -273,6 +295,7 @@ pub fn main() -> Result<()> {
273295
iteration_mode,
274296
format,
275297
out,
298+
object_hash,
276299
should_interrupt: &git_repository::interrupt::IS_INTERRUPTED,
277300
},
278301
)
@@ -321,7 +344,7 @@ pub fn main() -> Result<()> {
321344
},
322345
Subcommands::Commitgraph(subcommands) => match subcommands {
323346
commitgraph::Subcommands::Verify { path, statistics } => prepare_and_run(
324-
"commit-graph-verify",
347+
"commitgraph-verify",
325348
verbose,
326349
progress,
327350
progress_keep_open,

Diff for: src/plumbing/options.rs

+33-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub struct Args {
3636
)]
3737
pub format: core::OutputFormat,
3838

39+
/// The object format to assume when reading files that don't inherently know about it, or when writing files.
40+
#[clap(long, default_value = "sha1", possible_values(&["sha1"]))]
41+
pub object_hash: git_repository::hash::Kind,
42+
3943
#[clap(subcommand)]
4044
pub cmd: Subcommands,
4145
}
@@ -63,6 +67,12 @@ pub mod pack {
6367

6468
#[derive(Debug, clap::Parser)]
6569
pub enum Subcommands {
70+
/// Subcommands for interacting with pack indices (.idx)
71+
#[clap(subcommand)]
72+
Index(index::Subcommands),
73+
/// Subcommands for interacting with multi-pack indices (named "multi-pack-index")
74+
#[clap(subcommand)]
75+
MultiIndex(multi_index::Subcommands),
6676
/// Create a new pack with a set of objects.
6777
#[clap(setting = AppSettings::DisableVersionFlag)]
6878
Create {
@@ -153,9 +163,6 @@ pub mod pack {
153163
/// If unset, they will be discarded.
154164
directory: Option<PathBuf>,
155165
},
156-
/// Subcommands for interacting with pack indices (.idx)
157-
#[clap(subcommand)]
158-
Index(index::Subcommands),
159166
/// Dissolve a pack into its loose objects.
160167
///
161168
/// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process.
@@ -234,6 +241,29 @@ pub mod pack {
234241
},
235242
}
236243

244+
///
245+
pub mod multi_index {
246+
use clap::AppSettings;
247+
use std::path::PathBuf;
248+
249+
#[derive(Debug, clap::Parser)]
250+
pub enum Subcommands {
251+
/// create a multi-pack index from one or more pack index files
252+
#[clap(setting = AppSettings::DisableVersionFlag)]
253+
Create {
254+
/// The path to which the multi-index file should be written, overwriting any possibly existing file.
255+
///
256+
/// Note for the multi-index to be useful, it should be side-by-side with the supplied `.idx` files.
257+
#[clap(long, short = 'o')]
258+
output_path: PathBuf,
259+
260+
/// Paths to the pack index files to read (with .idx extension).
261+
#[clap(required = true)]
262+
index_paths: Vec<PathBuf>,
263+
},
264+
}
265+
}
266+
237267
///
238268
pub mod index {
239269
use clap::AppSettings;

Diff for: tests/journey/gix.sh

+13-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ title "git-tempfile crate"
4242
title "gix pack"
4343
(when "running 'pack'"
4444
snapshot="$snapshot/pack"
45-
45+
4646
title "gix pack receive"
4747
(with "the 'receive' sub-command"
4848
snapshot="$snapshot/receive"
@@ -265,7 +265,18 @@ title "gix pack"
265265

266266
title "gix pack multi-index"
267267
(with "the 'multi-index' sub-command"
268-
268+
snapshot="$snapshot/multi-index"
269+
title "gix pack multi-index create"
270+
(with "the 'create' sub-command"
271+
snapshot="$snapshot/create"
272+
(with 'multiple pack indices'
273+
(sandbox
274+
it "creates a multi-index successfully" && {
275+
expect_run $SUCCESSFULLY "$exe_plumbing" pack multi-index create $fixtures/packs/pack-*.idx -o multi-pack-index
276+
}
277+
)
278+
)
279+
)
269280
)
270281

271282
title "gix pack explode"

0 commit comments

Comments
 (0)