Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

352
vendor/walkdir/src/dent.rs vendored Normal file
View File

@@ -0,0 +1,352 @@
use std::ffi::OsStr;
use std::fmt;
use std::fs::{self, FileType};
use std::path::{Path, PathBuf};
use crate::error::Error;
use crate::Result;
/// A directory entry.
///
/// This is the type of value that is yielded from the iterators defined in
/// this crate.
///
/// On Unix systems, this type implements the [`DirEntryExt`] trait, which
/// provides efficient access to the inode number of the directory entry.
///
/// # Differences with `std::fs::DirEntry`
///
/// This type mostly mirrors the type by the same name in [`std::fs`]. There
/// are some differences however:
///
/// * All recursive directory iterators must inspect the entry's type.
/// Therefore, the value is stored and its access is guaranteed to be cheap and
/// successful.
/// * [`path`] and [`file_name`] return borrowed variants.
/// * If [`follow_links`] was enabled on the originating iterator, then all
/// operations except for [`path`] operate on the link target. Otherwise, all
/// operations operate on the symbolic link.
///
/// [`std::fs`]: https://doc.rust-lang.org/stable/std/fs/index.html
/// [`path`]: #method.path
/// [`file_name`]: #method.file_name
/// [`follow_links`]: struct.WalkDir.html#method.follow_links
/// [`DirEntryExt`]: trait.DirEntryExt.html
pub struct DirEntry {
/// The path as reported by the [`fs::ReadDir`] iterator (even if it's a
/// symbolic link).
///
/// [`fs::ReadDir`]: https://doc.rust-lang.org/stable/std/fs/struct.ReadDir.html
path: PathBuf,
/// The file type. Necessary for recursive iteration, so store it.
ty: FileType,
/// Is set when this entry was created from a symbolic link and the user
/// expects the iterator to follow symbolic links.
follow_link: bool,
/// The depth at which this entry was generated relative to the root.
depth: usize,
/// The underlying inode number (Unix only).
#[cfg(unix)]
ino: u64,
/// The underlying metadata (Windows only). We store this on Windows
/// because this comes for free while reading a directory.
///
/// We use this to determine whether an entry is a directory or not, which
/// works around a bug in Rust's standard library:
/// https://github.com/rust-lang/rust/issues/46484
#[cfg(windows)]
metadata: fs::Metadata,
}
impl DirEntry {
/// The full path that this entry represents.
///
/// The full path is created by joining the parents of this entry up to the
/// root initially given to [`WalkDir::new`] with the file name of this
/// entry.
///
/// Note that this *always* returns the path reported by the underlying
/// directory entry, even when symbolic links are followed. To get the
/// target path, use [`path_is_symlink`] to (cheaply) check if this entry
/// corresponds to a symbolic link, and [`std::fs::read_link`] to resolve
/// the target.
///
/// [`WalkDir::new`]: struct.WalkDir.html#method.new
/// [`path_is_symlink`]: struct.DirEntry.html#method.path_is_symlink
/// [`std::fs::read_link`]: https://doc.rust-lang.org/stable/std/fs/fn.read_link.html
pub fn path(&self) -> &Path {
&self.path
}
/// The full path that this entry represents.
///
/// Analogous to [`path`], but moves ownership of the path.
///
/// [`path`]: struct.DirEntry.html#method.path
pub fn into_path(self) -> PathBuf {
self.path
}
/// Returns `true` if and only if this entry was created from a symbolic
/// link. This is unaffected by the [`follow_links`] setting.
///
/// When `true`, the value returned by the [`path`] method is a
/// symbolic link name. To get the full target path, you must call
/// [`std::fs::read_link(entry.path())`].
///
/// [`path`]: struct.DirEntry.html#method.path
/// [`follow_links`]: struct.WalkDir.html#method.follow_links
/// [`std::fs::read_link(entry.path())`]: https://doc.rust-lang.org/stable/std/fs/fn.read_link.html
pub fn path_is_symlink(&self) -> bool {
self.ty.is_symlink() || self.follow_link
}
/// Return the metadata for the file that this entry points to.
///
/// This will follow symbolic links if and only if the [`WalkDir`] value
/// has [`follow_links`] enabled.
///
/// # Platform behavior
///
/// This always calls [`std::fs::symlink_metadata`].
///
/// If this entry is a symbolic link and [`follow_links`] is enabled, then
/// [`std::fs::metadata`] is called instead.
///
/// # Errors
///
/// Similar to [`std::fs::metadata`], returns errors for path values that
/// the program does not have permissions to access or if the path does not
/// exist.
///
/// [`WalkDir`]: struct.WalkDir.html
/// [`follow_links`]: struct.WalkDir.html#method.follow_links
/// [`std::fs::metadata`]: https://doc.rust-lang.org/std/fs/fn.metadata.html
/// [`std::fs::symlink_metadata`]: https://doc.rust-lang.org/stable/std/fs/fn.symlink_metadata.html
pub fn metadata(&self) -> Result<fs::Metadata> {
self.metadata_internal()
}
#[cfg(windows)]
fn metadata_internal(&self) -> Result<fs::Metadata> {
if self.follow_link {
fs::metadata(&self.path)
} else {
Ok(self.metadata.clone())
}
.map_err(|err| Error::from_entry(self, err))
}
#[cfg(not(windows))]
fn metadata_internal(&self) -> Result<fs::Metadata> {
if self.follow_link {
fs::metadata(&self.path)
} else {
fs::symlink_metadata(&self.path)
}
.map_err(|err| Error::from_entry(self, err))
}
/// Return the file type for the file that this entry points to.
///
/// If this is a symbolic link and [`follow_links`] is `true`, then this
/// returns the type of the target.
///
/// This never makes any system calls.
///
/// [`follow_links`]: struct.WalkDir.html#method.follow_links
pub fn file_type(&self) -> fs::FileType {
self.ty
}
/// Return the file name of this entry.
///
/// If this entry has no file name (e.g., `/`), then the full path is
/// returned.
pub fn file_name(&self) -> &OsStr {
self.path.file_name().unwrap_or_else(|| self.path.as_os_str())
}
/// Returns the depth at which this entry was created relative to the root.
///
/// The smallest depth is `0` and always corresponds to the path given
/// to the `new` function on `WalkDir`. Its direct descendents have depth
/// `1`, and their descendents have depth `2`, and so on.
pub fn depth(&self) -> usize {
self.depth
}
/// Returns true if and only if this entry points to a directory.
pub(crate) fn is_dir(&self) -> bool {
self.ty.is_dir()
}
#[cfg(windows)]
pub(crate) fn from_entry(
depth: usize,
ent: &fs::DirEntry,
) -> Result<DirEntry> {
let path = ent.path();
let ty = ent
.file_type()
.map_err(|err| Error::from_path(depth, path.clone(), err))?;
let md = ent
.metadata()
.map_err(|err| Error::from_path(depth, path.clone(), err))?;
Ok(DirEntry { path, ty, follow_link: false, depth, metadata: md })
}
#[cfg(unix)]
pub(crate) fn from_entry(
depth: usize,
ent: &fs::DirEntry,
) -> Result<DirEntry> {
use std::os::unix::fs::DirEntryExt;
let ty = ent
.file_type()
.map_err(|err| Error::from_path(depth, ent.path(), err))?;
Ok(DirEntry {
path: ent.path(),
ty,
follow_link: false,
depth,
ino: ent.ino(),
})
}
#[cfg(not(any(unix, windows)))]
pub(crate) fn from_entry(
depth: usize,
ent: &fs::DirEntry,
) -> Result<DirEntry> {
let ty = ent
.file_type()
.map_err(|err| Error::from_path(depth, ent.path(), err))?;
Ok(DirEntry { path: ent.path(), ty, follow_link: false, depth })
}
#[cfg(windows)]
pub(crate) fn from_path(
depth: usize,
pb: PathBuf,
follow: bool,
) -> Result<DirEntry> {
let md = if follow {
fs::metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
} else {
fs::symlink_metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
};
Ok(DirEntry {
path: pb,
ty: md.file_type(),
follow_link: follow,
depth,
metadata: md,
})
}
#[cfg(unix)]
pub(crate) fn from_path(
depth: usize,
pb: PathBuf,
follow: bool,
) -> Result<DirEntry> {
use std::os::unix::fs::MetadataExt;
let md = if follow {
fs::metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
} else {
fs::symlink_metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
};
Ok(DirEntry {
path: pb,
ty: md.file_type(),
follow_link: follow,
depth,
ino: md.ino(),
})
}
#[cfg(not(any(unix, windows)))]
pub(crate) fn from_path(
depth: usize,
pb: PathBuf,
follow: bool,
) -> Result<DirEntry> {
let md = if follow {
fs::metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
} else {
fs::symlink_metadata(&pb)
.map_err(|err| Error::from_path(depth, pb.clone(), err))?
};
Ok(DirEntry {
path: pb,
ty: md.file_type(),
follow_link: follow,
depth,
})
}
}
impl Clone for DirEntry {
#[cfg(windows)]
fn clone(&self) -> DirEntry {
DirEntry {
path: self.path.clone(),
ty: self.ty,
follow_link: self.follow_link,
depth: self.depth,
metadata: self.metadata.clone(),
}
}
#[cfg(unix)]
fn clone(&self) -> DirEntry {
DirEntry {
path: self.path.clone(),
ty: self.ty,
follow_link: self.follow_link,
depth: self.depth,
ino: self.ino,
}
}
#[cfg(not(any(unix, windows)))]
fn clone(&self) -> DirEntry {
DirEntry {
path: self.path.clone(),
ty: self.ty,
follow_link: self.follow_link,
depth: self.depth,
}
}
}
impl fmt::Debug for DirEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "DirEntry({:?})", self.path)
}
}
/// Unix-specific extension methods for `walkdir::DirEntry`
#[cfg(unix)]
pub trait DirEntryExt {
/// Returns the underlying `d_ino` field in the contained `dirent`
/// structure.
fn ino(&self) -> u64;
}
#[cfg(unix)]
impl DirEntryExt for DirEntry {
/// Returns the underlying `d_ino` field in the contained `dirent`
/// structure.
fn ino(&self) -> u64 {
self.ino
}
}

262
vendor/walkdir/src/error.rs vendored Normal file
View File

@@ -0,0 +1,262 @@
use std::error;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use crate::DirEntry;
/// An error produced by recursively walking a directory.
///
/// This error type is a light wrapper around [`std::io::Error`]. In
/// particular, it adds the following information:
///
/// * The depth at which the error occurred in the file tree, relative to the
/// root.
/// * The path, if any, associated with the IO error.
/// * An indication that a loop occurred when following symbolic links. In this
/// case, there is no underlying IO error.
///
/// To maintain good ergonomics, this type has a
/// [`impl From<Error> for std::io::Error`][impl] defined which preserves the original context.
/// This allows you to use an [`io::Result`] with methods in this crate if you don't care about
/// accessing the underlying error data in a structured form.
///
/// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
/// [`io::Result`]: https://doc.rust-lang.org/stable/std/io/type.Result.html
/// [impl]: struct.Error.html#impl-From%3CError%3E
#[derive(Debug)]
pub struct Error {
depth: usize,
inner: ErrorInner,
}
#[derive(Debug)]
enum ErrorInner {
Io { path: Option<PathBuf>, err: io::Error },
Loop { ancestor: PathBuf, child: PathBuf },
}
impl Error {
/// Returns the path associated with this error if one exists.
///
/// For example, if an error occurred while opening a directory handle,
/// the error will include the path passed to [`std::fs::read_dir`].
///
/// [`std::fs::read_dir`]: https://doc.rust-lang.org/stable/std/fs/fn.read_dir.html
pub fn path(&self) -> Option<&Path> {
match self.inner {
ErrorInner::Io { path: None, .. } => None,
ErrorInner::Io { path: Some(ref path), .. } => Some(path),
ErrorInner::Loop { ref child, .. } => Some(child),
}
}
/// Returns the path at which a cycle was detected.
///
/// If no cycle was detected, [`None`] is returned.
///
/// A cycle is detected when a directory entry is equivalent to one of
/// its ancestors.
///
/// To get the path to the child directory entry in the cycle, use the
/// [`path`] method.
///
/// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None
/// [`path`]: struct.Error.html#path
pub fn loop_ancestor(&self) -> Option<&Path> {
match self.inner {
ErrorInner::Loop { ref ancestor, .. } => Some(ancestor),
_ => None,
}
}
/// Returns the depth at which this error occurred relative to the root.
///
/// The smallest depth is `0` and always corresponds to the path given to
/// the [`new`] function on [`WalkDir`]. Its direct descendents have depth
/// `1`, and their descendents have depth `2`, and so on.
///
/// [`new`]: struct.WalkDir.html#method.new
/// [`WalkDir`]: struct.WalkDir.html
pub fn depth(&self) -> usize {
self.depth
}
/// Inspect the original [`io::Error`] if there is one.
///
/// [`None`] is returned if the [`Error`] doesn't correspond to an
/// [`io::Error`]. This might happen, for example, when the error was
/// produced because a cycle was found in the directory tree while
/// following symbolic links.
///
/// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To
/// obtain an owned value, the [`into_io_error`] can be used instead.
///
/// > This is the original [`io::Error`] and is _not_ the same as
/// > [`impl From<Error> for std::io::Error`][impl] which contains additional context about the
/// error.
///
/// # Example
///
/// ```rust,no_run
/// use std::io;
/// use std::path::Path;
///
/// use walkdir::WalkDir;
///
/// for entry in WalkDir::new("foo") {
/// match entry {
/// Ok(entry) => println!("{}", entry.path().display()),
/// Err(err) => {
/// let path = err.path().unwrap_or(Path::new("")).display();
/// println!("failed to access entry {}", path);
/// if let Some(inner) = err.io_error() {
/// match inner.kind() {
/// io::ErrorKind::InvalidData => {
/// println!(
/// "entry contains invalid data: {}",
/// inner)
/// }
/// io::ErrorKind::PermissionDenied => {
/// println!(
/// "Missing permission to read entry: {}",
/// inner)
/// }
/// _ => {
/// println!(
/// "Unexpected error occurred: {}",
/// inner)
/// }
/// }
/// }
/// }
/// }
/// }
/// ```
///
/// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None
/// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
/// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html
/// [`Error`]: struct.Error.html
/// [`into_io_error`]: struct.Error.html#method.into_io_error
/// [impl]: struct.Error.html#impl-From%3CError%3E
pub fn io_error(&self) -> Option<&io::Error> {
match self.inner {
ErrorInner::Io { ref err, .. } => Some(err),
ErrorInner::Loop { .. } => None,
}
}
/// Similar to [`io_error`] except consumes self to convert to the original
/// [`io::Error`] if one exists.
///
/// [`io_error`]: struct.Error.html#method.io_error
/// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
pub fn into_io_error(self) -> Option<io::Error> {
match self.inner {
ErrorInner::Io { err, .. } => Some(err),
ErrorInner::Loop { .. } => None,
}
}
pub(crate) fn from_path(
depth: usize,
pb: PathBuf,
err: io::Error,
) -> Self {
Error { depth, inner: ErrorInner::Io { path: Some(pb), err } }
}
pub(crate) fn from_entry(dent: &DirEntry, err: io::Error) -> Self {
Error {
depth: dent.depth(),
inner: ErrorInner::Io {
path: Some(dent.path().to_path_buf()),
err,
},
}
}
pub(crate) fn from_io(depth: usize, err: io::Error) -> Self {
Error { depth, inner: ErrorInner::Io { path: None, err } }
}
pub(crate) fn from_loop(
depth: usize,
ancestor: &Path,
child: &Path,
) -> Self {
Error {
depth,
inner: ErrorInner::Loop {
ancestor: ancestor.to_path_buf(),
child: child.to_path_buf(),
},
}
}
}
impl error::Error for Error {
#[allow(deprecated)]
fn description(&self) -> &str {
match self.inner {
ErrorInner::Io { ref err, .. } => err.description(),
ErrorInner::Loop { .. } => "file system loop found",
}
}
fn cause(&self) -> Option<&dyn error::Error> {
self.source()
}
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self.inner {
ErrorInner::Io { ref err, .. } => Some(err),
ErrorInner::Loop { .. } => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.inner {
ErrorInner::Io { path: None, ref err } => err.fmt(f),
ErrorInner::Io { path: Some(ref path), ref err } => write!(
f,
"IO error for operation on {}: {}",
path.display(),
err
),
ErrorInner::Loop { ref ancestor, ref child } => write!(
f,
"File system loop found: \
{} points to an ancestor {}",
child.display(),
ancestor.display()
),
}
}
}
impl From<Error> for io::Error {
/// Convert the [`Error`] to an [`io::Error`], preserving the original
/// [`Error`] as the ["inner error"]. Note that this also makes the display
/// of the error include the context.
///
/// This is different from [`into_io_error`] which returns the original
/// [`io::Error`].
///
/// [`Error`]: struct.Error.html
/// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
/// ["inner error"]: https://doc.rust-lang.org/std/io/struct.Error.html#method.into_inner
/// [`into_io_error`]: struct.WalkDir.html#method.into_io_error
fn from(walk_err: Error) -> io::Error {
let kind = match walk_err {
Error { inner: ErrorInner::Io { ref err, .. }, .. } => err.kind(),
Error { inner: ErrorInner::Loop { .. }, .. } => {
io::ErrorKind::Other
}
};
io::Error::new(kind, walk_err)
}
}

1194
vendor/walkdir/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

4
vendor/walkdir/src/tests/mod.rs vendored Normal file
View File

@@ -0,0 +1,4 @@
#[macro_use]
mod util;
mod recursive;

1092
vendor/walkdir/src/tests/recursive.rs vendored Normal file

File diff suppressed because it is too large Load Diff

252
vendor/walkdir/src/tests/util.rs vendored Normal file
View File

@@ -0,0 +1,252 @@
use std::env;
use std::error;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::result;
use crate::{DirEntry, Error};
/// Create an error from a format!-like syntax.
#[macro_export]
macro_rules! err {
($($tt:tt)*) => {
Box::<dyn error::Error + Send + Sync>::from(format!($($tt)*))
}
}
/// A convenient result type alias.
pub type Result<T> = result::Result<T, Box<dyn error::Error + Send + Sync>>;
/// The result of running a recursive directory iterator on a single directory.
#[derive(Debug)]
pub struct RecursiveResults {
ents: Vec<DirEntry>,
errs: Vec<Error>,
}
impl RecursiveResults {
/// Return all of the errors encountered during traversal.
pub fn errs(&self) -> &[Error] {
&self.errs
}
/// Assert that no errors have occurred.
pub fn assert_no_errors(&self) {
assert!(
self.errs.is_empty(),
"expected to find no errors, but found: {:?}",
self.errs
);
}
/// Return all the successfully retrieved directory entries in the order
/// in which they were retrieved.
pub fn ents(&self) -> &[DirEntry] {
&self.ents
}
/// Return all paths from all successfully retrieved directory entries.
///
/// This does not include paths that correspond to an error.
pub fn paths(&self) -> Vec<PathBuf> {
self.ents.iter().map(|d| d.path().to_path_buf()).collect()
}
/// Return all the successfully retrieved directory entries, sorted
/// lexicographically by their full file path.
pub fn sorted_ents(&self) -> Vec<DirEntry> {
let mut ents = self.ents.clone();
ents.sort_by(|e1, e2| e1.path().cmp(e2.path()));
ents
}
/// Return all paths from all successfully retrieved directory entries,
/// sorted lexicographically.
///
/// This does not include paths that correspond to an error.
pub fn sorted_paths(&self) -> Vec<PathBuf> {
self.sorted_ents().into_iter().map(|d| d.into_path()).collect()
}
}
/// A helper for managing a directory in which to run tests.
///
/// When manipulating paths within this directory, paths are interpreted
/// relative to this directory.
#[derive(Debug)]
pub struct Dir {
dir: TempDir,
}
impl Dir {
/// Create a new empty temporary directory.
pub fn tmp() -> Dir {
let dir = TempDir::new().unwrap();
Dir { dir }
}
/// Return the path to this directory.
pub fn path(&self) -> &Path {
self.dir.path()
}
/// Return a path joined to the path to this directory.
pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
self.path().join(path)
}
/// Run the given iterator and return the result as a distinct collection
/// of directory entries and errors.
pub fn run_recursive<I>(&self, it: I) -> RecursiveResults
where
I: IntoIterator<Item = result::Result<DirEntry, Error>>,
{
let mut results = RecursiveResults { ents: vec![], errs: vec![] };
for result in it {
match result {
Ok(ent) => results.ents.push(ent),
Err(err) => results.errs.push(err),
}
}
results
}
/// Create a directory at the given path, while creating all intermediate
/// directories as needed.
pub fn mkdirp<P: AsRef<Path>>(&self, path: P) {
let full = self.join(path);
fs::create_dir_all(&full)
.map_err(|e| {
err!("failed to create directory {}: {}", full.display(), e)
})
.unwrap();
}
/// Create an empty file at the given path. All ancestor directories must
/// already exists.
pub fn touch<P: AsRef<Path>>(&self, path: P) {
let full = self.join(path);
File::create(&full)
.map_err(|e| {
err!("failed to create file {}: {}", full.display(), e)
})
.unwrap();
}
/// Create empty files at the given paths. All ancestor directories must
/// already exists.
pub fn touch_all<P: AsRef<Path>>(&self, paths: &[P]) {
for p in paths {
self.touch(p);
}
}
/// Create a file symlink to the given src with the given link name.
pub fn symlink_file<P1: AsRef<Path>, P2: AsRef<Path>>(
&self,
src: P1,
link_name: P2,
) {
#[cfg(windows)]
fn imp(src: &Path, link_name: &Path) -> io::Result<()> {
use std::os::windows::fs::symlink_file;
symlink_file(src, link_name)
}
#[cfg(unix)]
fn imp(src: &Path, link_name: &Path) -> io::Result<()> {
use std::os::unix::fs::symlink;
symlink(src, link_name)
}
let (src, link_name) = (self.join(src), self.join(link_name));
imp(&src, &link_name)
.map_err(|e| {
err!(
"failed to symlink file {} with target {}: {}",
src.display(),
link_name.display(),
e
)
})
.unwrap()
}
/// Create a directory symlink to the given src with the given link name.
pub fn symlink_dir<P1: AsRef<Path>, P2: AsRef<Path>>(
&self,
src: P1,
link_name: P2,
) {
#[cfg(windows)]
fn imp(src: &Path, link_name: &Path) -> io::Result<()> {
use std::os::windows::fs::symlink_dir;
symlink_dir(src, link_name)
}
#[cfg(unix)]
fn imp(src: &Path, link_name: &Path) -> io::Result<()> {
use std::os::unix::fs::symlink;
symlink(src, link_name)
}
let (src, link_name) = (self.join(src), self.join(link_name));
imp(&src, &link_name)
.map_err(|e| {
err!(
"failed to symlink directory {} with target {}: {}",
src.display(),
link_name.display(),
e
)
})
.unwrap()
}
}
/// A simple wrapper for creating a temporary directory that is automatically
/// deleted when it's dropped.
///
/// We use this in lieu of tempfile because tempfile brings in too many
/// dependencies.
#[derive(Debug)]
pub struct TempDir(PathBuf);
impl Drop for TempDir {
fn drop(&mut self) {
fs::remove_dir_all(&self.0).unwrap();
}
}
impl TempDir {
/// Create a new empty temporary directory under the system's configured
/// temporary directory.
pub fn new() -> Result<TempDir> {
#[allow(deprecated)]
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
static TRIES: usize = 100;
#[allow(deprecated)]
static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
let tmpdir = env::temp_dir();
for _ in 0..TRIES {
let count = COUNTER.fetch_add(1, Ordering::SeqCst);
let path = tmpdir.join("rust-walkdir").join(count.to_string());
if path.is_dir() {
continue;
}
fs::create_dir_all(&path).map_err(|e| {
err!("failed to create {}: {}", path.display(), e)
})?;
return Ok(TempDir(path));
}
Err(err!("failed to create temp dir after {} tries", TRIES))
}
/// Return the underlying path to this temporary directory.
pub fn path(&self) -> &Path {
&self.0
}
}

25
vendor/walkdir/src/util.rs vendored Normal file
View File

@@ -0,0 +1,25 @@
use std::io;
use std::path::Path;
#[cfg(unix)]
pub fn device_num<P: AsRef<Path>>(path: P) -> io::Result<u64> {
use std::os::unix::fs::MetadataExt;
path.as_ref().metadata().map(|md| md.dev())
}
#[cfg(windows)]
pub fn device_num<P: AsRef<Path>>(path: P) -> io::Result<u64> {
use winapi_util::{file, Handle};
let h = Handle::from_path_any(path)?;
file::information(h).map(|info| info.volume_serial_number())
}
#[cfg(not(any(unix, windows)))]
pub fn device_num<P: AsRef<Path>>(_: P) -> io::Result<u64> {
Err(io::Error::new(
io::ErrorKind::Other,
"walkdir: same_file_system option not supported on this platform",
))
}