batchfetch 1.2.5__tar.gz → 1.2.6__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.
- {batchfetch-1.2.5 → batchfetch-1.2.6}/PKG-INFO +26 -1
- {batchfetch-1.2.5 → batchfetch-1.2.6}/README.md +25 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch/batchfetch_base.py +2 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch/batchfetch_cli.py +57 -5
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch/batchfetch_git.py +16 -16
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/PKG-INFO +26 -1
- {batchfetch-1.2.5 → batchfetch-1.2.6}/setup.py +1 -1
- {batchfetch-1.2.5 → batchfetch-1.2.6}/LICENSE +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch/__init__.py +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch/helpers.py +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/SOURCES.txt +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/dependency_links.txt +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/entry_points.txt +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/requires.txt +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/batchfetch.egg-info/top_level.txt +0 -0
- {batchfetch-1.2.5 → batchfetch-1.2.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: batchfetch
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: Efficiently clone and pull multiple Git repositories.
|
|
5
5
|
Home-page: https://github.com/jamescherti/batchfetch
|
|
6
6
|
Author: James Cherti
|
|
@@ -89,6 +89,31 @@ options:
|
|
|
89
89
|
-v, --verbose Enable verbose mode.
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
## Frequently Asked Questions
|
|
93
|
+
|
|
94
|
+
### What are untracked files?
|
|
95
|
+
|
|
96
|
+
The parent directory of the "path:" value defines the managed directory, where the directory of each path is considered as the managed directory.
|
|
97
|
+
|
|
98
|
+
For example, if the "path:" value is `file/my-project`, the managed directory will be `file/`. Any file within `file/` that is not managed by batchfetch will be considered an untracked file.
|
|
99
|
+
|
|
100
|
+
When *batchfetch* encounters an untracked file, it displays an error message to inform users about paths that are not managed by the system. The message provides clear instructions on how to handle these paths by adding them to the `options.ignore_untracked_paths` list, enabling users to manage untracked files effectively.
|
|
101
|
+
|
|
102
|
+
Here is an example of a *batchfetch.yaml* file that enables *batchfetch* to accept a list of untracked files:
|
|
103
|
+
|
|
104
|
+
``` yaml
|
|
105
|
+
options:
|
|
106
|
+
ignore_untracked_paths:
|
|
107
|
+
- ./test
|
|
108
|
+
- /absolute/path
|
|
109
|
+
- ../relative/path
|
|
110
|
+
|
|
111
|
+
tasks:
|
|
112
|
+
- git: https://github.com/user/project
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
By default, *batchfetch.yaml* is the only untracked file that is ignored. The user does not need to add it to the *ignore_untracked_paths* option.
|
|
116
|
+
|
|
92
117
|
## License
|
|
93
118
|
|
|
94
119
|
Copyright (C) 2024 [James Cherti](https://www.jamescherti.com)
|
|
@@ -69,6 +69,31 @@ options:
|
|
|
69
69
|
-v, --verbose Enable verbose mode.
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
## Frequently Asked Questions
|
|
73
|
+
|
|
74
|
+
### What are untracked files?
|
|
75
|
+
|
|
76
|
+
The parent directory of the "path:" value defines the managed directory, where the directory of each path is considered as the managed directory.
|
|
77
|
+
|
|
78
|
+
For example, if the "path:" value is `file/my-project`, the managed directory will be `file/`. Any file within `file/` that is not managed by batchfetch will be considered an untracked file.
|
|
79
|
+
|
|
80
|
+
When *batchfetch* encounters an untracked file, it displays an error message to inform users about paths that are not managed by the system. The message provides clear instructions on how to handle these paths by adding them to the `options.ignore_untracked_paths` list, enabling users to manage untracked files effectively.
|
|
81
|
+
|
|
82
|
+
Here is an example of a *batchfetch.yaml* file that enables *batchfetch* to accept a list of untracked files:
|
|
83
|
+
|
|
84
|
+
``` yaml
|
|
85
|
+
options:
|
|
86
|
+
ignore_untracked_paths:
|
|
87
|
+
- ./test
|
|
88
|
+
- /absolute/path
|
|
89
|
+
- ../relative/path
|
|
90
|
+
|
|
91
|
+
tasks:
|
|
92
|
+
- git: https://github.com/user/project
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
By default, *batchfetch.yaml* is the only untracked file that is ignored. The user does not need to add it to the *ignore_untracked_paths* option.
|
|
96
|
+
|
|
72
97
|
## License
|
|
73
98
|
|
|
74
99
|
Copyright (C) 2024 [James Cherti](https://www.jamescherti.com)
|
|
@@ -107,6 +107,7 @@ class TaskBatchFetch(TaskBase):
|
|
|
107
107
|
self.global_options_schema: Dict[Any, Any] = {
|
|
108
108
|
Optional("exec_before"): Or([str], str),
|
|
109
109
|
Optional("exec_after"): Or([str], str),
|
|
110
|
+
Optional("ignore_untracked_paths"): Or([str], str),
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
self.task_schema: Dict[Any, Any] = {
|
|
@@ -120,6 +121,7 @@ class TaskBatchFetch(TaskBase):
|
|
|
120
121
|
self.global_options_values: Dict[str, Any] = {
|
|
121
122
|
"exec_before": [],
|
|
122
123
|
"exec_after": [],
|
|
124
|
+
"ignore_untracked_paths": [],
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
self.task_default_values: Dict[str, Any] = {
|
|
@@ -43,7 +43,8 @@ class BatchFetchCli:
|
|
|
43
43
|
def __init__(self, max_workers: int, verbose: bool = False):
|
|
44
44
|
self.cfg: dict = {}
|
|
45
45
|
self.folder = Path(".")
|
|
46
|
-
self.
|
|
46
|
+
self.tracked_paths: Dict[Path, Set[str]] = {}
|
|
47
|
+
self.ignore_untracked_paths: Set[Path] = set()
|
|
47
48
|
self.verbose = verbose
|
|
48
49
|
self.max_workers = max_workers
|
|
49
50
|
self._logger = logging.getLogger(self.__class__.__name__)
|
|
@@ -97,6 +98,22 @@ class BatchFetchCli:
|
|
|
97
98
|
file=sys.stderr)
|
|
98
99
|
sys.exit(1)
|
|
99
100
|
|
|
101
|
+
self.ignore_untracked_paths.add(Path(path).absolute())
|
|
102
|
+
self.ignore_untracked_paths.add(Path(path).resolve())
|
|
103
|
+
untracked_paths = None
|
|
104
|
+
if "options" in yaml_dict:
|
|
105
|
+
untracked_paths = \
|
|
106
|
+
yaml_dict["options"]["ignore_untracked_paths"]
|
|
107
|
+
|
|
108
|
+
if isinstance(untracked_paths, str):
|
|
109
|
+
untracked_paths = [untracked_paths]
|
|
110
|
+
|
|
111
|
+
if untracked_paths:
|
|
112
|
+
for ignore_untracked_path in untracked_paths:
|
|
113
|
+
self.ignore_untracked_paths.add(
|
|
114
|
+
Path(ignore_untracked_path).absolute()
|
|
115
|
+
)
|
|
116
|
+
|
|
100
117
|
self._loads(dict(yaml_dict))
|
|
101
118
|
except OSError as err:
|
|
102
119
|
raise BatchFetchError(str(err)) from err
|
|
@@ -154,7 +171,7 @@ class BatchFetchCli:
|
|
|
154
171
|
error = False
|
|
155
172
|
threads = []
|
|
156
173
|
num_success = 0
|
|
157
|
-
self.
|
|
174
|
+
self.tracked_paths = {}
|
|
158
175
|
|
|
159
176
|
executor_update = ThreadPoolExecutor(max_workers=self.max_workers)
|
|
160
177
|
|
|
@@ -165,7 +182,15 @@ class BatchFetchCli:
|
|
|
165
182
|
for task in all_tasks:
|
|
166
183
|
self.dirs_relative_to_batchfetch.add(str(task["path"]))
|
|
167
184
|
if not task["delete"]:
|
|
168
|
-
|
|
185
|
+
full_path = Path(task["path"]).absolute()
|
|
186
|
+
base_path = full_path.parent
|
|
187
|
+
try:
|
|
188
|
+
self.tracked_paths[base_path]
|
|
189
|
+
except KeyError:
|
|
190
|
+
self.tracked_paths[base_path] = set()
|
|
191
|
+
|
|
192
|
+
self.tracked_paths[base_path].add(full_path.name)
|
|
193
|
+
|
|
169
194
|
threads.append(executor_update.submit(task.update))
|
|
170
195
|
|
|
171
196
|
for future in as_completed(threads):
|
|
@@ -207,6 +232,8 @@ class BatchFetchCli:
|
|
|
207
232
|
|
|
208
233
|
return False
|
|
209
234
|
else:
|
|
235
|
+
self._find_untracked_paths()
|
|
236
|
+
|
|
210
237
|
if num_success == 0:
|
|
211
238
|
print("Nothing to do.")
|
|
212
239
|
elif not self.verbose:
|
|
@@ -214,11 +241,36 @@ class BatchFetchCli:
|
|
|
214
241
|
|
|
215
242
|
return True
|
|
216
243
|
|
|
244
|
+
def _find_untracked_paths(self):
|
|
245
|
+
"Find the files that are untracked and should be deleted."
|
|
246
|
+
untracked_paths = set()
|
|
247
|
+
for tracked_dir, tracked_filenames in self.tracked_paths.items():
|
|
248
|
+
actual_filenames = {file.name for file in tracked_dir.iterdir()}
|
|
249
|
+
for filename in actual_filenames - tracked_filenames:
|
|
250
|
+
full_path = tracked_dir / filename
|
|
251
|
+
if full_path in self.ignore_untracked_paths:
|
|
252
|
+
continue
|
|
253
|
+
|
|
254
|
+
untracked_paths.add(full_path)
|
|
255
|
+
|
|
256
|
+
if untracked_paths:
|
|
257
|
+
err_str = "The following files need to be deleted:\n"
|
|
258
|
+
for path in untracked_paths:
|
|
259
|
+
err_str += (" - " +
|
|
260
|
+
str(path) +
|
|
261
|
+
("/" if path.is_dir() else "") +
|
|
262
|
+
"\n")
|
|
263
|
+
err_str += ("The paths above are not managed by batchfetch."
|
|
264
|
+
" To retain them, add them to the "
|
|
265
|
+
"options.ignore_untracked_paths list, using either "
|
|
266
|
+
"relative or absolute paths")
|
|
267
|
+
raise BatchFetchError(err_str)
|
|
268
|
+
|
|
217
269
|
|
|
218
270
|
def parse_args():
|
|
219
271
|
"""Parse the command line arguments."""
|
|
220
272
|
desc = __doc__
|
|
221
|
-
usage = "%(prog)s [--option]
|
|
273
|
+
usage = "%(prog)s [--option]"
|
|
222
274
|
parser = argparse.ArgumentParser(description=desc, usage=usage)
|
|
223
275
|
|
|
224
276
|
parser.add_argument("-f",
|
|
@@ -255,8 +307,8 @@ def run_batchfetch_procedure(file: Path, args) -> int:
|
|
|
255
307
|
errno = 0
|
|
256
308
|
batchfetch_cli = BatchFetchCli(verbose=args.verbose,
|
|
257
309
|
max_workers=int(args.jobs))
|
|
258
|
-
batchfetch_cli.load(file)
|
|
259
310
|
os.chdir(file.parent)
|
|
311
|
+
batchfetch_cli.load(file)
|
|
260
312
|
|
|
261
313
|
try:
|
|
262
314
|
if not batchfetch_cli.run_tasks():
|
|
@@ -463,22 +463,22 @@ class BatchFetchGit(TaskBatchFetch):
|
|
|
463
463
|
self._run(cmd, cwd=str(self.git_local_dir), env=self.env)
|
|
464
464
|
self._git_fetch_origin_done = True
|
|
465
465
|
|
|
466
|
-
def _repo_update_submodules(self):
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
466
|
+
# def _repo_update_submodules(self):
|
|
467
|
+
# # This parameter instructs Git to initiate the update
|
|
468
|
+
# # process for submodules:
|
|
469
|
+
# # 1. Git fetches the commits specified in the parent
|
|
470
|
+
# # repository's configuration for each submodule.
|
|
471
|
+
# # 2. Updates are based solely on the commit pointers stored
|
|
472
|
+
# # within the parent repository's submodule configuration.
|
|
473
|
+
# # 3. It does not directly consult the upstream repositories
|
|
474
|
+
# # of the submodules.
|
|
475
|
+
# # 4. Submodules are updated to reflect the exact commits
|
|
476
|
+
# # revision in the parent repository's configuration,
|
|
477
|
+
# # potentially lagging behind the latest changes made in the
|
|
478
|
+
# # upstream repositories.
|
|
479
|
+
# if self.git_local_dir.joinpath(".gitmodules").is_file():
|
|
480
|
+
# cmd = ["git", "submodule", "update", "--recursive"]
|
|
481
|
+
# self._run(cmd, cwd=str(self.git_local_dir), env=self.env)
|
|
482
482
|
|
|
483
483
|
def _repo_fix_remote_origin(self):
|
|
484
484
|
correct_origin_url = self[self.main_key]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: batchfetch
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: Efficiently clone and pull multiple Git repositories.
|
|
5
5
|
Home-page: https://github.com/jamescherti/batchfetch
|
|
6
6
|
Author: James Cherti
|
|
@@ -89,6 +89,31 @@ options:
|
|
|
89
89
|
-v, --verbose Enable verbose mode.
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
## Frequently Asked Questions
|
|
93
|
+
|
|
94
|
+
### What are untracked files?
|
|
95
|
+
|
|
96
|
+
The parent directory of the "path:" value defines the managed directory, where the directory of each path is considered as the managed directory.
|
|
97
|
+
|
|
98
|
+
For example, if the "path:" value is `file/my-project`, the managed directory will be `file/`. Any file within `file/` that is not managed by batchfetch will be considered an untracked file.
|
|
99
|
+
|
|
100
|
+
When *batchfetch* encounters an untracked file, it displays an error message to inform users about paths that are not managed by the system. The message provides clear instructions on how to handle these paths by adding them to the `options.ignore_untracked_paths` list, enabling users to manage untracked files effectively.
|
|
101
|
+
|
|
102
|
+
Here is an example of a *batchfetch.yaml* file that enables *batchfetch* to accept a list of untracked files:
|
|
103
|
+
|
|
104
|
+
``` yaml
|
|
105
|
+
options:
|
|
106
|
+
ignore_untracked_paths:
|
|
107
|
+
- ./test
|
|
108
|
+
- /absolute/path
|
|
109
|
+
- ../relative/path
|
|
110
|
+
|
|
111
|
+
tasks:
|
|
112
|
+
- git: https://github.com/user/project
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
By default, *batchfetch.yaml* is the only untracked file that is ignored. The user does not need to add it to the *ignore_untracked_paths* option.
|
|
116
|
+
|
|
92
117
|
## License
|
|
93
118
|
|
|
94
119
|
Copyright (C) 2024 [James Cherti](https://www.jamescherti.com)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|