summaryrefslogtreecommitdiffstats
path: root/vendor/ignore/src/pathutil.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/ignore/src/pathutil.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ignore/src/pathutil.rs')
-rw-r--r--vendor/ignore/src/pathutil.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/vendor/ignore/src/pathutil.rs b/vendor/ignore/src/pathutil.rs
new file mode 100644
index 000000000..f21b4f5ab
--- /dev/null
+++ b/vendor/ignore/src/pathutil.rs
@@ -0,0 +1,142 @@
+use std::ffi::OsStr;
+use std::path::Path;
+
+use crate::walk::DirEntry;
+
+/// Returns true if and only if this entry is considered to be hidden.
+///
+/// This only returns true if the base name of the path starts with a `.`.
+///
+/// On Unix, this implements a more optimized check.
+#[cfg(unix)]
+pub fn is_hidden(dent: &DirEntry) -> bool {
+ use std::os::unix::ffi::OsStrExt;
+
+ if let Some(name) = file_name(dent.path()) {
+ name.as_bytes().get(0) == Some(&b'.')
+ } else {
+ false
+ }
+}
+
+/// Returns true if and only if this entry is considered to be hidden.
+///
+/// On Windows, this returns true if one of the following is true:
+///
+/// * The base name of the path starts with a `.`.
+/// * The file attributes have the `HIDDEN` property set.
+#[cfg(windows)]
+pub fn is_hidden(dent: &DirEntry) -> bool {
+ use std::os::windows::fs::MetadataExt;
+ use winapi_util::file;
+
+ // This looks like we're doing an extra stat call, but on Windows, the
+ // directory traverser reuses the metadata retrieved from each directory
+ // entry and stores it on the DirEntry itself. So this is "free."
+ if let Ok(md) = dent.metadata() {
+ if file::is_hidden(md.file_attributes() as u64) {
+ return true;
+ }
+ }
+ if let Some(name) = file_name(dent.path()) {
+ name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
+ } else {
+ false
+ }
+}
+
+/// Returns true if and only if this entry is considered to be hidden.
+///
+/// This only returns true if the base name of the path starts with a `.`.
+#[cfg(not(any(unix, windows)))]
+pub fn is_hidden(dent: &DirEntry) -> bool {
+ if let Some(name) = file_name(dent.path()) {
+ name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
+ } else {
+ false
+ }
+}
+
+/// Strip `prefix` from the `path` and return the remainder.
+///
+/// If `path` doesn't have a prefix `prefix`, then return `None`.
+#[cfg(unix)]
+pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
+ prefix: &'a P,
+ path: &'a Path,
+) -> Option<&'a Path> {
+ use std::os::unix::ffi::OsStrExt;
+
+ let prefix = prefix.as_ref().as_os_str().as_bytes();
+ let path = path.as_os_str().as_bytes();
+ if prefix.len() > path.len() || prefix != &path[0..prefix.len()] {
+ None
+ } else {
+ Some(&Path::new(OsStr::from_bytes(&path[prefix.len()..])))
+ }
+}
+
+/// Strip `prefix` from the `path` and return the remainder.
+///
+/// If `path` doesn't have a prefix `prefix`, then return `None`.
+#[cfg(not(unix))]
+pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
+ prefix: &'a P,
+ path: &'a Path,
+) -> Option<&'a Path> {
+ path.strip_prefix(prefix).ok()
+}
+
+/// Returns true if this file path is just a file name. i.e., Its parent is
+/// the empty string.
+#[cfg(unix)]
+pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
+ use memchr::memchr;
+ use std::os::unix::ffi::OsStrExt;
+
+ let path = path.as_ref().as_os_str().as_bytes();
+ memchr(b'/', path).is_none()
+}
+
+/// Returns true if this file path is just a file name. i.e., Its parent is
+/// the empty string.
+#[cfg(not(unix))]
+pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
+ path.as_ref().parent().map(|p| p.as_os_str().is_empty()).unwrap_or(false)
+}
+
+/// The final component of the path, if it is a normal file.
+///
+/// If the path terminates in ., .., or consists solely of a root of prefix,
+/// file_name will return None.
+#[cfg(unix)]
+pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
+ path: &'a P,
+) -> Option<&'a OsStr> {
+ use memchr::memrchr;
+ use std::os::unix::ffi::OsStrExt;
+
+ let path = path.as_ref().as_os_str().as_bytes();
+ if path.is_empty() {
+ return None;
+ } else if path.len() == 1 && path[0] == b'.' {
+ return None;
+ } else if path.last() == Some(&b'.') {
+ return None;
+ } else if path.len() >= 2 && &path[path.len() - 2..] == &b".."[..] {
+ return None;
+ }
+ let last_slash = memrchr(b'/', path).map(|i| i + 1).unwrap_or(0);
+ Some(OsStr::from_bytes(&path[last_slash..]))
+}
+
+/// The final component of the path, if it is a normal file.
+///
+/// If the path terminates in ., .., or consists solely of a root of prefix,
+/// file_name will return None.
+#[cfg(not(unix))]
+pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
+ path: &'a P,
+) -> Option<&'a OsStr> {
+ path.as_ref().file_name()
+}