Skip to content

Commit

Permalink
feat: add gitoxide.core.refsNamespace key and respect the `GIT_NAME…
Browse files Browse the repository at this point in the history
…SPACE` environment variable.

It's also provided as context value.
  • Loading branch information
Byron committed Nov 25, 2023
1 parent 0b3eb14 commit 8434aab
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 11 deletions.
19 changes: 15 additions & 4 deletions gix/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ impl Cache {

use util::config_bool;
let reflog = util::query_refupdates(&config, lenient_config)?;
let refs_namespace = util::query_refs_namespace(&config, lenient_config)?;
let ignore_case = config_bool(&config, &Core::IGNORE_CASE, "core.ignoreCase", false, lenient_config)?;
let use_multi_pack_index = config_bool(
&config,
Expand All @@ -167,6 +168,7 @@ impl Cache {
pack_cache_bytes,
object_cache_bytes,
reflog,
refs_namespace,
is_bare,
ignore_case,
hex_len,
Expand Down Expand Up @@ -223,10 +225,12 @@ impl Cache {
self.object_kind_hint = object_kind_hint;
}
let reflog = util::query_refupdates(config, self.lenient_config)?;
let refs_namespace = util::query_refs_namespace(config, self.lenient_config)?;

self.hex_len = hex_len;
self.ignore_case = ignore_case;
self.reflog = reflog;
self.refs_namespace = refs_namespace;

self.user_agent = Default::default();
self.personas = Default::default();
Expand Down Expand Up @@ -299,6 +303,7 @@ impl crate::Repository {

fn apply_changed_values(&mut self) {
self.refs.write_reflog = util::reflog_or_default(self.config.reflog, self.work_dir().is_some());
self.refs.namespace = self.config.refs_namespace.clone();
}
}

Expand Down Expand Up @@ -413,10 +418,16 @@ fn apply_environment_overrides(
"gitoxide",
Some(Cow::Borrowed("core".into())),
git_prefix,
&[{
let key = &gitoxide::Core::SHALLOW_FILE;
(env(key), key.name)
}],
&[
{
let key = &gitoxide::Core::SHALLOW_FILE;
(env(key), key.name)
},
{
let key = &gitoxide::Core::REFS_NAMESPACE;
(env(key), key.name)
},
],
),
(
"gitoxide",
Expand Down
12 changes: 12 additions & 0 deletions gix/src/config/cache/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ pub(crate) fn query_refupdates(
.map_err(Into::into)
}

pub(crate) fn query_refs_namespace(
config: &gix_config::File<'static>,
lenient_config: bool,
) -> Result<Option<gix_ref::Namespace>, config::refs_namespace::Error> {
let key = "gitoxide.core.refsNamespace";
config
.string_by_key(key)
.map(|ns| gitoxide::Core::REFS_NAMESPACE.try_into_refs_namespace(ns))
.transpose()
.with_leniency(lenient_config)
}

pub(crate) fn reflog_or_default(
config_reflog: Option<gix_ref::store::WriteReflog>,
has_worktree: bool,
Expand Down
14 changes: 12 additions & 2 deletions gix/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub enum Error {
ConfigUnsigned(#[from] unsigned_integer::Error),
#[error(transparent)]
ConfigTypedString(#[from] key::GenericErrorWithValue),
#[error(transparent)]
RefsNamespace(#[from] refs_namespace::Error),
#[error("Cannot handle objects formatted as {:?}", .name)]
UnsupportedObjectFormat { name: BString },
#[error(transparent)]
Expand Down Expand Up @@ -167,10 +169,10 @@ pub mod command_context {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
PathSpec(#[from] gix_pathspec::defaults::from_environment::Error),
#[error(transparent)]
Boolean(#[from] config::boolean::Error),
#[error(transparent)]
ParseBool(#[from] gix_config::value::Error),
}
}

Expand Down Expand Up @@ -430,6 +432,12 @@ pub mod refspec {
pub type Error = super::key::Error<gix_refspec::parse::Error, 'r', 'p'>;
}

///
pub mod refs_namespace {
/// The error produced when failing to parse a refspec from the configuration.
pub type Error = super::key::Error<gix_validate::reference::name::Error, 'v', 'i'>;
}

///
pub mod ssl_version {
/// The error produced when failing to parse a refspec from the configuration.
Expand Down Expand Up @@ -526,6 +534,8 @@ pub(crate) struct Cache {
pub use_multi_pack_index: bool,
/// The representation of `core.logallrefupdates`, or `None` if the variable wasn't set.
pub reflog: Option<gix_ref::store::WriteReflog>,
/// The representation of `gitoxide.core.refsNamespace`, or `None` if the variable wasn't set.
pub refs_namespace: Option<gix_ref::Namespace>,
/// The configured user agent for presentation to servers.
pub(crate) user_agent: OnceCell<String>,
/// identities for later use, lazy initialization.
Expand Down
28 changes: 28 additions & 0 deletions gix/src/config/tree/sections/gitoxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ mod subsections {
#[derive(Copy, Clone, Default)]
pub struct Core;

/// The `gitoxide.allow.protocolFromUser` key.
pub type RefsNamespace = keys::Any<super::validate::RefsNamespace>;

impl RefsNamespace {
/// Derive the negotiation algorithm identified by `name`, case-sensitively.
pub fn try_into_refs_namespace(
&'static self,
name: std::borrow::Cow<'_, crate::bstr::BStr>,
) -> Result<gix_ref::Namespace, crate::config::refs_namespace::Error> {
gix_ref::namespace::expand(name.as_ref())
.map_err(|err| crate::config::key::Error::from_value(self, name.into_owned()).with_source(err))
}
}

impl Core {
/// The `gitoxide.core.defaultPackCacheMemoryLimit` key.
pub const DEFAULT_PACK_CACHE_MEMORY_LIMIT: keys::UnsignedInteger =
Expand All @@ -100,6 +114,11 @@ mod subsections {
/// It controls whether or not long running filter driver processes can use the 'delay' capability.
pub const FILTER_PROCESS_DELAY: keys::Boolean =
keys::Boolean::new_boolean("filterProcessDelay", &Gitoxide::CORE);

/// The `gitoxide.core.refsNamespace` key.
pub const REFS_NAMESPACE: RefsNamespace =
keys::Any::new_with_validate("refsNamespace", &Gitoxide::CORE, super::validate::RefsNamespace)
.with_environment_override("GIT_NAMESPACE");
}

impl Section for Core {
Expand All @@ -114,6 +133,7 @@ mod subsections {
&Self::USE_STDEV,
&Self::SHALLOW_FILE,
&Self::FILTER_PROCESS_DELAY,
&Self::REFS_NAMESPACE,
]
}

Expand Down Expand Up @@ -496,4 +516,12 @@ pub mod validate {
Ok(())
}
}

pub struct RefsNamespace;
impl Validate for RefsNamespace {
fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
super::Core::REFS_NAMESPACE.try_into_refs_namespace(value.into())?;
Ok(())
}
}
}
1 change: 1 addition & 0 deletions gix/src/open/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ impl ThreadSafeRepository {
}

refs.write_reflog = config::cache::util::reflog_or_default(config.reflog, worktree_dir.is_some());
refs.namespace = config.refs_namespace.clone();
let replacements = replacement_objects_refs_prefix(&config.resolved, lenient_config, filter_config_section)?
.and_then(|prefix| {
let _span = gix_trace::detail!("find replacement objects");
Expand Down
20 changes: 16 additions & 4 deletions gix/src/repository/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ impl crate::Repository {
/// hooks or filters.
#[cfg(feature = "attributes")]
pub fn command_context(&self) -> Result<gix_command::Context, config::command_context::Error> {
use crate::config::cache::util::ApplyLeniency;
use crate::config::tree::gitoxide;
use crate::config::tree::Key;

let boolean = |key: &dyn Key| {
self.config
.resolved
.boolean("gitoxide", Some("pathspec".into()), key.name())
.transpose()
.with_leniency(self.config.lenient_config)
};

Ok(gix_command::Context {
git_dir: self.git_dir().to_owned().into(),
worktree_dir: self.work_dir().map(ToOwned::to_owned),
Expand All @@ -92,10 +104,10 @@ impl crate::Repository {
self.filter_config_section(),
)?
.map(|enabled| !enabled),
ref_namespace: None,
literal_pathspecs: None,
glob_pathspecs: None,
icase_pathspecs: None,
ref_namespace: self.refs.namespace.as_ref().map(|ns| ns.as_bstr().to_owned()),
literal_pathspecs: boolean(&gitoxide::Pathspec::LITERAL)?,
glob_pathspecs: boolean(&gitoxide::Pathspec::GLOB)?.or(boolean(&gitoxide::Pathspec::NOGLOB)?),
icase_pathspecs: boolean(&gitoxide::Pathspec::ICASE)?,
})
}

Expand Down
15 changes: 14 additions & 1 deletion gix/tests/gix-init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ mod with_overrides {
.set("GIT_NOGLOB_PATHSPECS", "pathspecs-noglob")
.set("GIT_ICASE_PATHSPECS", "pathspecs-icase")
.set("GIT_TERMINAL_PROMPT", "42")
.set("GIT_SHALLOW_FILE", "shallow-file-env");
.set("GIT_SHALLOW_FILE", "shallow-file-env")
.set("GIT_NAMESPACE", "namespace-env");
let mut opts = gix::open::Options::isolated()
.cli_overrides([
"http.userAgent=agent-from-cli",
Expand All @@ -62,6 +63,7 @@ mod with_overrides {
"gitoxide.ssh.commandWithoutShellFallback=ssh-command-fallback-cli",
"gitoxide.http.proxyAuthMethod=proxy-auth-method-cli",
"gitoxide.core.shallowFile=shallow-file-cli",
"gitoxide.core.refsNamespace=namespace-cli",
])
.config_overrides([
"http.userAgent=agent-from-api",
Expand All @@ -74,6 +76,7 @@ mod with_overrides {
"gitoxide.ssh.commandWithoutShellFallback=ssh-command-fallback-api",
"gitoxide.http.proxyAuthMethod=proxy-auth-method-api",
"gitoxide.core.shallowFile=shallow-file-api",
"gitoxide.core.refsNamespace=namespace-api",
]);
opts.permissions.env.git_prefix = Permission::Allow;
opts.permissions.env.http_transport = Permission::Allow;
Expand All @@ -96,6 +99,16 @@ mod with_overrides {
cow_bstr("shallow-file-env")
]
);
assert_eq!(
config
.strings_by_key("gitoxide.core.refsNamespace")
.expect("at least one value"),
[
cow_bstr("namespace-cli"),
cow_bstr("namespace-api"),
cow_bstr("namespace-env")
]
);
assert_eq!(
config.strings_by_key("http.userAgent").expect("at least one value"),
[
Expand Down

0 comments on commit 8434aab

Please sign in to comment.