Skip to content

various improvements #1884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 18, 2025
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
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn stream(
let (mut stream, index) = repo.worktree_stream(tree)?;
if !add_paths.is_empty() {
let root = gix::path::realpath(
repo.work_dir()
repo.workdir()
.ok_or_else(|| anyhow!("Adding files requires a worktree directory that contains them"))?,
)?;
for path in add_paths {
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/attributes/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub(crate) mod function {
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
.adjust_for_bare(repo.is_bare()),
)?;
let workdir = repo.work_dir();
let workdir = repo.workdir();
for pattern in pathspec.search().patterns() {
let path = pattern.path();
let entry = cache.at_entry(
Expand Down
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/attributes/validate_baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub(crate) mod function {
};
let work_dir = ignore
.then(|| {
repo.work_dir()
repo.workdir()
.map(ToOwned::to_owned)
.ok_or_else(|| anyhow!("repository at {:?} must have a worktree checkout", repo.path()))
})
Expand Down Expand Up @@ -249,7 +249,7 @@ pub(crate) mod function {
}
bail!(
"{}: Validation failed with {} mismatches out of {}",
gix::path::realpath(repo.work_dir().unwrap_or(repo.git_dir()))?.display(),
gix::path::realpath(repo.workdir().unwrap_or(repo.git_dir()))?.display(),
mismatches.len(),
progress.counter().load(Ordering::Relaxed)
);
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) mod function {
if format != OutputFormat::Human {
bail!("JSON output isn't implemented yet");
}
let Some(workdir) = repo.work_dir() else {
let Some(workdir) = repo.workdir() else {
bail!("Need a worktree to clean, this is a bare repository");
};

Expand Down
6 changes: 3 additions & 3 deletions gitoxide-core/src/repository/exclude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn query(
let mut pathspec = repo.pathspec(
true,
patterns.iter(),
repo.work_dir().is_some(),
repo.workdir().is_some(),
&index,
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping.adjust_for_bare(repo.is_bare()),
)?;
Expand All @@ -82,12 +82,12 @@ pub fn query(
let pathspec = repo.pathspec(
true,
patterns.iter(),
repo.work_dir().is_some(),
repo.workdir().is_some(),
&index,
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
.adjust_for_bare(repo.is_bare()),
)?;
let workdir = repo.work_dir();
let workdir = repo.workdir();
for pattern in pathspec.search().patterns() {
let path = pattern.path();
let entry = cache.at_entry(
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/merge/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn file(
let base_id = repo.rev_parse_single(base.as_bstr()).ok();
let ours_id = repo.rev_parse_single(ours.as_bstr()).ok();
let theirs_id = repo.rev_parse_single(theirs.as_bstr()).ok();
let roots = worktree_roots(base_id, ours_id, theirs_id, repo.work_dir())?;
let roots = worktree_roots(base_id, ours_id, theirs_id, repo.workdir())?;

let mut cache = repo.merge_resource_cache(roots)?;
let null = repo.object_hash().null();
Expand Down
13 changes: 11 additions & 2 deletions gix-fs/src/snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// TODO: tests
use std::ops::Deref;

use gix_features::threading::{get_mut, get_ref, MutableOnDemand, OwnShared};
use std::ops::Deref;

/// A structure holding enough information to reload a value if its on-disk representation changes as determined by its modified time.
#[derive(Debug)]
Expand Down Expand Up @@ -39,6 +38,16 @@ impl<T: Clone + std::fmt::Debug> Clone for FileSnapshot<T> {
}
}

impl<T: Clone + std::fmt::Debug> FileSnapshot<T> {
/// Return the contained instance if nobody else is holding it, or clone it otherwise.
pub fn into_owned_or_cloned(self: OwnShared<Self>) -> T {
match OwnShared::try_unwrap(self) {
Ok(this) => this.value,
Err(this) => this.value.clone(),
}
}
}

/// A snapshot of a resource which is up-to-date in the moment it is retrieved.
pub type SharedFileSnapshot<T> = OwnShared<FileSnapshot<T>>;

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions gix-fs/tests/fs.rs → gix-fs/tests/fs/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error + Send +
mod capabilities;
mod dir;
mod read_dir;
mod snapshot;
mod stack;
File renamed without changes.
54 changes: 54 additions & 0 deletions gix-fs/tests/fs/snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use gix_fs::SharedFileSnapshotMut;
use std::path::Path;

#[test]
fn journey() -> Result<(), Box<dyn std::error::Error>> {
let tmp = tempfile::tempdir().unwrap();
if !has_nanosecond_times(tmp.path())? {
return Ok(());
}

let file_path = tmp.path().join("content");
let smut = SharedFileSnapshotMut::<String>::new();

let check = || file_path.metadata().ok()?.modified().ok();
let open = || {
Ok(match std::fs::read_to_string(&file_path) {
Ok(s) => Some(s),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
Err(err) => return Err(err),
})
};
let snap = smut.recent_snapshot(check, open)?;
assert!(snap.is_none());

std::fs::write(&file_path, "content")?;
let snap = smut.recent_snapshot(check, open)?.expect("content read");
assert_eq!(&**snap, "content", "it read the file for the first time");

std::fs::write(&file_path, "change")?;
let snap = smut.recent_snapshot(check, open)?.expect("content read");
assert_eq!(&**snap, "change", "it picks up the change");

std::fs::remove_file(&file_path)?;
let snap = smut.recent_snapshot(check, open)?;
assert!(snap.is_none(), "file deleted, nothing to see here");

std::fs::write(&file_path, "new")?;
let snap = smut.recent_snapshot(check, open)?.expect("content read again");
let owned: String = snap.into_owned_or_cloned();
assert_eq!(owned, "new", "owned versions are possible easily and efficiently");
Ok(())
}

fn has_nanosecond_times(root: &Path) -> std::io::Result<bool> {
let test_file = root.join("nanosecond-test");

std::fs::write(&test_file, "a")?;
let first_time = test_file.metadata()?.modified()?;

std::fs::write(&test_file, "b")?;
let second_time = test_file.metadata()?.modified()?;

Ok(first_time != second_time)
}
File renamed without changes.
3 changes: 2 additions & 1 deletion gix-status/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ pub use index_as_worktree_with_renames::function::index_as_worktree_with_renames
/// It can efficiently validate paths when these are queried in sort-order, which leads to each component
/// to only be checked once.
pub struct SymlinkCheck {
inner: gix_fs::Stack,
/// Supports querying additional information, like the stack root.
pub inner: gix_fs::Stack,
}

mod stack;
Expand Down
4 changes: 2 additions & 2 deletions gix/examples/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ fn main() -> anyhow::Result<()> {

println!(
"Checking out into {:?} ...",
prepare_checkout.repo().work_dir().expect("should be there")
prepare_checkout.repo().workdir().expect("should be there")
);

let (repo, _) = prepare_checkout.main_worktree(gix::progress::Discard, &gix::interrupt::IS_INTERRUPTED)?;
println!("Repo cloned into {:?}", repo.work_dir().expect("directory pre-created"));
println!("Repo cloned into {:?}", repo.workdir().expect("directory pre-created"));

let remote = repo
.find_default_remote(gix::remote::Direction::Fetch)
Expand Down
2 changes: 1 addition & 1 deletion gix/examples/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use gix::{prelude::ObjectIdExt, Reference};

fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut repo = gix::discover(".")?;
println!("Repo: {}", repo.work_dir().unwrap_or_else(|| repo.git_dir()).display());
println!("Repo: {}", repo.workdir().unwrap_or_else(|| repo.git_dir()).display());
let mut max_parents = 0;
let mut avg_parents = 0;
repo.object_cache_size(32 * 1024);
Expand Down
2 changes: 1 addition & 1 deletion gix/src/clone/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl PrepareFetch {
impl Drop for PrepareFetch {
fn drop(&mut self) {
if let Some(repo) = self.repo.take() {
std::fs::remove_dir_all(repo.work_dir().unwrap_or_else(|| repo.path())).ok();
std::fs::remove_dir_all(repo.workdir().unwrap_or_else(|| repo.path())).ok();
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions gix/src/clone/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub mod main_worktree {
.repo
.as_ref()
.expect("BUG: this method may only be called until it is successful");
let workdir = repo.work_dir().ok_or_else(|| Error::BareRepository {
let workdir = repo.workdir().ok_or_else(|| Error::BareRepository {
git_dir: repo.git_dir().to_owned(),
})?;

Expand All @@ -118,9 +118,7 @@ pub mod main_worktree {
})?;
let mut index = gix_index::File::from_state(index, repo.index_path());

let mut opts = repo
.config
.checkout_options(repo, gix_worktree::stack::state::attributes::Source::IdMapping)?;
let mut opts = repo.checkout_options(gix_worktree::stack::state::attributes::Source::IdMapping)?;
opts.destination_is_initially_empty = true;

let mut files = progress.add_child_with_id("checkout".to_string(), ProgressId::CheckoutFiles.into());
Expand Down Expand Up @@ -173,7 +171,7 @@ impl PrepareCheckout {
impl Drop for PrepareCheckout {
fn drop(&mut self) {
if let Some(repo) = self.repo.take() {
std::fs::remove_dir_all(repo.work_dir().unwrap_or_else(|| repo.path())).ok();
std::fs::remove_dir_all(repo.workdir().unwrap_or_else(|| repo.path())).ok();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion gix/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +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.write_reflog = util::reflog_or_default(self.config.reflog, self.workdir().is_some());
self.refs.namespace.clone_from(&self.config.refs_namespace);
}
}
Expand Down
2 changes: 1 addition & 1 deletion gix/src/dirwalk/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct Outcome {
/// The pathspecs used to guide the operation,
pub pathspec: PathspecDetached,
/// The root actually being used for the traversal, and useful to transform the paths returned for the user.
/// It's always within the [`work-dir`](Repository::work_dir).
/// It's always within the [`work-dir`](Repository::workdir).
pub traversal_root: PathBuf,
/// The actual result of the dirwalk.
pub dirwalk: gix_dir::walk::Outcome,
Expand Down
2 changes: 1 addition & 1 deletion gix/src/dirwalk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub struct Outcome<'repo> {
/// The pathspecs used to guide the operation,
pub pathspec: Pathspec<'repo>,
/// The root actually being used for the traversal, and useful to transform the paths returned for the user.
/// It's always within the [`work-dir`](crate::Repository::work_dir).
/// It's always within the [`work-dir`](crate::Repository::workdir).
pub traversal_root: PathBuf,
/// The actual result of the dirwalk.
pub dirwalk: gix_dir::walk::Outcome,
Expand Down
2 changes: 1 addition & 1 deletion gix/src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl Pipeline<'_> {

let rela_path_as_path = gix_path::from_bstr(rela_path);
let repo = self.repo;
let worktree_dir = repo.work_dir().ok_or(Error::MissingWorktree)?;
let worktree_dir = repo.workdir().ok_or(Error::MissingWorktree)?;
let path = worktree_dir.join(&rela_path_as_path);
let md = match std::fs::symlink_metadata(&path) {
Ok(md) => md,
Expand Down
2 changes: 1 addition & 1 deletion gix/src/pathspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<'repo> Pathspec<'repo> {
patterns,
prefix,
&gix_path::realpath_opts(
repo.work_dir().unwrap_or_else(|| repo.git_dir()),
repo.workdir().unwrap_or_else(|| repo.git_dir()),
repo.options.current_dir_or_empty(),
gix_path::realpath::MAX_SYMLINKS,
)?,
Expand Down
2 changes: 1 addition & 1 deletion gix/src/remote/connection/fetch/update_refs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ fn insert_head(
head: Option<crate::Head<'_>>,
out: &mut BTreeMap<gix_ref::FullName, Vec<PathBuf>>,
) -> Result<(), update::Error> {
if let Some((head, wd)) = head.and_then(|head| head.repo.work_dir().map(|wd| (head, wd))) {
if let Some((head, wd)) = head.and_then(|head| head.repo.workdir().map(|wd| (head, wd))) {
out.entry("HEAD".try_into().expect("valid"))
.or_default()
.push(wd.to_owned());
Expand Down
4 changes: 2 additions & 2 deletions gix/src/remote/connection/fetch/update_refs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ mod update {
(
"+refs/remotes/origin/g:refs/heads/main",
fetch::refs::update::Mode::RejectedCurrentlyCheckedOut {
worktree_dirs: vec![repo.work_dir().expect("present").to_owned()],
worktree_dirs: vec![repo.workdir().expect("present").to_owned()],
},
None,
"checked out branches cannot be written, as it requires a merge of sorts which isn't done here",
Expand Down Expand Up @@ -498,7 +498,7 @@ mod update {
"refs/heads/main",
fetch::refs::Update {
mode: fetch::refs::update::Mode::RejectedCurrentlyCheckedOut {
worktree_dirs: vec![repo.work_dir().expect("present").to_owned()],
worktree_dirs: vec![repo.workdir().expect("present").to_owned()],
},
type_change: None,
edit_index: None,
Expand Down
6 changes: 3 additions & 3 deletions gix/src/repository/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl Repository {
Ok(AttributeStack::new(
gix_worktree::Stack::new(
// this is alright as we don't cause mutation of that directory, it's virtual.
self.work_dir().unwrap_or(self.git_dir()),
self.workdir().unwrap_or(self.git_dir()),
state,
case,
buf,
Expand Down Expand Up @@ -82,7 +82,7 @@ impl Repository {
Ok(AttributeStack::new(
gix_worktree::Stack::new(
// this is alright as we don't cause mutation of that directory, it's virtual.
self.work_dir().unwrap_or(self.git_dir()),
self.workdir().unwrap_or(self.git_dir()),
state,
case,
buf,
Expand Down Expand Up @@ -127,7 +127,7 @@ impl Repository {
Ok(AttributeStack::new(
gix_worktree::Stack::new(
// this is alright as we don't cause mutation of that directory, it's virtual.
self.work_dir().unwrap_or(self.git_dir()),
self.workdir().unwrap_or(self.git_dir()),
state,
case,
buf,
Expand Down
14 changes: 14 additions & 0 deletions gix/src/repository/checkout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::{config, Repository};

impl Repository {
/// Return options that can be used to drive a low-level checkout operation.
/// Use `attributes_source` to determine where `.gitattributes` files should be read from, which depends on
/// the presence of a worktree to begin with.
/// Here, typically this value would be [`gix_worktree::stack::state::attributes::Source::IdMapping`]
pub fn checkout_options(
&self,
attributes_source: gix_worktree::stack::state::attributes::Source,
) -> Result<gix_worktree_state::checkout::Options, config::checkout_options::Error> {
self.config.checkout_options(self, attributes_source)
}
}
2 changes: 1 addition & 1 deletion gix/src/repository/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl crate::Repository {
.into()
},
git_dir: self.git_dir().to_owned().into(),
worktree_dir: self.work_dir().map(ToOwned::to_owned),
worktree_dir: self.workdir().map(ToOwned::to_owned),
no_replace_objects: config::shared::is_replace_refs_enabled(
&self.config.resolved,
self.config.lenient_config,
Expand Down
4 changes: 2 additions & 2 deletions gix/src/repository/dirwalk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Repository {
delegate: &mut dyn gix_dir::walk::Delegate,
) -> Result<dirwalk::Outcome<'_>, dirwalk::Error> {
let _span = gix_trace::coarse!("gix::dirwalk");
let workdir = self.work_dir().ok_or(dirwalk::Error::MissingWorkDir)?;
let workdir = self.workdir().ok_or(dirwalk::Error::MissingWorkDir)?;
let mut excludes = self.excludes(
index,
None,
Expand All @@ -56,7 +56,7 @@ impl Repository {
let accelerate_lookup = fs_caps.ignore_case.then(|| index.prepare_icase_backing());
let mut opts = gix_dir::walk::Options::from(options);
let worktree_relative_worktree_dirs_storage;
if let Some(workdir) = self.work_dir().filter(|_| opts.for_deletion.is_some()) {
if let Some(workdir) = self.workdir().filter(|_| opts.for_deletion.is_some()) {
let linked_worktrees = self.worktrees()?;
if !linked_worktrees.is_empty() {
let real_workdir = gix_path::realpath_opts(
Expand Down
2 changes: 1 addition & 1 deletion gix/src/repository/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl std::fmt::Debug for crate::Repository {
f.debug_struct("Repository")
.field("kind", &self.kind())
.field("git_dir", &self.git_dir())
.field("work_dir", &self.work_dir())
.field("workdir", &self.workdir())
.finish()
}
}
Expand Down
Loading