Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion gix/src/repository/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{bstr::ByteSlice, config};
/// General Configuration
impl crate::Repository {
/// Return a snapshot of the configuration as seen upon opening the repository.
///
/// Use [`reload()`](Self::reload()) to refresh it from disk.
pub fn config_snapshot(&self) -> config::Snapshot<'_> {
config::Snapshot { repo: self }
}
Expand All @@ -13,7 +15,8 @@ impl crate::Repository {
/// When the returned instance is dropped, it is applied in full, even if the reason for the drop is an error.
///
/// Note that changes to the configuration are in-memory only and are observed only this instance
/// of the [`Repository`](crate::Repository).
/// of the [`Repository`](crate::Repository). Use [`reload()`](Self::reload()) to discard them and
/// refresh the snapshot from disk.
pub fn config_snapshot_mut(&mut self) -> config::SnapshotMut<'_> {
let config = self.config.resolved.as_ref().clone();
config::SnapshotMut {
Expand Down
26 changes: 26 additions & 0 deletions gix/src/repository/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ impl crate::Repository {
pub fn into_sync(self) -> crate::ThreadSafeRepository {
self.into()
}

/// Reopen this repository in place using the stored open options.
/// Use this to forcefully refresh Git configuration, drop caches, and release system resources
/// for opened object database resources.
///
/// This discards in-memory-only configuration edits and any other transient repository state that is recreated
/// during opening.
///
/// # Notes on relative paths
///
/// When the [`git_dir`](Self::git_dir()) is relative and the current working dir changed,
/// then a reload will be performed on the joined path of both to make it succeed, which makes
/// the reloaded repository git-dir absolute.
pub fn reload(&mut self) -> Result<&mut Self, crate::open::Error> {
Comment thread
Byron marked this conversation as resolved.
let mut git_dir = self.git_dir().to_owned();
let options = self.options.clone().open_path_as_is(true);
if git_dir.is_relative() {
if let Some((prev_cwd, cwd)) = options.current_dir.as_ref().zip(std::env::current_dir().ok()) {
if *prev_cwd != cwd {
git_dir = prev_cwd.join(git_dir);
}
}
}
*self = crate::ThreadSafeRepository::open_opts(git_dir, options)?.to_thread_local();
Ok(self)
}
}

#[cfg_attr(not(feature = "max-performance-safe"), allow(unused_variables, unused_mut))]
Expand Down
31 changes: 30 additions & 1 deletion gix/tests/gix/repository/config/config_snapshot/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use gix::config::tree::{gitoxide, Branch, Core, Key};

use crate::named_repo;
use crate::{named_repo, repo_rw};

#[cfg(feature = "credentials")]
mod credential_helpers;
Expand Down Expand Up @@ -170,3 +170,32 @@ fn apply_cli_overrides() -> crate::Result {

Ok(())
}

#[test]
fn reload_reloads_on_disk_changes() -> crate::Result {
use std::io::Write;

let (mut repo, _tmp) = repo_rw("make_config_repo.sh")?;
assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);

let config_path = repo.git_dir().join("config");
let mut config = std::fs::OpenOptions::new().append(true).open(config_path)?;
writeln!(config, "\n[core]\n\tabbrev = 4")?;

assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);
repo.reload()?;
assert_eq!(repo.config_snapshot().integer("core.abbrev"), Some(4));
Ok(())
}

#[test]
fn reload_discards_in_memory_only_changes() -> crate::Result {
let mut repo = named_repo("make_config_repo.sh")?;

repo.config_snapshot_mut().set_raw_value(&Core::ABBREV, "4")?;
assert_eq!(repo.config_snapshot().integer("core.abbrev"), Some(4));

repo.reload()?;
assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);
Ok(())
}
Loading