Skip to content

Commit e6ed377

Browse files
committed
fix!: consider non-files as pruned officially.
Previously, these were silently ignored. This also brings back `entry::Kind::from(std::fs::FileType)`.
1 parent 69ee6a3 commit e6ed377

File tree

4 files changed

+24
-21
lines changed

4 files changed

+24
-21
lines changed

gix-dir/src/entry.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::walk::ForDeletionMode;
22
use crate::{Entry, EntryRef};
33
use std::borrow::Cow;
4+
use std::fs::FileType;
45

56
/// A way of attaching additional information to an [Entry] .
67
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
@@ -25,6 +26,10 @@ pub enum Property {
2526
/// The kind of the entry, seated in their kinds available on disk.
2627
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
2728
pub enum Kind {
29+
/// Something that is not a file, like a named pipe or character device.
30+
///
31+
/// These can only exist in the filesystem.
32+
NonFile,
2833
/// The entry is a blob, executable or not.
2934
File,
3035
/// The entry is a symlink.
@@ -147,20 +152,17 @@ impl Entry {
147152
}
148153
}
149154

150-
impl Kind {
151-
/// Try to represent the file type `t` as `Entry`, or return `None` if it cannot be represented.
152-
///
153-
/// The latter can happen if it's a `pipe` for instance.
154-
pub fn try_from_file_type(t: std::fs::FileType) -> Option<Self> {
155-
Some(if t.is_dir() {
155+
impl From<std::fs::FileType> for Kind {
156+
fn from(value: FileType) -> Self {
157+
if value.is_dir() {
156158
Kind::Directory
157-
} else if t.is_symlink() {
159+
} else if value.is_symlink() {
158160
Kind::Symlink
159-
} else if t.is_file() {
161+
} else if value.is_file() {
160162
Kind::File
161163
} else {
162-
return None;
163-
})
164+
Kind::NonFile
165+
}
164166
}
165167
}
166168

gix-dir/src/walk/classify.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ pub fn root(
2020
let mut last_length = None;
2121
let mut path_buf = worktree_root.to_owned();
2222
// These initial values kick in if worktree_relative_root.is_empty();
23-
let file_kind = path_buf
24-
.symlink_metadata()
25-
.ok()
26-
.and_then(|m| entry::Kind::try_from_file_type(m.file_type()));
23+
let file_kind = path_buf.symlink_metadata().ok().map(|m| m.file_type().into());
2724
let mut out = path(&mut path_buf, buf, 0, file_kind, || None, options, ctx)?;
2825
let worktree_root_is_repository = out
2926
.disk_kind
@@ -35,10 +32,7 @@ pub fn root(
3532
}
3633
path_buf.push(component);
3734
buf.extend_from_slice(gix_path::os_str_into_bstr(component.as_os_str()).expect("no illformed UTF8"));
38-
let file_kind = path_buf
39-
.symlink_metadata()
40-
.ok()
41-
.and_then(|m| entry::Kind::try_from_file_type(m.file_type()));
35+
let file_kind = path_buf.symlink_metadata().ok().map(|m| m.file_type().into());
4236

4337
out = path(
4438
&mut path_buf,
@@ -200,6 +194,12 @@ pub fn path(
200194
);
201195
let mut kind = uptodate_index_kind.or(disk_kind).or_else(on_demand_disk_kind);
202196

197+
// Detect non-files as early as possible and pre-mark them as pruned.
198+
if kind == Some(entry::Kind::NonFile) {
199+
out.disk_kind = kind;
200+
return Ok(out.with_status(entry::Status::Pruned));
201+
}
202+
203203
// We always check the pathspec to have the value filled in reliably.
204204
out.pathspec_match = ctx
205205
.pathspec

gix-dir/src/walk/readdir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub(super) fn recursive(
6464
current_bstr,
6565
if prev_len == 0 { 0 } else { prev_len + 1 },
6666
None,
67-
|| entry.file_type().ok().and_then(entry::Kind::try_from_file_type),
67+
|| entry.file_type().ok().map(Into::into),
6868
opts,
6969
ctx,
7070
)?;

gix-dir/tests/dir/walk.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ fn fifo_in_traversal() {
9999
&[
100100
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
101101
entry("dir-with-file/nested-file", Untracked, File),
102+
entry_nomatch("dir/nested", Pruned, NonFile),
102103
entry("file", Untracked, File),
104+
entry_nomatch("top", Pruned, NonFile),
103105
],
104-
"Non-files are not even pruned, they are ignored entirely.\
105-
If one day this isn't what we want, we can create an own filetype for them"
106+
"Non-files are officially pruned, and also have a file-type attached"
106107
);
107108
}
108109

0 commit comments

Comments
 (0)