summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/config/cache/incubate.rs
blob: 047f2132b52c19fcf748509861c8fb493ae892c0 (plain)
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
107
108
109
110
111
#![allow(clippy::result_large_err)]
use super::{util, Error};
use crate::config::tree::{Core, Extensions};

/// A utility to deal with the cyclic dependency between the ref store and the configuration. The ref-store needs the
/// object hash kind, and the configuration needs the current branch name to resolve conditional includes with `onbranch`.
pub(crate) struct StageOne {
    pub git_dir_config: gix_config::File<'static>,
    pub buf: Vec<u8>,

    pub is_bare: bool,
    pub lossy: Option<bool>,
    pub object_hash: gix_hash::Kind,
    pub reflog: Option<gix_ref::store::WriteReflog>,
}

/// Initialization
impl StageOne {
    pub fn new(
        common_dir: &std::path::Path,
        git_dir: &std::path::Path,
        git_dir_trust: gix_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,
            gix_config::Source::Local,
            git_dir_trust,
            lossy,
        )?;

        // Note that we assume the repo is bare by default unless we are told otherwise. This is relevant if
        // the repo doesn't have a configuration file.
        let is_bare = util::config_bool(&config, &Core::BARE, "core.bare", true, lenient)?;
        let repo_format_version = config
            .integer_by_key("core.repositoryFormatVersion")
            .map(|version| Core::REPOSITORY_FORMAT_VERSION.try_into_usize(version))
            .transpose()?
            .unwrap_or_default();
        let object_hash = (repo_format_version != 1)
            .then_some(Ok(gix_hash::Kind::Sha1))
            .or_else(|| {
                config
                    .string("extensions", None, "objectFormat")
                    .map(|format| Extensions::OBJECT_FORMAT.try_into_object_format(format))
            })
            .transpose()?
            .unwrap_or(gix_hash::Kind::Sha1);

        let extension_worktree = util::config_bool(
            &config,
            &Extensions::WORKTREE_CONFIG,
            "extensions.worktreeConfig",
            false,
            lenient,
        )?;
        if extension_worktree {
            let worktree_config = load_config(
                git_dir.join("config.worktree"),
                &mut buf,
                gix_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: gix_config::Source,
    git_dir_trust: gix_sec::Trust,
    lossy: Option<bool>,
) -> Result<gix_config::File<'static>, Error> {
    buf.clear();
    let metadata = gix_config::file::Metadata::from(source)
        .at(&config_path)
        .with(git_dir_trust);
    let mut file = match std::fs::File::open(&config_path) {
        Ok(f) => f,
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(gix_config::File::new(metadata)),
        Err(err) => return Err(err.into()),
    };
    std::io::copy(&mut file, buf)?;

    let config = gix_config::File::from_bytes_owned(
        buf,
        metadata,
        gix_config::file::init::Options {
            includes: gix_config::file::includes::Options::no_follow(),
            ..util::base_options(lossy)
        },
    )?;

    Ok(config)
}