Skip to content

Commit 24836dc

Browse files
committed
gnostr-traverse:initial impl
0 parents  commit 24836dc

File tree

16 files changed

+671
-0
lines changed

16 files changed

+671
-0
lines changed

.github/workflows/ci.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
build:
11+
name: Rust (${{ matrix.rust }}) (${{ matrix.os }})
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os:
17+
- macos-latest
18+
- ubuntu-latest
19+
- windows-latest
20+
rust:
21+
- stable
22+
- beta
23+
- nightly
24+
25+
steps:
26+
- uses: actions/checkout@v2
27+
28+
- uses: actions-rs/toolchain@v1
29+
with:
30+
profile: minimal
31+
toolchain: ${{ matrix.rust }}
32+
override: true
33+
components: rustfmt, clippy
34+
35+
- uses: actions-rs/cargo@v1
36+
with:
37+
command: build
38+
39+
- uses: actions-rs/cargo@v1
40+
with:
41+
command: test
42+
43+
- uses: actions-rs/cargo@v1
44+
with:
45+
command: fmt
46+
args: --all -- --check
47+
48+
- uses: actions-rs/cargo@v1
49+
with:
50+
command: clippy
51+
args: --all --all-features --profile test

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/target
2+
/Cargo.lock
3+
/**/*.rs.bk
4+
.nvmrc
5+
.gnostr/proxy

Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "gnostr-traverse"
3+
version = "0.0.1" # remember to update html_root_url
4+
authors = ["gnostr <[email protected]>", "Isaac Whitfield <[email protected]>"]
5+
description = "walk a directory structure and do something"
6+
repository = "https://github.com/gnostr-org/gnostr-traverse"
7+
keywords = ["backup", "compression", "clean"]
8+
categories = ["algorithms", "command-line-utilities", "filesystem"]
9+
readme = "README.md"
10+
edition = "2021"
11+
license = "MIT"
12+
13+
[dependencies]
14+
clap = "2.33"
15+
walkdir = "2.2"
16+
17+
[profile.release]
18+
codegen-units = 1
19+
opt-level = 3
20+
lto = true

GNUmakefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-:
2+
cargo install --path . && gnostr-clean .

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Isaac Whitfield
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.

README.md

Whitespace-only changes.

src/main.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//! Cleaning of unnecessary files in development directories.
2+
#![doc(html_root_url = "https://docs.rs/detox/0.1.2")]
3+
mod tasks;
4+
mod options;
5+
6+
use walkdir::WalkDir;
7+
8+
use crate::options::Options;
9+
10+
use std::env;
11+
use std::error::Error;
12+
use std::path::Path;
13+
14+
fn main() -> Result<(), Box<dyn Error>> {
15+
// parse in our options from the command line args
16+
let options = Options::from(env::args_os());
17+
18+
// iterate each provided location
19+
for location in &options.locations {
20+
// grab the size of the location before we start
21+
let start = get_size(location);
22+
23+
// iterate all file entries that we come across in the recursive walk
24+
for entry in WalkDir::new(location).into_iter().filter_map(Result::ok) {
25+
// grab the full path
26+
let path = entry.path();
27+
println!("{}", path.display());
28+
29+
// fetch the file name
30+
let segment = path
31+
.file_name()
32+
.unwrap()
33+
.to_str()
34+
.expect("a segment should exist");
35+
36+
// walk through all cleaners
37+
for task in &options.tasks {
38+
// skip if the cleaner doesn't care
39+
if !task.triggers().contains(&segment) {
40+
continue;
41+
}
42+
43+
// grab the dir
44+
let dir = path
45+
.parent()
46+
.unwrap()
47+
.to_str()
48+
.expect("dir should be a str");
49+
50+
// clean the directory
51+
print!("{} ", task.name());
52+
task.job(dir)?;
53+
}
54+
}
55+
56+
// fetch the size of the location when done
57+
let end = get_size(location);
58+
59+
if start >= end {
60+
// output the stats
61+
println!(
62+
"Reduced {} from {} to {} ({:.2}%)",
63+
location.display(),
64+
start,
65+
end,
66+
((start - end) as f64 / start as f64) * 100.0
67+
)
68+
} else if start == end {
69+
println!("No reduction in size!")
70+
} else {
71+
}
72+
}
73+
74+
// done!
75+
Ok(())
76+
}
77+
78+
/// Determines the size of a directory on the filesystem.
79+
fn get_size(path: &Path) -> u64 {
80+
WalkDir::new(path)
81+
.into_iter()
82+
.filter_map(Result::ok)
83+
.filter(|node| node.file_type().is_file())
84+
.filter_map(|file| file.metadata().ok())
85+
.map(|meta| meta.len())
86+
.sum()
87+
}

src/options.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//! Options parsing and configuration for command line interfaces.
2+
use clap::{App, AppSettings, Arg};
3+
use std::ffi::OsString;
4+
use std::path::PathBuf;
5+
6+
use crate::Path;
7+
use crate::tasks::*;
8+
9+
/// Options struct to store configuration state.
10+
pub struct Options {
11+
pub(crate) tasks: Vec<Box<dyn Task>>,
12+
pub(crate) locations: Vec<PathBuf>,
13+
}
14+
15+
impl Options {
16+
/// Creates an `Options` struct from an iterable set of arguments.
17+
pub fn from<I, T>(args: I) -> Options
18+
where
19+
I: IntoIterator<Item = T>,
20+
T: Into<OsString> + Clone,
21+
{
22+
// create a new parser for our args
23+
let parser = Options::create_parser();
24+
25+
// parse out the arguments into matching opts
26+
let options = parser.get_matches_from(args);
27+
28+
// create opts
29+
Options {
30+
tasks: vec![
31+
Box::new(GitTask),
32+
Box::new(GnostrTask),
33+
Box::new(MakeFileTask),
34+
Box::new(NodeTask),
35+
Box::new(CargoTask),
36+
Box::new(MacosTask),
37+
],
38+
locations: options
39+
.values_of("locations")
40+
.unwrap()
41+
.filter_map(|location| PathBuf::from(location).canonicalize().ok())
42+
.collect(),
43+
}
44+
}
45+
46+
/// Creates a parser used to generate `Options`.
47+
fn create_parser<'a, 'b>() -> App<'a, 'b> {
48+
App::new("")
49+
// package metadata from cargo
50+
.name(env!("CARGO_PKG_NAME"))
51+
.about(env!("CARGO_PKG_DESCRIPTION"))
52+
.version(env!("CARGO_PKG_VERSION"))
53+
// arguments and flag details
54+
.args(&[
55+
// inputs: +required +multiple
56+
Arg::with_name("locations")
57+
.help("Locations to search for cleanup")
58+
.multiple(true)
59+
.required(true)
60+
.default_value("."),
61+
])
62+
// settings required for parsing
63+
.settings(&[
64+
AppSettings::ArgRequiredElseHelp,
65+
AppSettings::HidePossibleValuesInHelp,
66+
AppSettings::TrailingVarArg,
67+
])
68+
}
69+
}

0 commit comments

Comments
 (0)