Mercurial > hg
changeset 50862:5efccea9cf38
rust-status: explicitly track bad file types
Before this, we silently skipped bad file types.
Now, we check to see if a path is an exact_match in our matcher, and
if so, print an error for it, and only then do we skip it.
A path will be an exact match when it's specified as an explicit
command line argument, and this error-printing behavior is necessary
for compatibility with Python status.
author | Spencer Baugh <sbaugh@janestreet.com> |
---|---|
date | Wed, 02 Aug 2023 10:07:00 -0400 |
parents | 090658724abf |
children | 264072107105 |
files | rust/hg-core/src/dirstate/status.rs rust/hg-core/src/dirstate_tree/status.rs |
diffstat | 2 files changed, 36 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/dirstate/status.rs Mon Aug 14 09:25:36 2023 -0400 +++ b/rust/hg-core/src/dirstate/status.rs Wed Aug 02 10:07:00 2023 -0400 @@ -20,7 +20,7 @@ /// Wrong type of file from a `BadMatch` /// Note: a lot of those don't exist on all platforms. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BadType { CharacterDevice, BlockDevice,
--- a/rust/hg-core/src/dirstate_tree/status.rs Mon Aug 14 09:25:36 2023 -0400 +++ b/rust/hg-core/src/dirstate_tree/status.rs Wed Aug 02 10:07:00 2023 -0400 @@ -14,6 +14,7 @@ use crate::utils::files::get_path_from_bytes; use crate::utils::hg_path::HgPath; use crate::BadMatch; +use crate::BadType; use crate::DirstateStatus; use crate::HgPathCow; use crate::PatternFileWarning; @@ -24,6 +25,7 @@ use sha1::{Digest, Sha1}; use std::borrow::Cow; use std::io; +use std::os::unix::prelude::FileTypeExt; use std::path::Path; use std::path::PathBuf; use std::sync::Mutex; @@ -388,11 +390,7 @@ )); match std::fs::symlink_metadata(&fs_path) { Ok(fs_metadata) => { - let file_type = - match fs_metadata.file_type().try_into() { - Ok(file_type) => file_type, - Err(_) => return Ok(()), - }; + let file_type = fs_metadata.file_type().into(); let entry = DirEntry { hg_path: Cow::Borrowed( dirstate_node @@ -513,6 +511,15 @@ // replaced by a directory or something else. self.mark_removed_or_deleted_if_file(&dirstate_node)?; } + if let Some(bad_type) = fs_entry.is_bad() { + if self.matcher.exact_match(hg_path) { + let path = dirstate_node.full_path(self.dmap.on_disk)?; + self.outcome.lock().unwrap().bad.push(( + path.to_owned().into(), + BadMatch::BadType(bad_type), + )) + } + } if fs_entry.is_dir() { if self.options.collect_traversed_dirs { self.outcome @@ -866,21 +873,27 @@ File, Directory, Symlink, + BadType(BadType), } -impl TryFrom<std::fs::FileType> for FakeFileType { - type Error = (); - - fn try_from(f: std::fs::FileType) -> Result<Self, Self::Error> { +impl From<std::fs::FileType> for FakeFileType { + fn from(f: std::fs::FileType) -> Self { if f.is_dir() { - Ok(Self::Directory) + Self::Directory } else if f.is_file() { - Ok(Self::File) + Self::File } else if f.is_symlink() { - Ok(Self::Symlink) + Self::Symlink + } else if f.is_fifo() { + Self::BadType(BadType::FIFO) + } else if f.is_block_device() { + Self::BadType(BadType::BlockDevice) + } else if f.is_char_device() { + Self::BadType(BadType::CharacterDevice) + } else if f.is_socket() { + Self::BadType(BadType::Socket) } else { - // Things like FIFO etc. - Err(()) + Self::BadType(BadType::Unknown) } } } @@ -942,10 +955,7 @@ }; let filename = Cow::Owned(get_bytes_from_os_string(file_name).into()); - let file_type = match FakeFileType::try_from(file_type) { - Ok(file_type) => file_type, - Err(_) => continue, - }; + let file_type = FakeFileType::from(file_type); results.push(DirEntry { hg_path: filename, fs_path: Cow::Owned(full_path.to_path_buf()), @@ -974,6 +984,13 @@ fn is_symlink(&self) -> bool { self.file_type == FakeFileType::Symlink } + + fn is_bad(&self) -> Option<BadType> { + match self.file_type { + FakeFileType::BadType(ty) => Some(ty), + _ => None, + } + } } /// Return the `mtime` of a temporary file newly-created in the `.hg` directory