diff --git a/gix/src/clone/access.rs b/gix/src/clone/access.rs index 1c817e939ab..966c54b6671 100644 --- a/gix/src/clone/access.rs +++ b/gix/src/clone/access.rs @@ -10,7 +10,7 @@ impl PrepareFetch { /// _all changes done in `f()` will be persisted_. /// /// It can also be used to configure additional options, like those for fetching tags. Note that - /// [`with_fetch_tags()`][crate::Remote::with_fetch_tags()] should be called here to configure the clone as desired. + /// [`with_fetch_tags()`](crate::Remote::with_fetch_tags()) should be called here to configure the clone as desired. /// Otherwise a clone is configured to be complete and fetches all tags, not only those reachable from all branches. pub fn configure_remote( mut self, @@ -21,7 +21,7 @@ impl PrepareFetch { } /// Set the remote's name to the given value after it was configured using the function provided via - /// [`configure_remote()`][Self::configure_remote()]. + /// [`configure_remote()`](Self::configure_remote()). /// /// If not set here, it defaults to `origin` or the value of `clone.defaultRemoteName`. pub fn with_remote_name(mut self, name: impl Into) -> Result { @@ -34,6 +34,14 @@ impl PrepareFetch { self.shallow = shallow; self } + + /// Apply the given configuration `values` right before readying the actual fetch from the remote. + /// The configuration is marked with [source API](gix_config::Source::Api), and will not be written back, it's + /// retained only in memory. + pub fn with_in_memory_config_overrides(mut self, values: impl IntoIterator>) -> Self { + self.config_overrides = values.into_iter().map(Into::into).collect(); + self + } } /// Consumption diff --git a/gix/src/clone/fetch/mod.rs b/gix/src/clone/fetch/mod.rs index 8f05b10e95b..8fdee98edba 100644 --- a/gix/src/clone/fetch/mod.rs +++ b/gix/src/clone/fetch/mod.rs @@ -18,6 +18,10 @@ pub enum Error { RemoteConnection(#[source] Box), #[error(transparent)] RemoteName(#[from] crate::config::remote::symbolic_name::Error), + #[error(transparent)] + ParseConfig(#[from] crate::config::overrides::Error), + #[error(transparent)] + ApplyConfig(#[from] crate::config::Error), #[error("Failed to load repo-local git configuration before writing")] LoadConfig(#[from] gix_config::file::init::from_paths::Error), #[error("Failed to store configured remote in memory")] @@ -75,6 +79,12 @@ impl PrepareFetch { .as_mut() .expect("user error: multiple calls are allowed only until it succeeds"); + if !self.config_overrides.is_empty() { + let mut snapshot = repo.config_snapshot_mut(); + snapshot.append_config(&self.config_overrides, gix_config::Source::Api)?; + snapshot.commit()?; + } + let remote_name = match self.remote_name.as_ref() { Some(name) => name.to_owned(), None => repo diff --git a/gix/src/clone/mod.rs b/gix/src/clone/mod.rs index 8afc3b99b28..9e401386226 100644 --- a/gix/src/clone/mod.rs +++ b/gix/src/clone/mod.rs @@ -20,6 +20,8 @@ pub struct PrepareFetch { repo: Option, /// The name of the remote, which defaults to `origin` if not overridden. remote_name: Option, + /// Additional config `values` that are applied in-memory before starting the fetch process. + config_overrides: Vec, /// A function to configure a remote prior to fetching a pack. configure_remote: Option, /// A function to configure a connection before using it. @@ -126,6 +128,7 @@ impl PrepareFetch { #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))] fetch_options: Default::default(), repo: Some(repo), + config_overrides: Vec::new(), remote_name: None, configure_remote: None, #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))] @@ -144,8 +147,6 @@ pub struct PrepareCheckout { pub(self) repo: Option, } -mod access; - // This module encapsulates functionality that works with both feature toggles. Can be combined with `fetch` // once async and clone are a thing. #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))] @@ -181,6 +182,8 @@ mod access_feat { #[cfg(any(feature = "async-network-client-async-std", feature = "blocking-network-client"))] pub mod fetch; +mod access; + /// #[cfg(feature = "worktree-mutation")] pub mod checkout; diff --git a/gix/tests/clone/mod.rs b/gix/tests/clone/mod.rs index dc742058044..891199c78d2 100644 --- a/gix/tests/clone/mod.rs +++ b/gix/tests/clone/mod.rs @@ -109,6 +109,7 @@ mod blocking_io { fn from_shallow_allowed_by_default() -> crate::Result { let tmp = gix_testtools::tempfile::TempDir::new()?; let (repo, _change) = gix::prepare_clone_bare(remote::repo("base.shallow").path(), tmp.path())? + .with_in_memory_config_overrides(Some("my.marker=1")) .fetch_only(gix::progress::Discard, &std::sync::atomic::AtomicBool::default())?; assert_eq!( repo.shallow_commits()?.expect("present").as_slice(), @@ -118,6 +119,18 @@ mod blocking_io { hex_to_id("dfd0954dabef3b64f458321ef15571cc1a46d552"), ] ); + assert_eq!( + repo.config_snapshot().boolean("my.marker"), + Some(true), + "configuration overrides are set in time" + ); + assert_eq!( + gix::open_opts(repo.git_dir(), gix::open::Options::isolated())? + .config_snapshot() + .boolean("my.marker"), + None, + "these options are not persisted" + ); Ok(()) }