Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/walkdir/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/walkdir/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"425547c73a8eae93c39110869fd5ecac3a99a984c715ad7ab1d6a40b7efb0ee5","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"5fc28c8211fe74af2889a2eb859127f8d543e0f94be80659c307105ed831f84b","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","compare/nftw.c":"6b900b0ac78ce8ece1995f834b194fa14d87d744cabba8f475f0e10b21722c56","compare/walk.py":"d49e26d0b8b2b201d00f2f46bf1f9db46f873c27332da679c9a7adbbf54462d2","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/dent.rs":"ca573f4533370a09851579f5940f7cd9bd121b2f30ec51d29a40afdce984683b","src/error.rs":"ba58bf6f59d196567435d4b66699a928cc237fc7c8df01dc37ab822509905b7c","src/lib.rs":"3f7d673f9e278a71de2cb5f90353a44ea7803a98d49c2f72a68cb26dce8c966a","src/tests/mod.rs":"bbce9174bfdbb4a81a9000f702be056b63b439cb8f1bcac64b8569368627d56d","src/tests/recursive.rs":"b6305e7cc9f905ce6b7328ac9fb5b07e5a73fa549c0b84ef890fb442d1bbcb7c","src/tests/util.rs":"ca72ef96f82bb87d8c93d13d581ebb65efcd53fffa87097a84437acecbc30faa","src/util.rs":"14e0da711cad4825ead21446cd61a1444fd49bab853a8a239d8cb74b2caab351"},"package":"29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"}
|
||||
3
third-party/vendor/walkdir/COPYING
vendored
Normal file
3
third-party/vendor/walkdir/COPYING
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
This project is dual-licensed under the Unlicense and MIT licenses.
|
||||
|
||||
You may use this code under the terms of either license.
|
||||
49
third-party/vendor/walkdir/Cargo.toml
vendored
Normal file
49
third-party/vendor/walkdir/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
exclude = [
|
||||
"/ci/*",
|
||||
"/.travis.yml",
|
||||
"/appveyor.yml",
|
||||
]
|
||||
description = "Recursively walk a directory."
|
||||
homepage = "https://github.com/BurntSushi/walkdir"
|
||||
documentation = "https://docs.rs/walkdir/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"directory",
|
||||
"recursive",
|
||||
"walk",
|
||||
"iterator",
|
||||
]
|
||||
categories = ["filesystem"]
|
||||
license = "Unlicense/MIT"
|
||||
repository = "https://github.com/BurntSushi/walkdir"
|
||||
|
||||
[dependencies.same-file]
|
||||
version = "1.0.1"
|
||||
|
||||
[dev-dependencies.doc-comment]
|
||||
version = "0.3"
|
||||
|
||||
[target."cfg(windows)".dependencies.winapi-util]
|
||||
version = "0.1.1"
|
||||
|
||||
[badges.appveyor]
|
||||
repository = "BurntSushi/walkdir"
|
||||
|
||||
[badges.travis-ci]
|
||||
repository = "BurntSushi/walkdir"
|
||||
21
third-party/vendor/walkdir/LICENSE-MIT
vendored
Normal file
21
third-party/vendor/walkdir/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Andrew Gallant
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
139
third-party/vendor/walkdir/README.md
vendored
Normal file
139
third-party/vendor/walkdir/README.md
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
walkdir
|
||||
=======
|
||||
A cross platform Rust library for efficiently walking a directory recursively.
|
||||
Comes with support for following symbolic links, controlling the number of
|
||||
open file descriptors and efficient mechanisms for pruning the entries in the
|
||||
directory tree.
|
||||
|
||||
[](https://github.com/BurntSushi/walkdir/actions)
|
||||
[](https://crates.io/crates/walkdir)
|
||||
|
||||
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||
|
||||
### Documentation
|
||||
|
||||
[docs.rs/walkdir](https://docs.rs/walkdir/)
|
||||
|
||||
### Usage
|
||||
|
||||
To use this crate, add `walkdir` as a dependency to your project's
|
||||
`Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
walkdir = "2"
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
The following code recursively iterates over the directory given and prints
|
||||
the path for each entry:
|
||||
|
||||
```rust,no_run
|
||||
use walkdir::WalkDir;
|
||||
|
||||
for entry in WalkDir::new("foo") {
|
||||
let entry = entry.unwrap();
|
||||
println!("{}", entry.path().display());
|
||||
}
|
||||
```
|
||||
|
||||
Or, if you'd like to iterate over all entries and ignore any errors that may
|
||||
arise, use `filter_map`. (e.g., This code below will silently skip directories
|
||||
that the owner of the running process does not have permission to access.)
|
||||
|
||||
```rust,no_run
|
||||
use walkdir::WalkDir;
|
||||
|
||||
for entry in WalkDir::new("foo").into_iter().filter_map(|e| e.ok()) {
|
||||
println!("{}", entry.path().display());
|
||||
}
|
||||
```
|
||||
|
||||
### Example: follow symbolic links
|
||||
|
||||
The same code as above, except `follow_links` is enabled:
|
||||
|
||||
```rust,no_run
|
||||
use walkdir::WalkDir;
|
||||
|
||||
for entry in WalkDir::new("foo").follow_links(true) {
|
||||
let entry = entry.unwrap();
|
||||
println!("{}", entry.path().display());
|
||||
}
|
||||
```
|
||||
|
||||
### Example: skip hidden files and directories efficiently on unix
|
||||
|
||||
This uses the `filter_entry` iterator adapter to avoid yielding hidden files
|
||||
and directories efficiently:
|
||||
|
||||
```rust,no_run
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
fn is_hidden(entry: &DirEntry) -> bool {
|
||||
entry.file_name()
|
||||
.to_str()
|
||||
.map(|s| s.starts_with("."))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
let walker = WalkDir::new("foo").into_iter();
|
||||
for entry in walker.filter_entry(|e| !is_hidden(e)) {
|
||||
let entry = entry.unwrap();
|
||||
println!("{}", entry.path().display());
|
||||
}
|
||||
```
|
||||
|
||||
### Minimum Rust version policy
|
||||
|
||||
This crate's minimum supported `rustc` version is `1.34.0`.
|
||||
|
||||
The current policy is that the minimum Rust version required to use this crate
|
||||
can be increased in minor version updates. For example, if `crate 1.0` requires
|
||||
Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also require Rust
|
||||
1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a newer minimum
|
||||
version of Rust.
|
||||
|
||||
In general, this crate will be conservative with respect to the minimum
|
||||
supported version of Rust.
|
||||
|
||||
### Performance
|
||||
|
||||
The short story is that performance is comparable with `find` and glibc's
|
||||
`nftw` on both a warm and cold file cache. In fact, I cannot observe any
|
||||
performance difference after running `find /`, `walkdir /` and `nftw /` on my
|
||||
local file system (SSD, ~3 million entries). More precisely, I am reasonably
|
||||
confident that this crate makes as few system calls and close to as few
|
||||
allocations as possible.
|
||||
|
||||
I haven't recorded any benchmarks, but here are some things you can try with a
|
||||
local checkout of `walkdir`:
|
||||
|
||||
```sh
|
||||
# The directory you want to recursively walk:
|
||||
DIR=$HOME
|
||||
|
||||
# If you want to observe perf on a cold file cache, run this before *each*
|
||||
# command:
|
||||
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
|
||||
|
||||
# To warm the caches
|
||||
find $DIR
|
||||
|
||||
# Test speed of `find` on warm cache:
|
||||
time find $DIR
|
||||
|
||||
# Compile and test speed of `walkdir` crate:
|
||||
cargo build --release --example walkdir
|
||||
time ./target/release/examples/walkdir $DIR
|
||||
|
||||
# Compile and test speed of glibc's `nftw`:
|
||||
gcc -O3 -o nftw ./compare/nftw.c
|
||||
time ./nftw $DIR
|
||||
|
||||
# For shits and giggles, test speed of Python's (2 or 3) os.walk:
|
||||
time python ./compare/walk.py $DIR
|
||||
```
|
||||
|
||||
On my system, the performance of `walkdir`, `find` and `nftw` is comparable.
|
||||
24
third-party/vendor/walkdir/UNLICENSE
vendored
Normal file
24
third-party/vendor/walkdir/UNLICENSE
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
25
third-party/vendor/walkdir/compare/nftw.c
vendored
Normal file
25
third-party/vendor/walkdir/compare/nftw.c
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#define _XOPEN_SOURCE 500
|
||||
#include <ftw.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static int
|
||||
display_info(const char *fpath, const struct stat *sb,
|
||||
int tflag, struct FTW *ftwbuf)
|
||||
{
|
||||
printf("%s\n", fpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int flags = FTW_PHYS;
|
||||
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) {
|
||||
perror("nftw");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
10
third-party/vendor/walkdir/compare/walk.py
vendored
Normal file
10
third-party/vendor/walkdir/compare/walk.py
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(sys.argv[1]):
|
||||
for n in dirnames:
|
||||
print(os.path.join(dirpath, n))
|
||||
for n in filenames:
|
||||
print(os.path.join(dirpath, n))
|
||||
2
third-party/vendor/walkdir/rustfmt.toml
vendored
Normal file
2
third-party/vendor/walkdir/rustfmt.toml
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
max_width = 79
|
||||
use_small_heuristics = "max"
|
||||
352
third-party/vendor/walkdir/src/dent.rs
vendored
Normal file
352
third-party/vendor/walkdir/src/dent.rs
vendored
Normal 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
third-party/vendor/walkdir/src/error.rs
vendored
Normal file
262
third-party/vendor/walkdir/src/error.rs
vendored
Normal 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
third-party/vendor/walkdir/src/lib.rs
vendored
Normal file
1194
third-party/vendor/walkdir/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
4
third-party/vendor/walkdir/src/tests/mod.rs
vendored
Normal file
4
third-party/vendor/walkdir/src/tests/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#[macro_use]
|
||||
mod util;
|
||||
|
||||
mod recursive;
|
||||
1092
third-party/vendor/walkdir/src/tests/recursive.rs
vendored
Normal file
1092
third-party/vendor/walkdir/src/tests/recursive.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
252
third-party/vendor/walkdir/src/tests/util.rs
vendored
Normal file
252
third-party/vendor/walkdir/src/tests/util.rs
vendored
Normal 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
third-party/vendor/walkdir/src/util.rs
vendored
Normal file
25
third-party/vendor/walkdir/src/util.rs
vendored
Normal 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",
|
||||
))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue