Skip to content

Commit b8db207

Browse files
committed
feat: no-repo index from-list to create an index with empty files from the given list.
The list could be created with `find . -type f` for example.
1 parent edeb4de commit b8db207

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

Diff for: gitoxide-core/src/repository/index/mod.rs

+44
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::bail;
12
use std::{ffi::OsString, path::PathBuf};
23

34
use gix::prelude::FindExt;
@@ -35,5 +36,48 @@ pub fn from_tree(
3536
Ok(())
3637
}
3738

39+
pub fn from_list(entries_file: PathBuf, index_path: Option<PathBuf>, force: bool) -> anyhow::Result<()> {
40+
use std::io::BufRead;
41+
let object_hash = gix::hash::Kind::Sha1;
42+
43+
let mut index = gix::index::State::new(object_hash);
44+
for path in std::io::BufReader::new(std::fs::File::open(&entries_file)?).lines() {
45+
let path: PathBuf = path?.into();
46+
if !path.is_relative() {
47+
bail!("Input paths need to be relative, but {path:?} is not.")
48+
}
49+
let path = gix::path::into_bstr(path);
50+
index.dangerously_push_entry(
51+
gix::index::entry::Stat::default(),
52+
gix::hash::ObjectId::empty_blob(object_hash),
53+
gix::index::entry::Flags::empty(),
54+
gix::index::entry::Mode::FILE,
55+
gix::path::to_unix_separators_on_windows(path).as_ref(),
56+
)
57+
}
58+
index.sort_entries();
59+
60+
let options = gix::index::write::Options::default();
61+
match index_path {
62+
Some(index_path) => {
63+
if index_path.is_file() && !force {
64+
anyhow::bail!(
65+
"File at \"{}\" already exists, to overwrite use the '-f' flag",
66+
index_path.display()
67+
);
68+
}
69+
let mut index = gix::index::File::from_state(index, index_path);
70+
index.write(options)?;
71+
}
72+
None => {
73+
let index = gix::index::File::from_state(index, std::path::PathBuf::new());
74+
let mut out = Vec::with_capacity(512 * 1024);
75+
index.write_to(&mut out, options)?;
76+
}
77+
}
78+
79+
Ok(())
80+
}
81+
3882
pub mod entries;
3983
pub use entries::function::entries;

Diff for: src/plumbing/main.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,26 @@ pub fn main() -> Result<()> {
293293
index_path,
294294
cmd,
295295
}) => match cmd {
296+
free::index::Subcommands::FromList {
297+
force,
298+
index_output_path,
299+
file,
300+
} => prepare_and_run(
301+
"index-from-list",
302+
verbose,
303+
progress,
304+
progress_keep_open,
305+
None,
306+
move |_progress, _out, _err| core::repository::index::from_list(file, index_output_path, force),
307+
),
296308
free::index::Subcommands::CheckoutExclusive {
297309
directory,
298310
empty_files,
299311
repository,
300312
keep_going,
301313
} => prepare_and_run(
302314
"index-checkout",
303-
verbose,
315+
auto_verbose,
304316
progress,
305317
progress_keep_open,
306318
None,

Diff for: src/plumbing/options/free.rs

+13
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@ pub mod index {
5353

5454
#[derive(Debug, clap::Subcommand)]
5555
pub enum Subcommands {
56+
/// Create an index from a list of empty files, one per line of the input.
57+
FromList {
58+
/// Overwrite the specified index file if it already exists.
59+
#[clap(long, short = 'f')]
60+
force: bool,
61+
/// Path to the index file to be written.
62+
/// If none is given it will be kept in memory only as a way to measure performance. One day we will probably write the index
63+
/// back by default, but that requires us to write more of the index to work.
64+
#[clap(long, short = 'i')]
65+
index_output_path: Option<PathBuf>,
66+
/// The file to read the index entries from, one path per line.
67+
file: PathBuf,
68+
},
5669
/// Validate constraints and assumptions of an index along with its integrity.
5770
Verify,
5871
/// Print information about the index structure

0 commit comments

Comments
 (0)