Skip to content

Commit

Permalink
Reimplementing directories scan
Browse files Browse the repository at this point in the history
  • Loading branch information
containerscrew committed Aug 23, 2024
1 parent 7a80e03 commit 6619afb
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 66 deletions.
11 changes: 9 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pub struct Args {
short = 'w',
long = "workers",
help = "Number of threads to use for scanning repositories",
default_value_t = 3,
value_parser(clap::value_parser!(u16).range(1..=5)),
default_value_t = 5,
value_parser(clap::value_parser!(u16).range(1..=10)),
required = false
)]
pub workers: u16,
Expand All @@ -56,4 +56,11 @@ pub struct Args {
required = false
)]
pub exclude: Option<Vec<String>>,

#[arg(
long = "scan-all",
help = "Scan all git repos, with or without untracked files",
required = false
)]
pub scan_all: bool,
}
42 changes: 31 additions & 11 deletions src/git_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,47 @@ use git2::{DiffOptions, Repository, StatusOptions};
use std::io;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use std::sync::mpsc;
use std::sync::mpsc::Sender;
use threadpool::ThreadPool;
use walkdir::{DirEntry, WalkDir};

// Check if a directory should be excluded
fn is_excluded_dir(entry: &DirEntry, exclude_dirs: &[String]) -> bool {
exclude_dirs.iter().any(|dir| entry.path().starts_with(dir))
}

pub fn find_git_repos(start_path: &Path, exclude_dirs: &[String]) -> Vec<PathBuf> {
let mut git_repos = Vec::new();
// Send the path to the channel if it is a Git repository
fn check_and_send_repo(path: PathBuf, tx: Sender<PathBuf>) {
if path.join(".git").exists() {
tx.send(path).unwrap();
}
}

for entry in WalkDir::new(start_path)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| !is_excluded_dir(e, exclude_dirs))
{
let path = entry.path();
if path.is_dir() && path.join(".git").exists() {
git_repos.push(path.to_path_buf());
// Find Git repositories starting from a given directory using a ThreadPool
pub fn find_git_repos(
start_path: &Path,
exclude_dirs: &[String],
num_threads: usize,
) -> Vec<PathBuf> {
let pool = ThreadPool::new(num_threads); // Create a thread pool with the specified number of threads
let (tx, rx) = mpsc::channel(); // Create a channel to send results from threads to the main thread

// Iterate over all entries in the starting path
for entry in WalkDir::new(start_path).into_iter().filter_map(|e| e.ok()) {
let path = entry.path().to_path_buf();
if path.is_dir() && !is_excluded_dir(&entry, exclude_dirs) {
let tx = tx.clone(); // Clone the sender to be used in the thread
pool.execute(move || {
check_and_send_repo(path, tx); // Check if the directory is a Git repository and send the path if it is
});
}
}

git_repos
drop(tx); // Close the sender side of the channel to indicate no more sends

// Collect all the paths from the receiver into a vector
rx.into_iter().collect()
}

pub fn check_untracked_files(repo_path: &Path) -> Result<Vec<String>, git2::Error> {
Expand Down
100 changes: 47 additions & 53 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,58 +39,52 @@ fn main() {
let start_path = Path::new(&args.path);
// If user not specify exclude dirs, set it to empty
let exclude_dirs = args.exclude.as_deref().unwrap_or(&[]);
let git_repos = find_git_repos(start_path, exclude_dirs);
let git_repos = find_git_repos(start_path, &exclude_dirs, args.workers as usize);

// Create a thread pool with a limited number of threads
let num_threads: usize = args.workers as usize;
let pool = ThreadPool::new(num_threads);

// Create a channel to send the results back to the main thread
let (tx, rx) = mpsc::channel();

// Spawn a thread for each repo to check for untracked files
for repo_path in git_repos {
let tx = tx.clone();
let repo_path = repo_path.clone();
pool.execute(move || {
match check_untracked_files(&repo_path) {
Ok(untracked_files) => {
if !untracked_files.is_empty() {
// Send the results back to the main thread
tx.send((repo_path.clone(), untracked_files)).unwrap();
}
}
Err(e) => eprintln!("{}: {}", "Error checking repository".red(), e),
}
});
}

// Close the sending side of the channel
drop(tx);

// Print the results as they arrive
let mut has_results = false;
while let Ok((repo_path, untracked_files)) = rx.recv() {
has_results = true;
println_orange!("Untracked files in: {}", repo_path.display());
if !args.summary {
for file in untracked_files {
println_light_orange!(" - {}", file);
if args.diff {
match show_diff(&repo_path, &file) {
Ok(diff) => println!("{}", diff),
Err(e) => eprintln!("{}: {}", "Error showing diff".red(), e),
}
}
}
}
}

// Print a message if no results were found
if !has_results {
println_orange!(
"-----> There are no changes to git in {}",
start_path.display()
);
}
//
// // Spawn a thread for each repo to check for untracked files
// for repo_path in git_repos {
// let tx = tx.clone();
// let repo_path = repo_path.clone();
// pool.execute(move || {
// match check_untracked_files(&repo_path) {
// Ok(untracked_files) => {
// if !untracked_files.is_empty() {
// // Send the results back to the main thread
// tx.send((repo_path.clone(), untracked_files)).unwrap();
// }
// }
// Err(e) => eprintln!("{}: {}", "Error checking repository".red(), e),
// }
// });
// }
//
// // Close the sending side of the channel
// drop(tx);
//
// // Print the results as they arrive
// let mut has_results = false;
// while let Ok((repo_path, untracked_files)) = rx.recv() {
// has_results = true;
// println_orange!("Untracked files in: {}", repo_path.display());
// if !args.summary {
// for file in untracked_files {
// println_light_orange!(" - {}", file);
// if args.diff {
// match show_diff(&repo_path, &file) {
// Ok(diff) => println!("{}", diff),
// Err(e) => eprintln!("{}: {}", "Error showing diff".red(), e),
// }
// }
// }
// }
// }
//
// // Print a message if no results were found
// if !has_results {
// println_orange!(
// "-----> There are no changes to git in {}",
// start_path.display()
// );
// }
}

0 comments on commit 6619afb

Please sign in to comment.