git_sprout/
scratch_index.rs1use std::path::Path;
5
6use gix_hash::ObjectId;
7use gix_index::entry::{Flags, Mode, Stat};
8use gix_index::{write, File, State};
9
10#[derive(Debug, Clone)]
12pub struct Record {
13 pub path: Vec<u8>,
14 pub mode: u32,
16 pub oid: ObjectId,
17 pub stat: Stat,
19}
20
21#[derive(Debug)]
24pub enum Error {
25 UnknownMode(u32),
26 Write(gix_index::file::write::Error),
27}
28
29pub const SUPPORTED_VERSION: u32 = 2;
32
33const VERSION_RANGE: std::ops::RangeInclusive<u32> = 2..=4;
35
36pub fn default_version(
43 environment: Option<&str>,
44 configured: Option<&str>,
45 many_files: bool,
46) -> u32 {
47 let requested = environment
48 .or(configured)
49 .and_then(|value| value.trim().parse::<u32>().ok())
50 .or_else(|| many_files.then_some(4));
51 match requested {
52 Some(version) if VERSION_RANGE.contains(&version) => version,
53 _ => SUPPORTED_VERSION,
54 }
55}
56
57pub fn write(
59 index_path: &Path,
60 object_hash: gix_hash::Kind,
61 records: &[Record],
62) -> Result<(), Error> {
63 let mut state = State::new(object_hash);
64 for record in records {
65 let mode = Mode::from_bits(record.mode).ok_or(Error::UnknownMode(record.mode))?;
66 state.dangerously_push_entry(
67 record.stat,
68 record.oid,
69 Flags::empty(),
70 mode,
71 record.path.as_slice().into(),
72 );
73 }
74 state.sort_entries();
75 let mut file = File::from_state(state, index_path);
76 file.write(write::Options {
77 extensions: write::Extensions::None,
78 skip_hash: false,
79 })
80 .map_err(Error::Write)
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn a_plain_repository_gets_version_two() {
89 assert_eq!(default_version(None, None, false), 2);
90 }
91
92 #[test]
93 fn configuration_and_environment_choose_the_version() {
94 assert_eq!(default_version(None, Some("4"), false), 4);
95 assert_eq!(default_version(Some("3"), Some("4"), false), 3);
96 }
97
98 #[test]
99 fn many_files_asks_for_version_four() {
100 assert_eq!(default_version(None, None, true), 4);
101 assert_eq!(default_version(None, Some("2"), true), 2);
102 }
103
104 #[test]
105 fn an_impossible_version_falls_back_to_the_default() {
106 assert_eq!(default_version(None, Some("9"), false), 2);
107 assert_eq!(default_version(None, Some("nonsense"), false), 2);
108 }
109}