| #![allow(clippy::result_large_err)] |
| |
| use super::{util, Error}; |
| use crate::config::cache::util::ApplyLeniency; |
| use crate::config::tree::{Core, Extensions, Key}; |
| |
| /// 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>, |
| pub precompose_unicode: bool, |
| } |
| |
| /// 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, |
| lenient, |
| )?; |
| |
| // 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, |
| lenient, |
| )?; |
| config.append(worktree_config); |
| }; |
| let precompose_unicode = config |
| .boolean("core", None, Core::PRECOMPOSE_UNICODE.name()) |
| .map(|v| Core::PRECOMPOSE_UNICODE.enrich_error(v)) |
| .transpose() |
| .with_leniency(lenient) |
| .map_err(Error::ConfigBoolean)? |
| .unwrap_or_default(); |
| |
| let reflog = util::query_refupdates(&config, lenient)?; |
| Ok(StageOne { |
| git_dir_config: config, |
| buf, |
| is_bare, |
| lossy, |
| object_hash, |
| reflog, |
| precompose_unicode, |
| }) |
| } |
| } |
| |
| 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>, |
| lenient: bool, |
| ) -> Result<gix_config::File<'static>, Error> { |
| 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) => { |
| let err = Error::Io { |
| source: err, |
| path: config_path, |
| }; |
| if lenient { |
| gix_trace::warn!("ignoring: {err:#?}"); |
| return Ok(gix_config::File::new(metadata)); |
| } else { |
| return Err(err); |
| } |
| } |
| }; |
| |
| buf.clear(); |
| if let Err(err) = std::io::copy(&mut file, buf) { |
| let err = Error::Io { |
| source: err, |
| path: config_path, |
| }; |
| if lenient { |
| gix_trace::warn!("ignoring: {err:#?}"); |
| buf.clear(); |
| } else { |
| return Err(err); |
| } |
| }; |
| |
| 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, lenient) |
| }, |
| )?; |
| |
| Ok(config) |
| } |