Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/crufty.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod artifact_type;
pub mod cleaner;
pub mod cli;
pub mod estimator;
Expand Down
21 changes: 21 additions & 0 deletions src/crufty/artifact_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[derive(Debug, Clone)]
#[allow(dead_code)]
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Custom is used only in tests currently, thus dead code allowed (for now)

pub enum ArtifactType {
Rust,
Scala,
Custom { pattern: &'static str },
}

pub fn builtin() -> [ArtifactType; 2] {
[ArtifactType::Rust, ArtifactType::Scala]
}

impl ArtifactType {
pub fn pattern(&self) -> &'static str {
match self {
ArtifactType::Rust => "**/target",
ArtifactType::Scala => "**/target",
ArtifactType::Custom { pattern } => pattern,
}
}
}
88 changes: 61 additions & 27 deletions src/crufty/fetcher.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,56 @@
use std::path::PathBuf;

use globset::{Glob, GlobSetBuilder};
use super::artifact_type::ArtifactType;
use globset::{Glob, GlobSet, GlobSetBuilder};
use walkdir::WalkDir;

use super::types::ArtifactCandidate;

pub fn fetch_artifacts(root_path: &PathBuf) -> Vec<ArtifactCandidate> {
fn mk_global_set(
artifact_types: Vec<ArtifactType>,
) -> Result<GlobSet, globset::Error> {
let mut builder = GlobSetBuilder::new();
// FIX-ME hardcoded pattern for Rust
builder.add(Glob::new("**/target").unwrap());

let globset = builder.build().unwrap();

WalkDir::new(root_path)
.into_iter()
.filter_map(|entry_result| match entry_result {
Err(_) => None,
Ok(entry) if !entry.path().is_dir() => None,
Ok(entry) => {
let path = entry.into_path();
let rel_path = path.strip_prefix(root_path).ok()?;
match globset.is_match(&rel_path) {
true => Some(ArtifactCandidate::new(path)),
false => None,
for art_type in artifact_types {
builder.add(Glob::new(art_type.pattern())?);
}
builder.build()
}

pub fn fetch_artifacts(
root_path: &PathBuf,
artifact_types: Vec<ArtifactType>,
) -> Vec<ArtifactCandidate> {
match mk_global_set(artifact_types) {
Err(_) => vec![],
Ok(globset) => WalkDir::new(root_path)
.into_iter()
.filter_map(|entry_result| match entry_result {
Err(_) => None,
Ok(entry) if !entry.path().is_dir() => None,
Ok(entry) => {
let path = entry.into_path();
let rel_path = path.strip_prefix(root_path).ok()?;
match globset.is_match(&rel_path) {
true => Some(ArtifactCandidate::new(path)),
false => None,
}
}
}
})
.collect()
})
.collect(),
}
}

#[cfg(test)]
mod tests {

use assert_fs::prelude::*;
use assert_fs::{
fixture::{ChildPath, PathChild},
prelude::*,
TempDir,
};

use crate::crufty::artifact_type::ArtifactType;

use super::{fetch_artifacts, ArtifactCandidate};

fn mk_subpath(base: &TempDir, rel_path: &str) -> ChildPath {
Expand All @@ -46,19 +59,27 @@ mod tests {
sub
}

fn only_rust_projects() -> Vec<ArtifactType> {
vec![ArtifactType::Rust]
}

fn custom_project(pattern: &'static str) -> Vec<ArtifactType> {
vec![ArtifactType::Custom { pattern }]
}

fn mk_rust_project<P: PathChild>(base: &P) {
base.child("target").create_dir_all().unwrap();
base.child("Cargo.toml").touch().unwrap();
}

#[test]
fn test_simple_rust_project_being_scanned_folder() {
// given
// given there is a single rust project in the folder
let temp = TempDir::new().unwrap();
mk_rust_project(&temp);

// when
let results = fetch_artifacts(&temp.to_path_buf());
// when we search for Rust artifacts
let results = fetch_artifacts(&temp.to_path_buf(), only_rust_projects());

// then
assert_eq!(results.len(), 1, "Expected exactly one artifact");
Expand All @@ -67,6 +88,12 @@ mod tests {
let expected = ArtifactCandidate::new(expected_path);
assert_eq!(&results[0], &expected);

// when we search for projects other than Rust
let results =
fetch_artifacts(&temp.to_path_buf(), custom_project("**/bla"));
// then
assert_eq!(results.len(), 0, "Expected zero artifacts");

temp.close().unwrap();
}

Expand All @@ -81,8 +108,9 @@ mod tests {
let project3 = mk_subpath(&temp, "work/project3");
mk_rust_project(&project3);

// when
let mut results = fetch_artifacts(&temp.to_path_buf());
// when we search for Rust artifacts
let mut results =
fetch_artifacts(&temp.to_path_buf(), only_rust_projects());

// then
assert_eq!(results.len(), 3, "Expected exactly three artifacts");
Expand All @@ -107,6 +135,12 @@ mod tests {
let expected_3 = ArtifactCandidate::new(expected_path_3);
assert_eq!(&results[2], &expected_3);

// when we search for projects other than Rust
let results =
fetch_artifacts(&temp.to_path_buf(), custom_project("**/bla"));
// then
assert_eq!(results.len(), 0, "Expected zero artifacts");

temp.close().unwrap();
}
}
5 changes: 3 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use clap::Parser;
use console::{style, Term};
use crufty::artifact_type;
use crufty::cleaner::{self, CleanupResult};
use crufty::cli::{Cli, Commands};
use crufty::estimator::{estimate, total_size};
Expand Down Expand Up @@ -34,7 +35,7 @@ fn scan() -> io::Result<()> {
.write_line(&format!("[+] Scanning: {}", style(path.display()).bold()))?;

let spinner = ui::create_spinner("collecting artifacts");
let mut artifacts = fetch_artifacts(&path);
let mut artifacts = fetch_artifacts(&path, artifact_type::builtin().to_vec());
spinner.finish_and_clear();

term.write_line("")?;
Expand Down Expand Up @@ -82,7 +83,7 @@ fn clean() -> io::Result<()> {
let path = env::current_dir()?;

let spinner = ui::create_spinner("collecting artifacts");
let mut artifacts = fetch_artifacts(&path);
let mut artifacts = fetch_artifacts(&path, artifact_type::builtin().to_vec());
spinner.finish_and_clear();

if artifacts.is_empty() {
Expand Down