Skip to content
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

tree ➡ index diff for status #1344

Merged
merged 5 commits into from
Apr 22, 2024
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
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 `rustls@0.20.9` 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
Loading