git-rexec 1.0.0__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- git_rexec-1.0.1/.gitignore +6 -0
- {git_rexec-1.0.0 → git_rexec-1.0.1}/PKG-INFO +11 -7
- {git_rexec-1.0.0 → git_rexec-1.0.1}/README.md +10 -6
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git-rexec +109 -42
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git_rexec.egg-info/PKG-INFO +11 -7
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git_rexec.egg-info/SOURCES.txt +1 -0
- {git_rexec-1.0.0 → git_rexec-1.0.1}/pyproject.toml +1 -1
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git_rexec.egg-info/dependency_links.txt +0 -0
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git_rexec.egg-info/requires.txt +0 -0
- {git_rexec-1.0.0 → git_rexec-1.0.1}/git_rexec.egg-info/top_level.txt +0 -0
- {git_rexec-1.0.0 → git_rexec-1.0.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-rexec
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Locate Git repositories and execute commands against them in parallel.
|
|
5
5
|
Author: James Cherti
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -19,7 +19,7 @@ Requires-Dist: setproctitle; extra == "extras"
|
|
|
19
19
|
|
|
20
20
|
# git-rexec: Find Git Repositories and Execute Commands Against Them, either Sequentially or in Parallel
|
|
21
21
|
|
|
22
|
-
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool
|
|
22
|
+
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool recursively locates Git repositories within a directory and executes commands against them, either sequentially or in parallel.
|
|
23
23
|
|
|
24
24
|
Here are examples demonstrating how to use `git-rexec`:
|
|
25
25
|
- Execute `git status -s` across all discovered Git repositories (found by searching recursively under the current working directory) in parallel (`-p` or `--parallel`):
|
|
@@ -32,6 +32,12 @@ Here are examples demonstrating how to use `git-rexec`:
|
|
|
32
32
|
git-rexec -j 5 --parallel -- git fetch
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
|
|
36
|
+
- Include sub-repositories (e.g., Git worktrees and submodules) alongside standard Git repositories during discovery (`-s` or `--include-sub-repos`), and execute `git status` against them:
|
|
37
|
+
```bash
|
|
38
|
+
git-rexec -s -p -- git status
|
|
39
|
+
```
|
|
40
|
+
|
|
35
41
|
- Target a specific base directory (`~/projects`) using the `-C` flag to recursively discover repositories within it, while explicitly excluding a specific subfolder (`~/projects/archive`). This example executes `git status -s` in parallel for all discovered repositories except those within the excluded path:
|
|
36
42
|
```bash
|
|
37
43
|
git-rexec -C ~/projects --exclude-dir ~/projects/archive --parallel -- git status -s
|
|
@@ -47,10 +53,10 @@ If this helps your workflow, please support the project by **⭐ starring git-re
|
|
|
47
53
|
## Features
|
|
48
54
|
|
|
49
55
|
- Recursively discover Git repositories starting from a specified root directory.
|
|
56
|
+
- Optional flag to include sub-repositories (e.g., Git worktrees and submodules) in the execution target list.
|
|
50
57
|
- Execute shell commands across multiple repositories in parallel using worker threads.
|
|
51
58
|
- Filter target repositories based on the exit code of a conditional check (`--if-exec`).
|
|
52
59
|
- Exclude specific directories from the search path.
|
|
53
|
-
- Optional: Can leverage `fd` for fast directory traversal if installed, falling back to standard Python path resolution otherwise.
|
|
54
60
|
|
|
55
61
|
## Installation
|
|
56
62
|
|
|
@@ -67,7 +73,7 @@ sudo cp git-rexec /usr/local/bin/
|
|
|
67
73
|
Install the package directly from the Git repository using `pip`:
|
|
68
74
|
|
|
69
75
|
```bash
|
|
70
|
-
pip install --user git
|
|
76
|
+
pip install --user git-rexec
|
|
71
77
|
```
|
|
72
78
|
|
|
73
79
|
## Dependencies
|
|
@@ -75,7 +81,6 @@ pip install --user git+https://github.com/jamescherti/git-rexec
|
|
|
75
81
|
### System Dependencies
|
|
76
82
|
|
|
77
83
|
- `git`: Required for repository validation and execution.
|
|
78
|
-
- `fd` (Optional): Highly recommended for faster repository discovery.
|
|
79
84
|
|
|
80
85
|
### Python Dependencies (Optional)
|
|
81
86
|
|
|
@@ -86,14 +91,12 @@ You can install the optional Python dependencies via pip:
|
|
|
86
91
|
|
|
87
92
|
```bash
|
|
88
93
|
pip install colorama setproctitle
|
|
89
|
-
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
## Usage
|
|
93
97
|
|
|
94
98
|
```bash
|
|
95
99
|
git-rexec [OPTIONS] [exec_cmd ...]
|
|
96
|
-
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
*(Assuming the `git-rexec` script is executable and in your PATH.)*
|
|
@@ -109,6 +112,7 @@ git-rexec [OPTIONS] [exec_cmd ...]
|
|
|
109
112
|
- `-p, --parallel`: Execute the command in parallel using threads.
|
|
110
113
|
- `-i, --if-exec <command>`: Execute the main command only if this check command returns an exit code of `0`.
|
|
111
114
|
- `-j, --jobs <int>`: The maximum number of concurrent workers/processors to use for parallel execution. Defaults to the number of CPU cores available.
|
|
115
|
+
- `-s, --include-sub-repos`: Include sub-repositories (e.g., Git worktrees and submodules) in the search target list.
|
|
112
116
|
- `-h, --help`: Show the help message and exit.
|
|
113
117
|
- `-q, --quiet`: Quiet mode. Suppresses the informational tracking headers (`[EXEC]` and `[EXEC-P]`) that prefix execution output. In sequential mode, it hides the `[EXEC]` repository delimiter line entirely; in parallel mode (`-p`), it strips the yellow `[EXEC-P]` header track and removes the four-space indentation, printing only the raw, unindented stdout and stderr streams. This flag has no effect when no execution command is supplied, allowing discovered repository paths to print normally.
|
|
114
118
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# git-rexec: Find Git Repositories and Execute Commands Against Them, either Sequentially or in Parallel
|
|
2
2
|
|
|
3
|
-
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool
|
|
3
|
+
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool recursively locates Git repositories within a directory and executes commands against them, either sequentially or in parallel.
|
|
4
4
|
|
|
5
5
|
Here are examples demonstrating how to use `git-rexec`:
|
|
6
6
|
- Execute `git status -s` across all discovered Git repositories (found by searching recursively under the current working directory) in parallel (`-p` or `--parallel`):
|
|
@@ -13,6 +13,12 @@ Here are examples demonstrating how to use `git-rexec`:
|
|
|
13
13
|
git-rexec -j 5 --parallel -- git fetch
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
|
|
17
|
+
- Include sub-repositories (e.g., Git worktrees and submodules) alongside standard Git repositories during discovery (`-s` or `--include-sub-repos`), and execute `git status` against them:
|
|
18
|
+
```bash
|
|
19
|
+
git-rexec -s -p -- git status
|
|
20
|
+
```
|
|
21
|
+
|
|
16
22
|
- Target a specific base directory (`~/projects`) using the `-C` flag to recursively discover repositories within it, while explicitly excluding a specific subfolder (`~/projects/archive`). This example executes `git status -s` in parallel for all discovered repositories except those within the excluded path:
|
|
17
23
|
```bash
|
|
18
24
|
git-rexec -C ~/projects --exclude-dir ~/projects/archive --parallel -- git status -s
|
|
@@ -28,10 +34,10 @@ If this helps your workflow, please support the project by **⭐ starring git-re
|
|
|
28
34
|
## Features
|
|
29
35
|
|
|
30
36
|
- Recursively discover Git repositories starting from a specified root directory.
|
|
37
|
+
- Optional flag to include sub-repositories (e.g., Git worktrees and submodules) in the execution target list.
|
|
31
38
|
- Execute shell commands across multiple repositories in parallel using worker threads.
|
|
32
39
|
- Filter target repositories based on the exit code of a conditional check (`--if-exec`).
|
|
33
40
|
- Exclude specific directories from the search path.
|
|
34
|
-
- Optional: Can leverage `fd` for fast directory traversal if installed, falling back to standard Python path resolution otherwise.
|
|
35
41
|
|
|
36
42
|
## Installation
|
|
37
43
|
|
|
@@ -48,7 +54,7 @@ sudo cp git-rexec /usr/local/bin/
|
|
|
48
54
|
Install the package directly from the Git repository using `pip`:
|
|
49
55
|
|
|
50
56
|
```bash
|
|
51
|
-
pip install --user git
|
|
57
|
+
pip install --user git-rexec
|
|
52
58
|
```
|
|
53
59
|
|
|
54
60
|
## Dependencies
|
|
@@ -56,7 +62,6 @@ pip install --user git+https://github.com/jamescherti/git-rexec
|
|
|
56
62
|
### System Dependencies
|
|
57
63
|
|
|
58
64
|
- `git`: Required for repository validation and execution.
|
|
59
|
-
- `fd` (Optional): Highly recommended for faster repository discovery.
|
|
60
65
|
|
|
61
66
|
### Python Dependencies (Optional)
|
|
62
67
|
|
|
@@ -67,14 +72,12 @@ You can install the optional Python dependencies via pip:
|
|
|
67
72
|
|
|
68
73
|
```bash
|
|
69
74
|
pip install colorama setproctitle
|
|
70
|
-
|
|
71
75
|
```
|
|
72
76
|
|
|
73
77
|
## Usage
|
|
74
78
|
|
|
75
79
|
```bash
|
|
76
80
|
git-rexec [OPTIONS] [exec_cmd ...]
|
|
77
|
-
|
|
78
81
|
```
|
|
79
82
|
|
|
80
83
|
*(Assuming the `git-rexec` script is executable and in your PATH.)*
|
|
@@ -90,6 +93,7 @@ git-rexec [OPTIONS] [exec_cmd ...]
|
|
|
90
93
|
- `-p, --parallel`: Execute the command in parallel using threads.
|
|
91
94
|
- `-i, --if-exec <command>`: Execute the main command only if this check command returns an exit code of `0`.
|
|
92
95
|
- `-j, --jobs <int>`: The maximum number of concurrent workers/processors to use for parallel execution. Defaults to the number of CPU cores available.
|
|
96
|
+
- `-s, --include-sub-repos`: Include sub-repositories (e.g., Git worktrees and submodules) in the search target list.
|
|
93
97
|
- `-h, --help`: Show the help message and exit.
|
|
94
98
|
- `-q, --quiet`: Quiet mode. Suppresses the informational tracking headers (`[EXEC]` and `[EXEC-P]`) that prefix execution output. In sequential mode, it hides the `[EXEC]` repository delimiter line entirely; in parallel mode (`-p`), it strips the yellow `[EXEC-P]` header track and removes the four-space indentation, printing only the raw, unindented stdout and stderr streams. This flag has no effect when no execution command is supplied, allowing discovered repository paths to print normally.
|
|
95
99
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# Author: James Cherti
|
|
8
8
|
# URL: https://github.com/jamescherti/git-rexec
|
|
9
|
+
# Version: 1.0.1
|
|
9
10
|
#
|
|
10
11
|
# Copyright (C) 2019-2026 James Cherti
|
|
11
12
|
#
|
|
@@ -100,51 +101,95 @@ def git_toplevel(repo_path: Path) -> Optional[Path]:
|
|
|
100
101
|
return None
|
|
101
102
|
|
|
102
103
|
|
|
103
|
-
def
|
|
104
|
-
"""
|
|
104
|
+
def git_py_find_repo(root: Path) -> tuple[set[Path], set[Path]]:
|
|
105
|
+
"""Recursively find all Git repositories under the root path using Python.
|
|
106
|
+
|
|
107
|
+
:param root: Directory to search under.
|
|
108
|
+
:return: A tuple containing standard repository paths and sub-repository
|
|
109
|
+
paths.
|
|
110
|
+
"""
|
|
111
|
+
repos: set[Path] = set()
|
|
112
|
+
sub_repos: set[Path] = set()
|
|
105
113
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
114
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
115
|
+
if ".git" in dirnames:
|
|
116
|
+
repos.add(Path(dirpath).absolute())
|
|
117
|
+
elif ".git" in filenames:
|
|
118
|
+
sub_repos.add(Path(dirpath).absolute())
|
|
119
|
+
else:
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# Clear dirnames to prevent os.walk from descending into
|
|
123
|
+
# subdirectories
|
|
124
|
+
dirnames.clear()
|
|
125
|
+
|
|
126
|
+
return repos, sub_repos
|
|
127
|
+
|
|
128
|
+
def get_sub_repos(repo_path: Path) -> set[Path]:
|
|
129
|
+
"""Extract worktrees and submodules from a Git repository.
|
|
130
|
+
|
|
131
|
+
:param repo_path: The path to the standard repository.
|
|
132
|
+
:return: A set of absolute paths to worktrees and submodules.
|
|
109
133
|
"""
|
|
110
|
-
|
|
134
|
+
sub_repos: set[Path] = set()
|
|
135
|
+
|
|
136
|
+
# Discover worktrees
|
|
137
|
+
# pylint: disable=too-many-try-statements
|
|
111
138
|
try:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
[
|
|
115
|
-
'fd', '--type', 'd', '--hidden',
|
|
116
|
-
'--no-ignore', '^\\.git$',
|
|
117
|
-
'--absolute-path',
|
|
118
|
-
'--threads', str(max_workers),
|
|
119
|
-
path_str
|
|
120
|
-
],
|
|
139
|
+
wt_proc: subprocess.CompletedProcess[str] = subprocess.run(
|
|
140
|
+
["git", "-C", str(repo_path), "worktree", "list", "--porcelain"],
|
|
121
141
|
capture_output=True,
|
|
122
142
|
text=True,
|
|
123
|
-
check=
|
|
143
|
+
check=True,
|
|
124
144
|
)
|
|
125
|
-
except FileNotFoundError as err:
|
|
126
|
-
print(f"Error: {err}", file=sys.stderr)
|
|
127
|
-
sys.exit(1)
|
|
128
145
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
Path(git_dir).parent
|
|
133
|
-
for git_dir in proc.stdout.splitlines()
|
|
134
|
-
}
|
|
146
|
+
current_wt: Optional[Path] = None
|
|
147
|
+
is_bare: bool = False
|
|
135
148
|
|
|
149
|
+
for line in wt_proc.stdout.splitlines():
|
|
150
|
+
line = line.strip()
|
|
136
151
|
|
|
137
|
-
|
|
138
|
-
|
|
152
|
+
# Git porcelain separates blocks with a blank line
|
|
153
|
+
if not line:
|
|
154
|
+
if current_wt and not is_bare \
|
|
155
|
+
and current_wt != repo_path.resolve():
|
|
156
|
+
sub_repos.add(current_wt)
|
|
157
|
+
# Reset state for the next block
|
|
158
|
+
current_wt = None
|
|
159
|
+
is_bare = False
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
if line.startswith("worktree "):
|
|
163
|
+
current_wt = Path(line[9:]).resolve()
|
|
164
|
+
elif line == "bare":
|
|
165
|
+
is_bare = True
|
|
166
|
+
|
|
167
|
+
# Process the final block in case the output lacks a trailing newline
|
|
168
|
+
if current_wt and not is_bare and current_wt != repo_path.resolve():
|
|
169
|
+
sub_repos.add(current_wt)
|
|
170
|
+
|
|
171
|
+
except subprocess.CalledProcessError:
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
# Discover submodules
|
|
175
|
+
try:
|
|
176
|
+
sm_proc: subprocess.CompletedProcess[str] = subprocess.run(
|
|
177
|
+
["git", "-C", str(repo_path),
|
|
178
|
+
"submodule", "foreach", "--quiet", "pwd"],
|
|
179
|
+
capture_output=True,
|
|
180
|
+
text=True,
|
|
181
|
+
check=True,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
for line in sm_proc.stdout.splitlines():
|
|
185
|
+
sm_path: Path = Path(line.strip()).resolve()
|
|
186
|
+
sub_repos.add(sm_path)
|
|
187
|
+
|
|
188
|
+
except subprocess.CalledProcessError:
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
return sub_repos
|
|
139
192
|
|
|
140
|
-
:param root: Directory to search under.
|
|
141
|
-
:return: set of paths to Git repositories.
|
|
142
|
-
"""
|
|
143
|
-
return {
|
|
144
|
-
git_dir.absolute().parent
|
|
145
|
-
for git_dir in root.rglob(".git")
|
|
146
|
-
if git_dir.is_dir()
|
|
147
|
-
}
|
|
148
193
|
|
|
149
194
|
|
|
150
195
|
def run_command_get_output(repo_path: Path, cmd_list: list[str],
|
|
@@ -242,24 +287,39 @@ def process_repo(repo_path: Path, exec_parallel_cmd: Optional[list[str]],
|
|
|
242
287
|
|
|
243
288
|
def discover_repos(directory: Path,
|
|
244
289
|
max_workers: int,
|
|
245
|
-
exclude_dirs: list[str]
|
|
246
|
-
|
|
290
|
+
exclude_dirs: list[str],
|
|
291
|
+
include_sub_repos: bool) -> set[Path]:
|
|
292
|
+
"""Discover Git repositories starting from directory and apply exclusions.
|
|
247
293
|
|
|
248
294
|
:param directory: The root directory for search.
|
|
249
295
|
:param max_workers: Maximum number of threads/workers.
|
|
250
296
|
:param exclude_dirs: Directories to exclude.
|
|
297
|
+
:param include_sub_repos: Whether to include sub-repositories.
|
|
251
298
|
:return: A set of repository root paths.
|
|
252
299
|
"""
|
|
253
300
|
repos: set[Path] = set()
|
|
301
|
+
worktrees: set[Path] = set()
|
|
254
302
|
|
|
255
303
|
# Discover all repositories
|
|
256
304
|
toplevel: Optional[Path] = git_toplevel(directory)
|
|
257
305
|
if toplevel:
|
|
258
306
|
repos = {toplevel}
|
|
259
|
-
elif shutil.which("fd"):
|
|
260
|
-
repos = git_fd_find_repo(directory, max_workers)
|
|
261
307
|
else:
|
|
262
|
-
repos = git_py_find_repo(directory)
|
|
308
|
+
repos, worktrees = git_py_find_repo(directory)
|
|
309
|
+
|
|
310
|
+
# Extract and append sub-repositories concurrently if requested
|
|
311
|
+
if include_sub_repos:
|
|
312
|
+
sub_repos: set[Path] = set()
|
|
313
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
314
|
+
futures: list[Future[set[Path]]] = [
|
|
315
|
+
executor.submit(get_sub_repos, repo)
|
|
316
|
+
for repo in repos | worktrees
|
|
317
|
+
]
|
|
318
|
+
for future in as_completed(futures):
|
|
319
|
+
result: set[Path] = future.result()
|
|
320
|
+
sub_repos.update(result)
|
|
321
|
+
|
|
322
|
+
repos.update(sub_repos)
|
|
263
323
|
|
|
264
324
|
# Filter out excluded directories
|
|
265
325
|
if not exclude_dirs:
|
|
@@ -303,7 +363,7 @@ def execute_parallel_tasks(
|
|
|
303
363
|
result: Optional[RepoContext] = future.result()
|
|
304
364
|
if result:
|
|
305
365
|
results.append(result)
|
|
306
|
-
except
|
|
366
|
+
except (OSError, ValueError) as exc:
|
|
307
367
|
print(f"Error processing repository {repo_path}: {exc}",
|
|
308
368
|
file=sys.stderr)
|
|
309
369
|
|
|
@@ -357,6 +417,12 @@ def parse_args() -> argparse.Namespace:
|
|
|
357
417
|
"([EXEC] and [EXEC-P]) that prefix execution output."),
|
|
358
418
|
default=False
|
|
359
419
|
)
|
|
420
|
+
parser.add_argument(
|
|
421
|
+
"-s", "--include-sub-repos",
|
|
422
|
+
action="store_true",
|
|
423
|
+
help="Include sub-repositories (e.g., Git worktrees and submodules)",
|
|
424
|
+
default=False
|
|
425
|
+
)
|
|
360
426
|
parser.add_argument(
|
|
361
427
|
"exec_cmd",
|
|
362
428
|
type=str,
|
|
@@ -428,7 +494,8 @@ def main() -> None:
|
|
|
428
494
|
# Discover Repositories
|
|
429
495
|
repos: set[Path] = discover_repos(args.directory.absolute(),
|
|
430
496
|
args.max_workers,
|
|
431
|
-
args.exclude_dir
|
|
497
|
+
args.exclude_dir,
|
|
498
|
+
args.include_sub_repos)
|
|
432
499
|
|
|
433
500
|
# setup background command list if needed
|
|
434
501
|
exec_parallel_cmd: Optional[list[str]] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-rexec
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Locate Git repositories and execute commands against them in parallel.
|
|
5
5
|
Author: James Cherti
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -19,7 +19,7 @@ Requires-Dist: setproctitle; extra == "extras"
|
|
|
19
19
|
|
|
20
20
|
# git-rexec: Find Git Repositories and Execute Commands Against Them, either Sequentially or in Parallel
|
|
21
21
|
|
|
22
|
-
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool
|
|
22
|
+
The [git-rexec](https://github.com/jamescherti/git-rexec/) command-line tool recursively locates Git repositories within a directory and executes commands against them, either sequentially or in parallel.
|
|
23
23
|
|
|
24
24
|
Here are examples demonstrating how to use `git-rexec`:
|
|
25
25
|
- Execute `git status -s` across all discovered Git repositories (found by searching recursively under the current working directory) in parallel (`-p` or `--parallel`):
|
|
@@ -32,6 +32,12 @@ Here are examples demonstrating how to use `git-rexec`:
|
|
|
32
32
|
git-rexec -j 5 --parallel -- git fetch
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
|
|
36
|
+
- Include sub-repositories (e.g., Git worktrees and submodules) alongside standard Git repositories during discovery (`-s` or `--include-sub-repos`), and execute `git status` against them:
|
|
37
|
+
```bash
|
|
38
|
+
git-rexec -s -p -- git status
|
|
39
|
+
```
|
|
40
|
+
|
|
35
41
|
- Target a specific base directory (`~/projects`) using the `-C` flag to recursively discover repositories within it, while explicitly excluding a specific subfolder (`~/projects/archive`). This example executes `git status -s` in parallel for all discovered repositories except those within the excluded path:
|
|
36
42
|
```bash
|
|
37
43
|
git-rexec -C ~/projects --exclude-dir ~/projects/archive --parallel -- git status -s
|
|
@@ -47,10 +53,10 @@ If this helps your workflow, please support the project by **⭐ starring git-re
|
|
|
47
53
|
## Features
|
|
48
54
|
|
|
49
55
|
- Recursively discover Git repositories starting from a specified root directory.
|
|
56
|
+
- Optional flag to include sub-repositories (e.g., Git worktrees and submodules) in the execution target list.
|
|
50
57
|
- Execute shell commands across multiple repositories in parallel using worker threads.
|
|
51
58
|
- Filter target repositories based on the exit code of a conditional check (`--if-exec`).
|
|
52
59
|
- Exclude specific directories from the search path.
|
|
53
|
-
- Optional: Can leverage `fd` for fast directory traversal if installed, falling back to standard Python path resolution otherwise.
|
|
54
60
|
|
|
55
61
|
## Installation
|
|
56
62
|
|
|
@@ -67,7 +73,7 @@ sudo cp git-rexec /usr/local/bin/
|
|
|
67
73
|
Install the package directly from the Git repository using `pip`:
|
|
68
74
|
|
|
69
75
|
```bash
|
|
70
|
-
pip install --user git
|
|
76
|
+
pip install --user git-rexec
|
|
71
77
|
```
|
|
72
78
|
|
|
73
79
|
## Dependencies
|
|
@@ -75,7 +81,6 @@ pip install --user git+https://github.com/jamescherti/git-rexec
|
|
|
75
81
|
### System Dependencies
|
|
76
82
|
|
|
77
83
|
- `git`: Required for repository validation and execution.
|
|
78
|
-
- `fd` (Optional): Highly recommended for faster repository discovery.
|
|
79
84
|
|
|
80
85
|
### Python Dependencies (Optional)
|
|
81
86
|
|
|
@@ -86,14 +91,12 @@ You can install the optional Python dependencies via pip:
|
|
|
86
91
|
|
|
87
92
|
```bash
|
|
88
93
|
pip install colorama setproctitle
|
|
89
|
-
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
## Usage
|
|
93
97
|
|
|
94
98
|
```bash
|
|
95
99
|
git-rexec [OPTIONS] [exec_cmd ...]
|
|
96
|
-
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
*(Assuming the `git-rexec` script is executable and in your PATH.)*
|
|
@@ -109,6 +112,7 @@ git-rexec [OPTIONS] [exec_cmd ...]
|
|
|
109
112
|
- `-p, --parallel`: Execute the command in parallel using threads.
|
|
110
113
|
- `-i, --if-exec <command>`: Execute the main command only if this check command returns an exit code of `0`.
|
|
111
114
|
- `-j, --jobs <int>`: The maximum number of concurrent workers/processors to use for parallel execution. Defaults to the number of CPU cores available.
|
|
115
|
+
- `-s, --include-sub-repos`: Include sub-repositories (e.g., Git worktrees and submodules) in the search target list.
|
|
112
116
|
- `-h, --help`: Show the help message and exit.
|
|
113
117
|
- `-q, --quiet`: Quiet mode. Suppresses the informational tracking headers (`[EXEC]` and `[EXEC-P]`) that prefix execution output. In sequential mode, it hides the `[EXEC]` repository delimiter line entirely; in parallel mode (`-p`), it strips the yellow `[EXEC-P]` header track and removes the four-space indentation, printing only the raw, unindented stdout and stderr streams. This flag has no effect when no execution command is supplied, allowing discovered repository paths to print normally.
|
|
114
118
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|