├── .envrc
├── .gitignore
├── flake.nix
├── flake.lock
├── Cargo.toml
├── LICENSE
├── src
├── lib.rs
├── main.rs
└── nmuidi.rs
├── .github
└── workflows
│ └── build.yml
├── README.md
└── Cargo.lock
/.envrc:
--------------------------------------------------------------------------------
1 | use flake
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #VS Code
2 | .vscode/
3 |
4 | # Generated by Cargo
5 | # will have compiled files and executables
6 | debug/
7 | target/
8 |
9 | # These are backup files generated by rustfmt
10 | **/*.rs.bk
11 |
12 | # MSVC Windows builds of rustc generate these, which store debugging information
13 | *.pdb
14 |
15 | # Tmp files and directories used for testing
16 | tmp/
17 |
18 | # Direnv metadata
19 | .direnv
20 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
3 |
4 | outputs = { self, nixpkgs }:
5 | let
6 | supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
7 | forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
8 | pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
9 | in
10 | {
11 | devShells = forAllSystems (system: {
12 | default = pkgs.${system}.mkShell {
13 | buildInputs = with pkgs.${system}; [ cargo rustc rust-analyzer ];
14 | };
15 | });
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "nixpkgs": {
4 | "locked": {
5 | "lastModified": 1753750875,
6 | "narHash": "sha256-J1P0aQymehe8AHsID9wwoMjbaYrIB2eH5HftoXhF9xk=",
7 | "owner": "NixOS",
8 | "repo": "nixpkgs",
9 | "rev": "871381d997e4a063f25a3994ce8a9ac595246610",
10 | "type": "github"
11 | },
12 | "original": {
13 | "owner": "NixOS",
14 | "ref": "nixpkgs-unstable",
15 | "repo": "nixpkgs",
16 | "type": "github"
17 | }
18 | },
19 | "root": {
20 | "inputs": {
21 | "nixpkgs": "nixpkgs"
22 | }
23 | }
24 | },
25 | "root": "root",
26 | "version": 7
27 | }
28 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "nmuidi"
3 | version = "0.1.5"
4 | edition = "2021"
5 | description = "Parallelizes deleting directories which can significantly speed up deleting large deeply nested directories with a large number of files on Windows"
6 | readme = "README.md"
7 | homepage = "https://github.com/Dillonb/nmuidi"
8 | documentation = "https://docs.rs/nmuidi"
9 | repository = "https://github.com/Dillonb/nmuidi"
10 | license = "MIT"
11 | keywords = ["windows", "delete", "parallel"]
12 | categories = ["command-line-utilities", "filesystem"]
13 |
14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
15 |
16 | [dependencies]
17 | jwalk = "0.8.1"
18 | num_cpus = "1.16.0"
19 | itertools = "0.11.0"
20 | log = "0.4.20"
21 | pretty_env_logger = "0.5.0"
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Al Dente Software
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Deletes stuff, hopefully quickly
2 | //!
3 | //! ## Installation
4 | //! - [Download for Windows](https://nightly.link/Dillonb/nmuidi/workflows/build/main/nmuidi-windows.zip)
5 | //! - Or just use `cargo`
6 | //!
7 | //! ## Benchmarks
8 | //! - [This video](https://www.youtube.com/watch?v=G8BdXgBdaOA) benchmarks several popular suggestions for deleting files quickly on Windows and compares them to nmuidi.
9 | //!
10 | //! ## How to use
11 | //! ### As a command-line tool
12 | //! - You can download using the link above. The easiest way to use it in Windows is to make a folder (something like `C:\bin`)
13 | //! - Add that folder to your path
14 | //! - Then add `nmuidi.exe` file you downloaded to that folder and restart any terminals you have open
15 | //!
16 | //! Then you can run `nmuidi /path/to/some/dir` and you should see some output like the following:
17 | //! ```PS
18 | //! → ~\repos\nmuidi [main ≡ +0 ~1 -0 !]› nmuidi test
19 | //! Cleaning test
20 | //! ```
21 | //!
22 | //! ### As a library
23 | //! ```
24 | //! use nmuidi::prelude::*;
25 | //!
26 | //! let dir = "path/to/something";
27 | //! Cleaner::new(dir).clean();
28 | //! ```
29 | //!
30 |
31 | /// All nmuidi `Cleaner` functionality
32 | pub mod prelude {
33 | pub use crate::nmuidi::Cleaner;
34 | }
35 |
36 | /// Module containing basic libray functionality
37 | #[doc(hidden)]
38 | pub mod nmuidi;
39 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Rust
2 |
3 | on: [push, pull_request]
4 |
5 | env:
6 | CARGO_TERM_COLOR: always
7 | RUST_LOG: debug
8 |
9 | jobs:
10 | format:
11 | runs-on: windows-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v3
15 | - name: cargo-fmt
16 | run: cargo fmt --verbose
17 |
18 | clippy:
19 | runs-on: windows-latest
20 |
21 | steps:
22 | - uses: actions/checkout@v3
23 | - name: cargo-clippy
24 | run: cargo clippy -- -Dwarnings
25 | - name: cargo-clippy-pedantic
26 | continue-on-error: true
27 | run: cargo clippy -- -W clippy::pedantic
28 |
29 | test:
30 | runs-on: windows-latest
31 |
32 | steps:
33 | - uses: actions/checkout@v3
34 | - name: cargo-test
35 | run: cargo test
36 |
37 | build-windows:
38 | runs-on: windows-latest
39 | needs: [format, clippy, test]
40 |
41 | steps:
42 | - uses: actions/checkout@v1
43 | - uses: dtolnay/rust-toolchain@stable
44 |
45 | - name: Build
46 | run: cargo build --all --release
47 |
48 | - name: Upload to artifacts
49 | uses: actions/upload-artifact@master
50 | with:
51 | name: nmuidi-windows
52 | path: target/release/nmuidi.exe
53 |
54 | - name: Create release
55 | uses: softprops/action-gh-release@v2
56 | if: startsWith(github.ref, 'refs/tags/')
57 | with:
58 | files: |
59 | target/release/nmuidi.exe
60 | LICENSE
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nmuidi
2 |
3 | Deletes stuff, hopefully quickly
4 |
5 | To download, check out the [releases page](https://github.com/Dillonb/nmuidi/releases) or download [the latest development build](https://nightly.link/Dillonb/nmuidi/workflows/build/main/nmuidi-windows.zip).
6 |
7 | [This video](https://www.youtube.com/watch?v=G8BdXgBdaOA) benchmarks several popular suggestions for deleting files quickly on Windows and compares them to nmuidi.
8 |
9 | ## How to use
10 |
11 | ### As a command-line tool
12 |
13 | You can download using the link above. The easiest way to use it in Windows is to make a folder (something like `C:\bin`) and add that folder to your path. Then add `nmuidi.exe` file you downloaded to that folder and restart any terminals you have open.
14 |
15 | Then you can run `nmuidi /path/to/some/dir` and you should see some output like the following:
16 |
17 | ```PS
18 | → ~\repos\nmuidi [main ≡ +0 ~1 -0 !]› nmuidi test
19 | Cleaning test
20 | ```
21 |
22 | To change the log level, set the `RUST_LOG` environment variable:
23 |
24 | PowerShell: `$env:RUST_LOG = 'trace'`
25 |
26 | CMD: `set RUST_LOG=trace`
27 |
28 | The output will then look something like:
29 |
30 | ```PS
31 | → ~\repos\nmuidi [main ≡ +0 ~1 -0 !]› nmuidi test1 test2
32 | Cleaning test1
33 | Cleaning test2
34 | Total time: 10.00s
35 | Directory timings:
36 | dir test1 took 5.00s
37 | dir test2 took 5.00s
38 | Done.
39 | ```
40 |
41 | ### As a package
42 |
43 | 1. `cargo add nmuidi`
44 | 2. add `use nmuidi::nmuidi::Cleaner;`
45 | 3. Create a cleaner and clean `Cleaner::new("some/path").clean();`
46 |
47 |
48 | ## Why the dumb name
49 |
50 | 1. It's an inside joke
51 | 2. Having a complicated name makes it harder to accidentally nuke a folder. This program does NOT ask you to confirm, if you tell it to delete something it will start deleting things immediately.
52 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | use log::{debug, trace};
2 | #[doc(inline)]
3 | use nmuidi::prelude::*;
4 | use std::{env, time::Instant};
5 |
6 | fn main() {
7 | pretty_env_logger::init();
8 |
9 | let mut directory_timings = Vec::new();
10 | let start_time = Instant::now();
11 | for dir in env::args().skip(1) {
12 | println!("Cleaning {dir}");
13 | let start = Instant::now();
14 |
15 | Cleaner::new(&dir).clean();
16 | directory_timings.push((dir, start.elapsed()));
17 | }
18 |
19 | let elapsed_time = start_time.elapsed();
20 | debug!("Total time: {:.2?}", elapsed_time);
21 | debug!("Directory timings:");
22 | for (dir, time_spent) in directory_timings {
23 | debug!(" dir {dir} took {:.2?}", time_spent);
24 | }
25 | trace!("Done.");
26 | }
27 |
28 | #[cfg(test)]
29 | mod tests {
30 | use super::*;
31 | use jwalk::WalkDir;
32 | use std::fs;
33 |
34 | #[test]
35 | fn test_nested() {
36 | fs::create_dir_all("tmp/nested/dir1").unwrap();
37 | fs::write("tmp/nested/dir1/file1.txt", "File 1 content").unwrap();
38 |
39 | fs::create_dir_all("tmp/nested/dir1/dir2").unwrap();
40 | fs::write("tmp/nested/dir1/dir2/file2.txt", "File 2 content").unwrap();
41 |
42 | fs::create_dir_all("tmp/nested/dir1/dir2/dir3").unwrap();
43 | fs::write("tmp/nested/dir1/dir2/dir3/file3.txt", "File 3 content").unwrap();
44 |
45 | Cleaner::new("tmp/nested").clean();
46 |
47 | let num_files = WalkDir::new("tmp/nested")
48 | .skip_hidden(false)
49 | .into_iter()
50 | .collect::>()
51 | .len();
52 | assert_eq!(num_files, 1);
53 | }
54 |
55 | #[test]
56 | fn test_dirs() {
57 | fs::create_dir_all("tmp/dirs/dir1").unwrap();
58 | fs::create_dir_all("tmp/dirs/dir1a").unwrap();
59 | fs::create_dir_all("tmp/dirs/dir1/dir2").unwrap();
60 | fs::create_dir_all("tmp/dirs/dir1/dir2a").unwrap();
61 | fs::create_dir_all("tmp/dirs/dir1/dir2/dir3").unwrap();
62 | fs::create_dir_all("tmp/dirs/dir1/dir2/dir3a").unwrap();
63 |
64 | Cleaner::new("tmp/dirs").clean();
65 |
66 | let num_files = WalkDir::new("tmp/dirs")
67 | .skip_hidden(false)
68 | .into_iter()
69 | .collect::>()
70 | .len();
71 | assert_eq!(num_files, 1);
72 | }
73 |
74 | #[test]
75 | fn test_files() {
76 | fs::create_dir_all("tmp/files").unwrap();
77 | fs::write("tmp/files/file1.txt", "File 1 content").unwrap();
78 | fs::write("tmp/files/file2.txt", "File 2 content").unwrap();
79 | fs::write("tmp/files/file3.txt", "File 3 content").unwrap();
80 | fs::write("tmp/files/file4.txt", "File 4 content").unwrap();
81 | fs::write("tmp/files/file5.txt", "File 5 content").unwrap();
82 | fs::write("tmp/files/file6.txt", "File 6 content").unwrap();
83 |
84 | Cleaner::new("tmp/files").clean();
85 |
86 | let num_files = WalkDir::new("tmp/files")
87 | .skip_hidden(false)
88 | .into_iter()
89 | .collect::>()
90 | .len();
91 | assert_eq!(num_files, 1);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/nmuidi.rs:
--------------------------------------------------------------------------------
1 | use std::{fs, path::PathBuf};
2 |
3 | use itertools::Itertools;
4 | use jwalk::{
5 | rayon::prelude::{IntoParallelRefIterator, ParallelBridge, ParallelIterator},
6 | WalkDir,
7 | };
8 | use log::error;
9 |
10 | /// `Cleaner` is a lazily executed framework for nmuidi.
11 | /// # Examples
12 | /// ```
13 | /// use nmuidi::prelude::*;
14 | /// let cleaner = Cleaner::new("some/path").clean();
15 | /// ```
16 | pub struct Cleaner {
17 | path: PathBuf,
18 | dirs: Vec<(PathBuf, usize)>, // (path, depth)
19 | threads: usize,
20 | }
21 |
22 | impl Cleaner {
23 | /// Form a new `Cleaner` stuct, does not execute anything until `.clean()` is called
24 | pub fn new(path: T) -> Self
25 | where
26 | std::path::PathBuf: std::convert::From,
27 | {
28 | Self {
29 | path: path.into(),
30 | dirs: Vec::new(),
31 | threads: num_cpus::get() * 100,
32 | }
33 | }
34 |
35 | /// Perform the deletion of the selected directory
36 | pub fn clean(&mut self) {
37 | self.remove_files();
38 | self.remove_dirs();
39 | }
40 |
41 | fn remove_dirs(&mut self) {
42 | let dirs_by_depth = self.dirs.iter().group_by(|x| x.1);
43 | for (_, level) in &dirs_by_depth {
44 | level
45 | .collect::>()
46 | .par_iter()
47 | .map(|(dir, _group)| dir)
48 | .for_each(|dir| {
49 | if let Err(e) = fs::remove_dir_all(dir.as_path()) {
50 | println!("Error removing directory {}: {e}", dir.display());
51 | }
52 | });
53 | }
54 | }
55 |
56 | fn is_reparse_point(meta: &std::fs::Metadata) -> bool {
57 | use std::os::windows::fs::MetadataExt;
58 | const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0400;
59 | meta.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0
60 | }
61 |
62 | fn remove_files(&mut self) {
63 | let mut dirs: Vec<(std::path::PathBuf, usize)> = WalkDir::new(&self.path)
64 | .skip_hidden(false)
65 | .parallelism(jwalk::Parallelism::RayonNewPool(self.threads))
66 | .into_iter()
67 | .par_bridge()
68 | .flat_map(|entry| {
69 | match entry {
70 | Ok(entry) => {
71 | let path = entry.path();
72 |
73 | // Get metdata while avoiding walking into junctions
74 | let metadata = match fs::symlink_metadata(&path) {
75 | Ok(m) => m,
76 | Err(e) => {
77 | error!("Failed to get metadata for {}: {e}", path.display());
78 | return None;
79 | }
80 | };
81 |
82 | let f_type = metadata.file_type();
83 |
84 | // if this is a directory *and* reparse point then it's a junction,
85 | // delete it like a directory but skip walking inside
86 | if f_type.is_dir() && Cleaner::is_reparse_point(&metadata) {
87 | fs::remove_dir(&path).unwrap_or_else(|e| {
88 | error!("Failed to remove reparse point {}: {e}", path.display());
89 | });
90 | return None;
91 | }
92 |
93 | let mut perm = metadata.permissions();
94 | if perm.readonly() {
95 | #[allow(clippy::permissions_set_readonly_false)]
96 | perm.set_readonly(false);
97 | fs::set_permissions(&path, perm).unwrap_or_else(|e| {
98 | error!("Error making {} write-accessible: {e}", path.display());
99 | });
100 | }
101 | if f_type.is_file() {
102 | fs::remove_file(&path).unwrap_or_else(|e| {
103 | error!("Failed to remove file {}: {e}", path.display());
104 | });
105 | } else if f_type.is_dir() {
106 | return Some((path, entry.depth));
107 | }
108 | }
109 | Err(error) => error!("Error processing directory entry: {error}"),
110 | }
111 | None
112 | })
113 | .collect();
114 | dirs.sort_by(|a, b| b.1.cmp(&a.1)); // Note reverse sort
115 | self.dirs = dirs;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "aho-corasick"
7 | version = "1.1.2"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
10 | dependencies = [
11 | "memchr",
12 | ]
13 |
14 | [[package]]
15 | name = "autocfg"
16 | version = "1.1.0"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
19 |
20 | [[package]]
21 | name = "bitflags"
22 | version = "2.4.2"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
25 |
26 | [[package]]
27 | name = "cfg-if"
28 | version = "1.0.0"
29 | source = "registry+https://github.com/rust-lang/crates.io-index"
30 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
31 |
32 | [[package]]
33 | name = "crossbeam"
34 | version = "0.8.2"
35 | source = "registry+https://github.com/rust-lang/crates.io-index"
36 | checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
37 | dependencies = [
38 | "cfg-if",
39 | "crossbeam-channel",
40 | "crossbeam-deque",
41 | "crossbeam-epoch",
42 | "crossbeam-queue",
43 | "crossbeam-utils",
44 | ]
45 |
46 | [[package]]
47 | name = "crossbeam-channel"
48 | version = "0.5.8"
49 | source = "registry+https://github.com/rust-lang/crates.io-index"
50 | checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
51 | dependencies = [
52 | "cfg-if",
53 | "crossbeam-utils",
54 | ]
55 |
56 | [[package]]
57 | name = "crossbeam-deque"
58 | version = "0.8.3"
59 | source = "registry+https://github.com/rust-lang/crates.io-index"
60 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
61 | dependencies = [
62 | "cfg-if",
63 | "crossbeam-epoch",
64 | "crossbeam-utils",
65 | ]
66 |
67 | [[package]]
68 | name = "crossbeam-epoch"
69 | version = "0.9.15"
70 | source = "registry+https://github.com/rust-lang/crates.io-index"
71 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
72 | dependencies = [
73 | "autocfg",
74 | "cfg-if",
75 | "crossbeam-utils",
76 | "memoffset",
77 | "scopeguard",
78 | ]
79 |
80 | [[package]]
81 | name = "crossbeam-queue"
82 | version = "0.3.8"
83 | source = "registry+https://github.com/rust-lang/crates.io-index"
84 | checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
85 | dependencies = [
86 | "cfg-if",
87 | "crossbeam-utils",
88 | ]
89 |
90 | [[package]]
91 | name = "crossbeam-utils"
92 | version = "0.8.16"
93 | source = "registry+https://github.com/rust-lang/crates.io-index"
94 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
95 | dependencies = [
96 | "cfg-if",
97 | ]
98 |
99 | [[package]]
100 | name = "either"
101 | version = "1.9.0"
102 | source = "registry+https://github.com/rust-lang/crates.io-index"
103 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
104 |
105 | [[package]]
106 | name = "env_logger"
107 | version = "0.10.2"
108 | source = "registry+https://github.com/rust-lang/crates.io-index"
109 | checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
110 | dependencies = [
111 | "humantime",
112 | "is-terminal",
113 | "log",
114 | "regex",
115 | "termcolor",
116 | ]
117 |
118 | [[package]]
119 | name = "errno"
120 | version = "0.3.8"
121 | source = "registry+https://github.com/rust-lang/crates.io-index"
122 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
123 | dependencies = [
124 | "libc",
125 | "windows-sys",
126 | ]
127 |
128 | [[package]]
129 | name = "hermit-abi"
130 | version = "0.3.2"
131 | source = "registry+https://github.com/rust-lang/crates.io-index"
132 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
133 |
134 | [[package]]
135 | name = "humantime"
136 | version = "2.1.0"
137 | source = "registry+https://github.com/rust-lang/crates.io-index"
138 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
139 |
140 | [[package]]
141 | name = "is-terminal"
142 | version = "0.4.10"
143 | source = "registry+https://github.com/rust-lang/crates.io-index"
144 | checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
145 | dependencies = [
146 | "hermit-abi",
147 | "rustix",
148 | "windows-sys",
149 | ]
150 |
151 | [[package]]
152 | name = "itertools"
153 | version = "0.11.0"
154 | source = "registry+https://github.com/rust-lang/crates.io-index"
155 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
156 | dependencies = [
157 | "either",
158 | ]
159 |
160 | [[package]]
161 | name = "jwalk"
162 | version = "0.8.1"
163 | source = "registry+https://github.com/rust-lang/crates.io-index"
164 | checksum = "2735847566356cd2179a2a38264839308f7079fa96e6bd5a42d740460e003c56"
165 | dependencies = [
166 | "crossbeam",
167 | "rayon",
168 | ]
169 |
170 | [[package]]
171 | name = "libc"
172 | version = "0.2.152"
173 | source = "registry+https://github.com/rust-lang/crates.io-index"
174 | checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
175 |
176 | [[package]]
177 | name = "linux-raw-sys"
178 | version = "0.4.13"
179 | source = "registry+https://github.com/rust-lang/crates.io-index"
180 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
181 |
182 | [[package]]
183 | name = "log"
184 | version = "0.4.20"
185 | source = "registry+https://github.com/rust-lang/crates.io-index"
186 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
187 |
188 | [[package]]
189 | name = "memchr"
190 | version = "2.7.1"
191 | source = "registry+https://github.com/rust-lang/crates.io-index"
192 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
193 |
194 | [[package]]
195 | name = "memoffset"
196 | version = "0.9.0"
197 | source = "registry+https://github.com/rust-lang/crates.io-index"
198 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
199 | dependencies = [
200 | "autocfg",
201 | ]
202 |
203 | [[package]]
204 | name = "nmuidi"
205 | version = "0.1.5"
206 | dependencies = [
207 | "itertools",
208 | "jwalk",
209 | "log",
210 | "num_cpus",
211 | "pretty_env_logger",
212 | ]
213 |
214 | [[package]]
215 | name = "num_cpus"
216 | version = "1.16.0"
217 | source = "registry+https://github.com/rust-lang/crates.io-index"
218 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
219 | dependencies = [
220 | "hermit-abi",
221 | "libc",
222 | ]
223 |
224 | [[package]]
225 | name = "pretty_env_logger"
226 | version = "0.5.0"
227 | source = "registry+https://github.com/rust-lang/crates.io-index"
228 | checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
229 | dependencies = [
230 | "env_logger",
231 | "log",
232 | ]
233 |
234 | [[package]]
235 | name = "rayon"
236 | version = "1.7.0"
237 | source = "registry+https://github.com/rust-lang/crates.io-index"
238 | checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
239 | dependencies = [
240 | "either",
241 | "rayon-core",
242 | ]
243 |
244 | [[package]]
245 | name = "rayon-core"
246 | version = "1.11.0"
247 | source = "registry+https://github.com/rust-lang/crates.io-index"
248 | checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
249 | dependencies = [
250 | "crossbeam-channel",
251 | "crossbeam-deque",
252 | "crossbeam-utils",
253 | "num_cpus",
254 | ]
255 |
256 | [[package]]
257 | name = "regex"
258 | version = "1.10.3"
259 | source = "registry+https://github.com/rust-lang/crates.io-index"
260 | checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
261 | dependencies = [
262 | "aho-corasick",
263 | "memchr",
264 | "regex-automata",
265 | "regex-syntax",
266 | ]
267 |
268 | [[package]]
269 | name = "regex-automata"
270 | version = "0.4.4"
271 | source = "registry+https://github.com/rust-lang/crates.io-index"
272 | checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a"
273 | dependencies = [
274 | "aho-corasick",
275 | "memchr",
276 | "regex-syntax",
277 | ]
278 |
279 | [[package]]
280 | name = "regex-syntax"
281 | version = "0.8.2"
282 | source = "registry+https://github.com/rust-lang/crates.io-index"
283 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
284 |
285 | [[package]]
286 | name = "rustix"
287 | version = "0.38.30"
288 | source = "registry+https://github.com/rust-lang/crates.io-index"
289 | checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
290 | dependencies = [
291 | "bitflags",
292 | "errno",
293 | "libc",
294 | "linux-raw-sys",
295 | "windows-sys",
296 | ]
297 |
298 | [[package]]
299 | name = "scopeguard"
300 | version = "1.2.0"
301 | source = "registry+https://github.com/rust-lang/crates.io-index"
302 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
303 |
304 | [[package]]
305 | name = "termcolor"
306 | version = "1.4.1"
307 | source = "registry+https://github.com/rust-lang/crates.io-index"
308 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
309 | dependencies = [
310 | "winapi-util",
311 | ]
312 |
313 | [[package]]
314 | name = "winapi"
315 | version = "0.3.9"
316 | source = "registry+https://github.com/rust-lang/crates.io-index"
317 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
318 | dependencies = [
319 | "winapi-i686-pc-windows-gnu",
320 | "winapi-x86_64-pc-windows-gnu",
321 | ]
322 |
323 | [[package]]
324 | name = "winapi-i686-pc-windows-gnu"
325 | version = "0.4.0"
326 | source = "registry+https://github.com/rust-lang/crates.io-index"
327 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
328 |
329 | [[package]]
330 | name = "winapi-util"
331 | version = "0.1.6"
332 | source = "registry+https://github.com/rust-lang/crates.io-index"
333 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
334 | dependencies = [
335 | "winapi",
336 | ]
337 |
338 | [[package]]
339 | name = "winapi-x86_64-pc-windows-gnu"
340 | version = "0.4.0"
341 | source = "registry+https://github.com/rust-lang/crates.io-index"
342 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
343 |
344 | [[package]]
345 | name = "windows-sys"
346 | version = "0.52.0"
347 | source = "registry+https://github.com/rust-lang/crates.io-index"
348 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
349 | dependencies = [
350 | "windows-targets",
351 | ]
352 |
353 | [[package]]
354 | name = "windows-targets"
355 | version = "0.52.0"
356 | source = "registry+https://github.com/rust-lang/crates.io-index"
357 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
358 | dependencies = [
359 | "windows_aarch64_gnullvm",
360 | "windows_aarch64_msvc",
361 | "windows_i686_gnu",
362 | "windows_i686_msvc",
363 | "windows_x86_64_gnu",
364 | "windows_x86_64_gnullvm",
365 | "windows_x86_64_msvc",
366 | ]
367 |
368 | [[package]]
369 | name = "windows_aarch64_gnullvm"
370 | version = "0.52.0"
371 | source = "registry+https://github.com/rust-lang/crates.io-index"
372 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
373 |
374 | [[package]]
375 | name = "windows_aarch64_msvc"
376 | version = "0.52.0"
377 | source = "registry+https://github.com/rust-lang/crates.io-index"
378 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
379 |
380 | [[package]]
381 | name = "windows_i686_gnu"
382 | version = "0.52.0"
383 | source = "registry+https://github.com/rust-lang/crates.io-index"
384 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
385 |
386 | [[package]]
387 | name = "windows_i686_msvc"
388 | version = "0.52.0"
389 | source = "registry+https://github.com/rust-lang/crates.io-index"
390 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
391 |
392 | [[package]]
393 | name = "windows_x86_64_gnu"
394 | version = "0.52.0"
395 | source = "registry+https://github.com/rust-lang/crates.io-index"
396 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
397 |
398 | [[package]]
399 | name = "windows_x86_64_gnullvm"
400 | version = "0.52.0"
401 | source = "registry+https://github.com/rust-lang/crates.io-index"
402 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
403 |
404 | [[package]]
405 | name = "windows_x86_64_msvc"
406 | version = "0.52.0"
407 | source = "registry+https://github.com/rust-lang/crates.io-index"
408 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
409 |
--------------------------------------------------------------------------------