gitoxide_core/repository/index/
mod.rs

1use std::{ffi::OsString, path::PathBuf};
2
3use anyhow::bail;
4
5pub fn from_tree(
6    repo: gix::Repository,
7    mut spec: OsString,
8    index_path: Option<PathBuf>,
9    force: bool,
10    skip_hash: bool,
11) -> anyhow::Result<()> {
12    spec.push("^{tree}");
13    let spec = gix::path::os_str_into_bstr(&spec)?;
14    let tree = repo.rev_parse_single(spec)?;
15
16    let mut index = repo.index_from_tree(&tree)?;
17    let options = gix::index::write::Options {
18        skip_hash,
19        ..Default::default()
20    };
21
22    match index_path {
23        Some(index_path) => {
24            if index_path.is_file() && !force {
25                anyhow::bail!(
26                    "File at \"{}\" already exists, to overwrite use the '-f' flag",
27                    index_path.display()
28                );
29            }
30            index.set_path(index_path);
31            index.write(options)?;
32        }
33        None => {
34            let mut out = Vec::with_capacity(512 * 1024);
35            index.write_to(&mut out, options)?;
36        }
37    }
38
39    Ok(())
40}
41
42pub fn from_list(
43    entries_file: PathBuf,
44    index_path: Option<PathBuf>,
45    force: bool,
46    skip_hash: bool,
47) -> anyhow::Result<()> {
48    use std::io::BufRead;
49    let object_hash = gix::hash::Kind::Sha1;
50
51    let mut index = gix::index::State::new(object_hash);
52    for path in std::io::BufReader::new(std::fs::File::open(entries_file)?).lines() {
53        let path: PathBuf = path?.into();
54        if !path.is_relative() {
55            bail!("Input paths need to be relative, but {path:?} is not.")
56        }
57        let path = gix::path::into_bstr(path);
58        index.dangerously_push_entry(
59            gix::index::entry::Stat::default(),
60            gix::hash::ObjectId::empty_blob(object_hash),
61            gix::index::entry::Flags::empty(),
62            gix::index::entry::Mode::FILE,
63            gix::path::to_unix_separators_on_windows(path).as_ref(),
64        );
65    }
66    index.sort_entries();
67
68    let options = gix::index::write::Options {
69        skip_hash,
70        ..Default::default()
71    };
72    match index_path {
73        Some(index_path) => {
74            if index_path.is_file() && !force {
75                anyhow::bail!(
76                    "File at \"{}\" already exists, to overwrite use the '-f' flag",
77                    index_path.display()
78                );
79            }
80            let mut index = gix::index::File::from_state(index, index_path);
81            index.write(options)?;
82        }
83        None => {
84            let index = gix::index::File::from_state(index, std::path::PathBuf::new());
85            let mut out = Vec::with_capacity(512 * 1024);
86            index.write_to(&mut out, options)?;
87        }
88    }
89
90    Ok(())
91}
92
93pub mod entries;
94pub use entries::function::entries;