dirstate-tree: Ignore FIFOs etc. in the status algorithm
authorSimon Sapin <simon.sapin@octobus.net>
Mon, 26 Apr 2021 19:16:23 +0200
changeset 47114 aeb03758f37a
parent 47113 be579775c2d9
child 47115 1b4f0f819f92
dirstate-tree: Ignore FIFOs etc. in the status algorithm If a filesystem directory contains anything that is not: * a "normal" file * a symbolic link * or a directory … act as if that directory entry was not there. For example, if that path was previously a tracked file, mark it as deleted or removed. Differential Revision: https://phab.mercurial-scm.org/D10548
rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs	Fri Apr 16 12:12:41 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/status.rs	Mon Apr 26 19:16:23 2021 +0200
@@ -126,17 +126,21 @@
         dirstate_node: &'tree mut Node,
         has_ignored_ancestor: bool,
     ) {
-        if fs_entry.metadata.is_dir() {
-            if self.options.collect_traversed_dirs {
-                self.outcome.traversed.push(hg_path.into())
-            }
+        let file_type = fs_entry.metadata.file_type();
+        let file_or_symlink = file_type.is_file() || file_type.is_symlink();
+        if !file_or_symlink {
             // If we previously had a file here, it was removed (with
             // `hg rm` or similar) or deleted before it could be
-            // replaced by a directory.
+            // replaced by a directory or something else.
             self.mark_removed_or_deleted_if_file(
                 hg_path,
                 dirstate_node.state(),
             );
+        }
+        if file_type.is_dir() {
+            if self.options.collect_traversed_dirs {
+                self.outcome.traversed.push(hg_path.into())
+            }
             let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path);
             let is_at_repo_root = false;
             self.traverse_fs_directory_and_dirstate(
@@ -147,7 +151,7 @@
                 is_at_repo_root,
             );
         } else {
-            if self.matcher.matches(hg_path) {
+            if file_or_symlink && self.matcher.matches(hg_path) {
                 let full_path = Cow::from(hg_path);
                 if let Some(entry) = &dirstate_node.entry {
                     match entry.state {
@@ -276,7 +280,9 @@
         fs_entry: &DirEntry,
     ) {
         let hg_path = directory_hg_path.join(&fs_entry.base_name);
-        if fs_entry.metadata.is_dir() {
+        let file_type = fs_entry.metadata.file_type();
+        let file_or_symlink = file_type.is_file() || file_type.is_symlink();
+        if file_type.is_dir() {
             let is_ignored =
                 has_ignored_ancestor || (self.ignore_fn)(&hg_path);
             let traverse_children = if is_ignored {
@@ -304,7 +310,7 @@
             if self.options.collect_traversed_dirs {
                 self.outcome.traversed.push(hg_path.into())
             }
-        } else if self.matcher.matches(&hg_path) {
+        } else if file_or_symlink && self.matcher.matches(&hg_path) {
             self.mark_unknown_or_ignored(has_ignored_ancestor, hg_path.into())
         }
     }