Skip to content

Commit

Permalink
Merge branch 'status'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Apr 22, 2024
2 parents 977346e + 28a7afc commit 68fd5b3
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 50 deletions.
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ yanked = "warn"
# 2019-12-17 there are no security notice advisories in
# https://github.com/rustsec/advisory-db
notice = "warn"
ignore = []
ignore = [
# this is `[email protected]` coming in with `curl`, which doesn't have an update yet. It's only active optionally, not by default.
"RUSTSEC-2024-0336",
]



Expand Down
6 changes: 3 additions & 3 deletions gix-date/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ pub use parse::function::parse;
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Time {
/// time in seconds since epoch.
/// The seconds that passed since UNIX epoch. This makes it UTC, or `<seconds>+0000`.
pub seconds: SecondsSinceUnixEpoch,
/// time offset in seconds, may be negative to match the `sign` field.
/// The time's offset in seconds, which may be negative to match the `sign` field.
pub offset: OffsetInSeconds,
/// the sign of `offset`, used to encode `-0000` which would otherwise loose sign information.
/// the sign of `offset`, used to encode `-0000` which would otherwise lose sign information.
pub sign: time::Sign,
}

Expand Down
18 changes: 4 additions & 14 deletions gix-dir/src/walk/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,7 @@ pub fn root(
let mut path_buf = worktree_root.to_owned();
// These initial values kick in if worktree_relative_root.is_empty();
let file_kind = path_buf.symlink_metadata().map(|m| m.file_type().into()).ok();
let pathspec_orig = std::mem::replace(
ctx.pathspec,
gix_pathspec::Search::from_specs(None, None, "".as_ref()).expect("empty is valid"),
);
let res = path(&mut path_buf, buf, 0, file_kind, || None, options, ctx);
*ctx.pathspec = pathspec_orig;
let mut out = res?;
let mut out = path(&mut path_buf, buf, 0, file_kind, || None, options, ctx)?;
let worktree_root_is_repository = out
.disk_kind
.map_or(false, |kind| matches!(kind, entry::Kind::Repository));
Expand Down Expand Up @@ -59,9 +53,6 @@ pub fn root(
}
last_length = Some(buf.len());
}
if out.pathspec_match.is_none() {
out.pathspec_match = Some(PathspecMatch::Always);
}
Ok((out, worktree_root_is_repository))
}
/// The product of [`path()`] calls.
Expand Down Expand Up @@ -181,10 +172,9 @@ pub fn path(
out.property = entry::Property::DotGit.into();
return Ok(out);
}
let pathspec_could_match = rela_path.is_empty()
|| ctx
.pathspec
.can_match_relative_path(rela_path.as_bstr(), disk_kind.map(|ft| ft.is_dir()));
let pathspec_could_match = ctx
.pathspec
.can_match_relative_path(rela_path.as_bstr(), disk_kind.map(|ft| ft.is_dir()));
if !pathspec_could_match {
return Ok(out.with_status(entry::Status::Pruned));
}
Expand Down
22 changes: 13 additions & 9 deletions gix-dir/tests/walk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2732,7 +2732,7 @@ fn worktree_root_can_be_symlink() -> crate::Result {
#[test]
fn root_may_not_go_through_dot_git() -> crate::Result {
let root = fixture("with-nested-dot-git");
for (dir, expected_pathspec) in [("", Verbatim), ("subdir", Always)] {
for (dir, expected_pathspec) in [("", Some(Verbatim)), ("subdir", None)] {
let troot = root.join("dir").join(".git").join(dir);
let ((out, _root), entries) = collect(&root, Some(&troot), |keep, ctx| {
walk(&root, ctx, options_emit_all(), keep)
Expand All @@ -2747,9 +2747,11 @@ fn root_may_not_go_through_dot_git() -> crate::Result {
);
assert_eq!(
entries,
[entry("dir/.git", Pruned, Directory)
.with_property(DotGit)
.with_match(expected_pathspec)],
[{
let mut e = entry("dir/.git", Pruned, Directory).with_property(DotGit);
e.0.pathspec_match = expected_pathspec;
e
}],
"{dir}: no traversal happened as root passes though .git"
);
}
Expand Down Expand Up @@ -3165,7 +3167,7 @@ fn root_can_be_pruned_early_with_pathspec() -> crate::Result {

assert_eq!(
entries,
[entry("dir", Pruned, Directory)],
[entry_nomatch("dir", Pruned, Directory)],
"the pathspec didn't match the root, early abort"
);
Ok(())
Expand Down Expand Up @@ -3927,7 +3929,7 @@ fn untracked_and_ignored_collapse_mix() {
#[test]
fn root_cannot_pass_through_case_altered_capital_dot_git_if_case_insensitive() -> crate::Result {
let root = fixture("with-nested-capitalized-dot-git");
for (dir, expected_pathspec) in [("", Verbatim), ("subdir", Always)] {
for (dir, expected_pathspec) in [("", Some(Verbatim)), ("subdir", None)] {
let troot = root.join("dir").join(".GIT").join(dir);
let ((out, _root), entries) = collect(&root, Some(&troot), |keep, ctx| {
walk(
Expand All @@ -3950,9 +3952,11 @@ fn root_cannot_pass_through_case_altered_capital_dot_git_if_case_insensitive() -
);
assert_eq!(
entries,
[entry("dir/.GIT", Pruned, Directory)
.with_property(DotGit)
.with_match(expected_pathspec)],
[{
let mut e = entry("dir/.GIT", Pruned, Directory).with_property(DotGit);
e.0.pathspec_match = expected_pathspec;
e
}],
"{dir}: no traversal happened as root passes though .git, it compares in a case-insensitive fashion"
);
}
Expand Down
27 changes: 17 additions & 10 deletions gix-pathspec/src/search/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ impl Search {
is_dir: Option<bool>,
attributes: &mut dyn FnMut(&BStr, Case, bool, &mut gix_attributes::search::Outcome) -> bool,
) -> Option<Match<'_>> {
static MATCH_ALL_STAND_IN: Pattern = Pattern {
path: BString::new(Vec::new()),
signature: MagicSignature::empty(),
search_mode: SearchMode::ShellGlob,
attributes: Vec::new(),
prefix_len: 0,
nil: true,
};
if relative_path.is_empty() {
return Some(Match {
pattern: &MATCH_ALL_STAND_IN,
sequence_number: 0,
kind: Always,
});
}
let basename_not_important = None;
if relative_path
.get(..self.common_prefix_len)
Expand Down Expand Up @@ -106,14 +121,6 @@ impl Search {
});

if res.is_none() && self.all_patterns_are_excluded {
static MATCH_ALL_STAND_IN: Pattern = Pattern {
path: BString::new(Vec::new()),
signature: MagicSignature::empty(),
search_mode: SearchMode::ShellGlob,
attributes: Vec::new(),
prefix_len: 0,
nil: true,
};
Some(Match {
pattern: &MATCH_ALL_STAND_IN,
sequence_number: patterns_len,
Expand All @@ -133,7 +140,7 @@ impl Search {
/// is ignored.
/// Returns `false` if this pathspec has no chance of ever matching `relative_path`.
pub fn can_match_relative_path(&self, relative_path: &BStr, is_dir: Option<bool>) -> bool {
if self.patterns.is_empty() {
if self.patterns.is_empty() || relative_path.is_empty() {
return true;
}
let common_prefix_len = self.common_prefix_len.min(relative_path.len());
Expand Down Expand Up @@ -194,7 +201,7 @@ impl Search {
/// When `leading` is `true`, then `d` matches `d/d` as well. Thus, `relative_path` must may be
/// partially included in `pathspec`, otherwise it has to be fully included.
pub fn directory_matches_prefix(&self, relative_path: &BStr, leading: bool) -> bool {
if self.patterns.is_empty() {
if self.patterns.is_empty() || relative_path.is_empty() {
return true;
}
let common_prefix_len = self.common_prefix_len.min(relative_path.len());
Expand Down
25 changes: 25 additions & 0 deletions gix-pathspec/tests/search/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,31 @@ fn directory_matches_prefix_starting_wildcards_always_match() -> crate::Result {
Ok(())
}

#[test]
fn empty_dir_always_matches() -> crate::Result {
for specs in [
&["*ir"] as &[_],
&[],
&["included", ":!excluded"],
&[":!all", ":!excluded"],
] {
let mut search = gix_pathspec::Search::from_specs(pathspecs(specs), None, Path::new(""))?;
assert_eq!(
search
.pattern_matching_relative_path("".into(), None, &mut no_attrs)
.map(|m| m.kind),
Some(Always),
"{specs:?}"
);
assert!(search.directory_matches_prefix("".into(), false));
assert!(search.directory_matches_prefix("".into(), false));
for is_dir in [Some(true), Some(false), None] {
assert!(search.can_match_relative_path("".into(), is_dir));
}
}
Ok(())
}

#[test]
fn directory_matches_prefix_leading() -> crate::Result {
let search = gix_pathspec::Search::from_specs(pathspecs(&["d/d/generated/b"]), None, Path::new(""))?;
Expand Down
9 changes: 8 additions & 1 deletion gix-ref/src/store/file/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,14 @@ pub(crate) mod modifiable {
pub(crate) type MutableSharedBuffer = OwnShared<gix_fs::SharedFileSnapshotMut<packed::Buffer>>;

impl file::Store {
pub(crate) fn force_refresh_packed_buffer(&self) -> Result<(), packed::buffer::open::Error> {
/// Forcefully reload the packed refs buffer.
///
/// This method should be used if it's clear that the buffer on disk has changed, to
/// make the latest changes visible before other operations are done on this instance.
///
/// As some filesystems don't have nanosecond granularity, changes are likely to be missed
/// if they happen within one second otherwise.
pub fn force_refresh_packed_buffer(&self) -> Result<(), packed::buffer::open::Error> {
self.packed.force_refresh(|| {
let modified = self.packed_refs_path().metadata()?.modified()?;
self.open_packed_buffer().map(|packed| Some(modified).zip(packed))
Expand Down

0 comments on commit 68fd5b3

Please sign in to comment.