1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use super::{util, Error};
pub(crate) struct StageOne {
pub git_dir_config: git_config::File<'static>,
pub buf: Vec<u8>,
pub is_bare: bool,
pub lossy: Option<bool>,
pub object_hash: git_hash::Kind,
pub reflog: Option<git_ref::store::WriteReflog>,
}
impl StageOne {
pub fn new(
common_dir: &std::path::Path,
git_dir: &std::path::Path,
git_dir_trust: git_sec::Trust,
lossy: Option<bool>,
lenient: bool,
) -> Result<Self, Error> {
let mut buf = Vec::with_capacity(512);
let mut config = load_config(
common_dir.join("config"),
&mut buf,
git_config::Source::Local,
git_dir_trust,
lossy,
)?;
let is_bare = util::config_bool(&config, "core.bare", true, lenient)?;
let repo_format_version = config
.value::<git_config::Integer>("core", None, "repositoryFormatVersion")
.map_or(0, |v| v.to_decimal().unwrap_or_default());
let object_hash = (repo_format_version != 1)
.then(|| Ok(git_hash::Kind::Sha1))
.or_else(|| {
config.string("extensions", None, "objectFormat").map(|format| {
if format.as_ref().eq_ignore_ascii_case(b"sha1") {
Ok(git_hash::Kind::Sha1)
} else {
Err(Error::UnsupportedObjectFormat {
name: format.to_vec().into(),
})
}
})
})
.transpose()?
.unwrap_or(git_hash::Kind::Sha1);
let extension_worktree = util::config_bool(&config, "extensions.worktreeConfig", false, lenient)?;
if extension_worktree {
let worktree_config = load_config(
git_dir.join("config.worktree"),
&mut buf,
git_config::Source::Worktree,
git_dir_trust,
lossy,
)?;
config.append(worktree_config);
};
let reflog = util::query_refupdates(&config, lenient)?;
Ok(StageOne {
git_dir_config: config,
buf,
is_bare,
lossy,
object_hash,
reflog,
})
}
}
fn load_config(
config_path: std::path::PathBuf,
buf: &mut Vec<u8>,
source: git_config::Source,
git_dir_trust: git_sec::Trust,
lossy: Option<bool>,
) -> Result<git_config::File<'static>, Error> {
buf.clear();
let mut file = match std::fs::File::open(&config_path) {
Ok(f) => f,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(git_config::File::default()),
Err(err) => return Err(err.into()),
};
std::io::copy(&mut file, buf)?;
let config = git_config::File::from_bytes_owned(
buf,
git_config::file::Metadata::from(source)
.at(config_path)
.with(git_dir_trust),
git_config::file::init::Options {
includes: git_config::file::includes::Options::no_follow(),
..util::base_options(lossy)
},
)?;
Ok(config)
}