Skip to content

Commit

Permalink
Add diff and exclude dir features
Browse files Browse the repository at this point in the history
  • Loading branch information
containerscrew committed Aug 23, 2024
1 parent 59c0963 commit caf6125
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 9 deletions.
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ I have a lot of personal/work repositories in my laptop. Sometimes you jump from

Easy and simple.

# Badges

| | |
|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Language | ![Rust](https://img.shields.io/badge/rust-%23000000.svg?style=for-the-badge&logo=rust&logoColor=white) |
| Release | [![Release](https://img.shields.io/github/release/containerscrew/gitrack)](https://github.com/containerscrew/gitrack/releases/latest) |
| Code | ![Code Size](https://img.shields.io/github/languages/code-size/containerscrew/gitrack) |
| CI - Build | [![Build](https://github.com/containerscrew/gitrack/actions/workflows/build.yml/badge.svg)](https://github.com/containerscrew/gitrack/actions/workflows/build.yml) |
| CI - Release | [![Build](https://github.com/containerscrew/gitrack/actions/workflows/release.yml/badge.svg)](https://github.com/containerscrew/gitrack/actions/workflows/release.yml) |
| CI - Test | [![Build](https://github.com/containerscrew/gitrack/actions/workflows/test.yml/badge.svg)](https://github.com/containerscrew/gitrack/actions/workflows/test.yml) |
| Meta | [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) [![License - MIT](https://img.shields.io/github/license/containerscrew/gitrack)](/LICENSE) |
| Codecov | [![Codecov](https://codecov.io/gh/containerscrew/gitrack/graph/badge.svg?token=4AI2U4PX4V)](https://codecov.io/gh/containerscrew/gitrack) |
| Downloads | [![Downloads](https://img.shields.io/github/downloads/containerscrew/gitrack/total.svg?logo=github)](https://somsubhra.github.io/github-release-stats/?username=containerscrew&repository=gitrack) |

# Supported Platforms

| Arch | ARM64 | AMD64 |
Expand Down Expand Up @@ -76,6 +90,18 @@ Number of workers/threads:
gitrack -p /home/elliot -w 3
```

Diff file changes:

```bash
gitrack -p /home/elliot/gitrack -d # diff is not compatible with -s (summarized)
```

Exclude directories:

```bash
gitrack -p /home/elliot -s -e "/home/elliot/.cache" -e "/home/elliot/.local"
```

# Threads

> The use of threads is not really necessary in this type of tools, unless you have a very large file/folder system. Adding threads does not mean always better performance. I have included them in order to practice their use. **Max 5 threads, default 3**
Expand Down Expand Up @@ -111,8 +137,7 @@ Scan specific folder with details:
# TODO

* Implement git commit scan for sensitive data using regex. Just for fun. Like gitleaks does.
* Support diff files.
* Control threads
* Exclude directories

# Links

Expand Down
19 changes: 19 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,23 @@ pub struct Args {
required = false
)]
pub workers: u16,

#[arg(
short = 'd',
long = "diff",
help = "Show differences between changed files",
default_value_t = false,
required = false
)]
pub diff: bool,

#[arg(
short = 'e',
long = "exclude-dir",
help = "Exclude directories to scan",
value_delimiter = ' ',
num_args = 1..,
required = false
)]
pub exclude: Option<Vec<String>>,
}
53 changes: 49 additions & 4 deletions src/git_ops.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
use git2::{Repository, StatusOptions};
use colored::*;
use git2::{DiffOptions, Repository, StatusOptions};
use std::io;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
use walkdir::{DirEntry, WalkDir};

pub fn find_git_repos(start_path: &Path) -> Vec<PathBuf> {
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();
for entry in WalkDir::new(start_path).into_iter().filter_map(|e| e.ok()) {

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());
}
}

git_repos
}

Expand All @@ -29,3 +42,35 @@ pub fn check_untracked_files(repo_path: &Path) -> Result<Vec<String>, git2::Erro
}
Ok(untracked_files)
}

pub fn show_diff(repo_path: &Path, file: &str) -> io::Result<String> {
let repo = Repository::open(repo_path).expect("Error opening repository");
let mut diff_options = DiffOptions::new();
diff_options.pathspec(file);

let diff = repo
.diff_index_to_workdir(None, Some(&mut diff_options))
.expect("Error diffing");
let mut diff_output = Vec::new();

diff.print(git2::DiffFormat::Patch, |_, _, line| {
let content = String::from_utf8_lossy(line.content()).to_string();
let colored_line = match line.origin() {
'-' => content.red().to_string(), // Deleted lines in red
'+' => content.green().to_string(), // Added lines in green
_ => content, // Unchanged lines
};
diff_output.push(colored_line);
true
})
.expect("Error printing diff");

if !diff_output.is_empty() {
Ok(diff_output.join(""))
} else {
Err(io::Error::new(
ErrorKind::NotFound,
format!("No differences found for {}", file),
))
}
}
18 changes: 15 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::git_ops::{check_untracked_files, find_git_repos};
use crate::git_ops::{check_untracked_files, find_git_repos, show_diff};
use clap::Parser;
use cli::Args;
use colored::*;
Expand Down Expand Up @@ -29,11 +29,17 @@ fn main() {
// Initialize the CLI arguments
let args = Args::parse();

println!("{}", "----->  Starting gitrack  <-----".green());
println!(
"{}",
"----->  Inspecting your untracked local Git files  <-----".green()
);
println_orange!("-----> Scanning {}", args.path);

// Find .git repos in the specified path
let start_path = Path::new(&args.path);
let git_repos = find_git_repos(start_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);

// Create a thread pool with a limited number of threads
let num_threads: usize = args.workers as usize;
Expand Down Expand Up @@ -70,6 +76,12 @@ fn main() {
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),
}
}
}
}
}
Expand Down

0 comments on commit caf6125

Please sign in to comment.