Skip to content

Commit 26d5197

Browse files
authored
Merge pull request GitoxideLabs#2469 from GitoxideLabs/improvements
feat: add `Repository::reopen()` as quick way to reload all configuration and drop caches.
2 parents ab36136 + f15911c commit 26d5197

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

gix/src/repository/config/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use crate::{bstr::ByteSlice, config};
55
/// General Configuration
66
impl crate::Repository {
77
/// Return a snapshot of the configuration as seen upon opening the repository.
8+
///
9+
/// Use [`reload()`](Self::reload()) to refresh it from disk.
810
pub fn config_snapshot(&self) -> config::Snapshot<'_> {
911
config::Snapshot { repo: self }
1012
}
@@ -13,7 +15,8 @@ impl crate::Repository {
1315
/// When the returned instance is dropped, it is applied in full, even if the reason for the drop is an error.
1416
///
1517
/// Note that changes to the configuration are in-memory only and are observed only this instance
16-
/// of the [`Repository`](crate::Repository).
18+
/// of the [`Repository`](crate::Repository). Use [`reload()`](Self::reload()) to discard them and
19+
/// refresh the snapshot from disk.
1720
pub fn config_snapshot_mut(&mut self) -> config::SnapshotMut<'_> {
1821
let config = self.config.resolved.as_ref().clone();
1922
config::SnapshotMut {

gix/src/repository/init.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,32 @@ impl crate::Repository {
3434
pub fn into_sync(self) -> crate::ThreadSafeRepository {
3535
self.into()
3636
}
37+
38+
/// Reopen this repository in place using the stored open options.
39+
/// Use this to forcefully refresh Git configuration, drop caches, and release system resources
40+
/// for opened object database resources.
41+
///
42+
/// This discards in-memory-only configuration edits and any other transient repository state that is recreated
43+
/// during opening.
44+
///
45+
/// # Notes on relative paths
46+
///
47+
/// When the [`git_dir`](Self::git_dir()) is relative and the current working dir changed,
48+
/// then a reload will be performed on the joined path of both to make it succeed, which makes
49+
/// the reloaded repository git-dir absolute.
50+
pub fn reload(&mut self) -> Result<&mut Self, crate::open::Error> {
51+
let mut git_dir = self.git_dir().to_owned();
52+
let options = self.options.clone().open_path_as_is(true);
53+
if git_dir.is_relative() {
54+
if let Some((prev_cwd, cwd)) = options.current_dir.as_ref().zip(std::env::current_dir().ok()) {
55+
if *prev_cwd != cwd {
56+
git_dir = prev_cwd.join(git_dir);
57+
}
58+
}
59+
}
60+
*self = crate::ThreadSafeRepository::open_opts(git_dir, options)?.to_thread_local();
61+
Ok(self)
62+
}
3763
}
3864

3965
#[cfg_attr(not(feature = "max-performance-safe"), allow(unused_variables, unused_mut))]

gix/tests/gix/repository/config/config_snapshot/mod.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use gix::config::tree::{gitoxide, Branch, Core, Key};
22

3-
use crate::named_repo;
3+
use crate::{named_repo, repo_rw};
44

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

171171
Ok(())
172172
}
173+
174+
#[test]
175+
fn reload_reloads_on_disk_changes() -> crate::Result {
176+
use std::io::Write;
177+
178+
let (mut repo, _tmp) = repo_rw("make_config_repo.sh")?;
179+
assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);
180+
181+
let config_path = repo.git_dir().join("config");
182+
let mut config = std::fs::OpenOptions::new().append(true).open(config_path)?;
183+
writeln!(config, "\n[core]\n\tabbrev = 4")?;
184+
185+
assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);
186+
repo.reload()?;
187+
assert_eq!(repo.config_snapshot().integer("core.abbrev"), Some(4));
188+
Ok(())
189+
}
190+
191+
#[test]
192+
fn reload_discards_in_memory_only_changes() -> crate::Result {
193+
let mut repo = named_repo("make_config_repo.sh")?;
194+
195+
repo.config_snapshot_mut().set_raw_value(&Core::ABBREV, "4")?;
196+
assert_eq!(repo.config_snapshot().integer("core.abbrev"), Some(4));
197+
198+
repo.reload()?;
199+
assert_eq!(repo.config_snapshot().integer("core.abbrev"), None);
200+
Ok(())
201+
}

0 commit comments

Comments
 (0)