Skip to content

Commit

Permalink
Parse the hex-len from config on repo-initialization (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Apr 5, 2022
1 parent 2381c5d commit aee55c0
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 32 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 40 additions & 3 deletions git-repository/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
use crate::bstr::BString;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Could not open repository conifguration file")]
Open(#[from] git_config::parser::ParserOrIoError<'static>),
#[error("Cannot handle objects formatted as {:?}", .name)]
UnsupportedObjectFormat { name: crate::bstr::BString },
#[error("The value for '{}' cannot be empty", .key)]
EmptyValue { key: &'static str },
#[error("Invalid value for 'core.abbrev' = '{}'. It must be between 4 and {}", .value, .max)]
CoreAbbrev { value: BString, max: u8 },
}

/// Utility type to keep pre-obtained configuration values.
#[derive(Debug, Clone)]
pub(crate) struct Cache {
pub resolved: crate::Config,
/// The hex-length to assume when shortening object ids. If `None`, it should be computed based on the approximate object count.
pub hex_len: Option<u8>,
pub hex_len: Option<usize>,
/// true if the repository is designated as 'bare', without work tree
pub is_bare: bool,
/// The type of hash to use
Expand All @@ -22,9 +28,12 @@ pub(crate) struct Cache {

mod cache {
use super::{Cache, Error};
use crate::bstr::ByteSlice;
use git_config::file::GitConfig;
use git_config::values;
use git_config::values::{Boolean, Integer};
use std::borrow::Cow;
use std::convert::TryFrom;

impl Cache {
pub fn new(git_dir: &std::path::Path) -> Result<Self, Error> {
Expand All @@ -51,12 +60,40 @@ mod cache {
git_hash::Kind::Sha1
};

let mut hex_len = None;
if let Ok(hex_len_str) = config.value::<values::String<'_>>("core", None, "abbrev") {
if hex_len_str.value.trim().len() == 0 {
return Err(Error::EmptyValue { key: "core.abbrev" });
}
if hex_len_str.value.as_ref() != "auto" {
let value_bytes = hex_len_str.value.as_ref().as_ref();
if let Ok(Boolean::False(_)) = Boolean::try_from(value_bytes) {
hex_len = object_hash.len_in_hex().into();
} else {
// TODO: let it resolve the suffix
let value = Integer::try_from(value_bytes)
.map_err(|_| Error::CoreAbbrev {
value: hex_len_str.value.clone().into_owned(),
max: object_hash.len_in_hex() as u8,
})?
.value;
if value < 4 || value as usize > object_hash.len_in_hex() {
return Err(Error::CoreAbbrev {
value: hex_len_str.value.clone().into_owned(),
max: object_hash.len_in_hex() as u8,
});
}
hex_len = Some(value as usize);
}
}
}

Ok(Cache {
resolved: config.into(),
use_multi_pack_index,
object_hash,
is_bare,
hex_len: None,
hex_len,
})
}
}
Expand All @@ -65,6 +102,6 @@ mod cache {
let (section, key) = key.split_once('.').expect("valid section.key format");
config
.value::<Boolean<'_>>(section, None, key)
.map_or(default, |b| matches!(b, Boolean::True(_)))
.map_or(default, |b| b.to_bool())
}
}
35 changes: 9 additions & 26 deletions git-repository/src/id.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//!
use std::{convert::TryInto, ops::Deref};
use std::ops::Deref;

use git_hash::{oid, ObjectId};

Expand Down Expand Up @@ -27,18 +27,13 @@ impl<'repo> Id<'repo> {

/// Turn this object id into a shortened id with a length in hex as configured by `core.abbrev`.
pub fn shorten(&self) -> Result<git_hash::Prefix, shorten::Error> {
let hex_len = self.repo.config_int("core.abbrev", 7);
let hex_len = hex_len.try_into().map_err(|_| shorten::Error::ConfigValue {
actual: hex_len,
max_range: self.inner.kind().len_in_hex(),
err: None,
})?;
let prefix =
git_odb::find::PotentialPrefix::new(self.inner, hex_len).map_err(|err| shorten::Error::ConfigValue {
actual: hex_len as i64,
max_range: self.inner.kind().len_in_hex(),
err: Some(err),
})?;
let hex_len = self.repo.config.hex_len.unwrap_or(
// TODO: obtain calculated value
7,
);
// NOTE: this error shouldn't be possible
let prefix = git_odb::find::PotentialPrefix::new(self.inner, hex_len)
.expect("BUG: internal hex-len must always be valid");
Ok(self
.repo
.objects
Expand All @@ -51,19 +46,7 @@ impl<'repo> Id<'repo> {
///
pub mod shorten {
/// Returned by [`Id::prefix()`][super::Id::shorten()].
#[derive(thiserror::Error, Debug)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
FindExisting(#[from] crate::object::find::existing::OdbError),
#[error("core.abbrev length was {}, but needs to be between 4 and {}", .actual, .max_range)]
ConfigValue {
#[source]
err: Option<git_hash::prefix::Error>,
actual: i64,
max_range: usize,
},
}
pub type Error = crate::object::find::existing::OdbError;
}

impl<'repo> Deref for Id<'repo> {
Expand Down
4 changes: 1 addition & 3 deletions git-repository/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ mod init {
}
},
refs,
config: config,
config,
}
}

Expand All @@ -82,8 +82,6 @@ mod impls;

mod cache;

mod config;

mod reference;

mod object;
Expand Down

0 comments on commit aee55c0

Please sign in to comment.