Skip to content

Commit 4113cd7

Browse files
committed
feat: process repositories in parallel
1 parent 6b3993e commit 4113cd7

File tree

5 files changed

+56
-21
lines changed

5 files changed

+56
-21
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Unreleased
44

5-
Nothing Yet!
5+
- Process repositories in parallel
66

77
## Version 0.1.1
88

Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ lto = "thin"
1414
[dependencies]
1515
clap = { version = "4.5.4", features = ["derive", "cargo"] }
1616
ignore = "0.4.22"
17+
rayon = "1.10.0"
1718

1819
[workspace.metadata.dist]
1920
cargo-dist-version = "0.15.1"

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
# git-foreach
22

3-
`git-foreach` is a lightweight utility designed to execute a command in each Git repository within a directory and its
3+
git-foreach is a lightweight utility designed to execute a command in each Git repository within a directory and its
44
subdirectories. It's particularly useful for performing bulk operations, such as `git pull` or `git status`, across
55
multiple repositories simultaneously.
66

77
## Usage
88

9-
The specified `<command>` will be executed in each Git repository found in the current directory and all its
10-
subdirectories.
9+
To use `git-foreach`, simply prepend your desired command with `git-foreach`. The command will be executed in each Git
10+
repository found in the current directory and all its subdirectories.
1111

1212
```shell
1313
git-foreach <command>
1414
```
1515

16+
For instance, if you want to execute git pull in each repository, you would use:
17+
18+
```shell
19+
git-foreach "git pull"
20+
```
21+
22+
By default, git-foreach will stop executing if the command fails in one of the repositories. If you want the execution
23+
to continue despite failures, you can append `|| :` to the command. This will mask the error and allows git-foreach to
24+
continue processing the remaining repositories.
25+
26+
```shell
27+
git-foreach "git pull || :"
28+
```
29+
1630
## Installation
1731

1832
Pre-built binaries are available for Windows, Linux, and macOS. You can download them from

src/main.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use std::env;
55
use std::path::PathBuf;
66

77
use clap::Parser;
8-
use ignore::Walk;
8+
use ignore::{DirEntry, Walk};
9+
use rayon::prelude::*;
910

1011
use crate::error::Error;
1112

@@ -41,12 +42,10 @@ fn main() {
4142
/// subdirectories.
4243
fn repository_foreach<T: Iterator<Item = String>>(args: T) -> Result<(), Error> {
4344
let options = parse_options(args)?;
44-
45-
for repository in find_repositories(&options.directory)? {
46-
run_command_in_directory(&options, &repository)?;
47-
}
48-
49-
Ok(())
45+
find_repositories(&options.directory)
46+
.par_iter()
47+
.map(|repository| run_command_in_directory(&options, repository))
48+
.collect()
5049
}
5150

5251
/// Parse the command line options.
@@ -55,17 +54,11 @@ fn parse_options<T: Iterator<Item = String>>(args: T) -> Result<Options, Error>
5554
}
5655

5756
/// Find all git repositories in a directory and its subdirectories.
58-
fn find_repositories(path: &PathBuf) -> Result<HashSet<PathBuf>, Error> {
57+
fn find_repositories(path: &PathBuf) -> HashSet<PathBuf> {
5958
Walk::new(path)
60-
.filter_map(|entry| {
61-
let entry = entry.ok()?;
62-
let path = entry.path();
63-
if path.is_dir() && path.join(".git").exists() {
64-
Some(Ok(path.to_path_buf()))
65-
} else {
66-
None
67-
}
68-
})
59+
.flatten()
60+
.map(DirEntry::into_path)
61+
.filter(|path| path.is_dir() && path.join(".git").exists())
6962
.collect()
7063
}
7164

0 commit comments

Comments
 (0)