batchfetch 1.3.6__tar.gz → 1.3.8__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.3.6 → batchfetch-1.3.8}/PKG-INFO +60 -10
- {batchfetch-1.3.6 → batchfetch-1.3.8}/README.md +59 -9
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch/__init__.py +1 -1
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch/batchfetch_base.py +51 -30
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch/batchfetch_cli.py +50 -36
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch/batchfetch_git.py +218 -61
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch/helpers.py +24 -22
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/PKG-INFO +60 -10
- {batchfetch-1.3.6 → batchfetch-1.3.8}/setup.py +2 -2
- {batchfetch-1.3.6 → batchfetch-1.3.8}/tests/test_helpers.py +1 -1
- {batchfetch-1.3.6 → batchfetch-1.3.8}/LICENSE +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/SOURCES.txt +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/dependency_links.txt +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/entry_points.txt +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/requires.txt +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/batchfetch.egg-info/top_level.txt +0 -0
- {batchfetch-1.3.6 → batchfetch-1.3.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batchfetch
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.8
|
|
4
4
|
Summary: Efficiently clone and pull multiple Git repositories.
|
|
5
5
|
Home-page: https://github.com/jamescherti/batchfetch
|
|
6
6
|
Author: James Cherti
|
|
@@ -80,7 +80,7 @@ tasks:
|
|
|
80
80
|
delete: true
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
Execute the `batchfetch` command from the same directory as `batchfetch.
|
|
83
|
+
Execute the `batchfetch` command from the same directory as `batchfetch.yaml` to make it clone or update the local copies of the repositories above.
|
|
84
84
|
|
|
85
85
|
## Command-line options
|
|
86
86
|
|
|
@@ -94,7 +94,7 @@ Efficiently clone/pull multiple Git repositories in parallel.
|
|
|
94
94
|
positional arguments:
|
|
95
95
|
target This is a target path that batchfetch is supposed to
|
|
96
96
|
handle. When no target is specified, execute the tasks
|
|
97
|
-
of all target paths defined in the batchfetch.
|
|
97
|
+
of all target paths defined in the batchfetch.yaml list
|
|
98
98
|
of tasks.
|
|
99
99
|
|
|
100
100
|
options:
|
|
@@ -117,6 +117,7 @@ options:
|
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
## Features
|
|
120
|
+
|
|
120
121
|
- Git Clone and Fetch/Merge: Clones the repositories and their submodules, ensuring that all the repositories are always up-to-date by fetching and merging changes.
|
|
121
122
|
- Parallel Operations: Utilizes threads to simultaneously Git clone or pull multiple repositories, dramatically reducing wait times.
|
|
122
123
|
- User-Friendly Interface: Provides simple and straightforward command-line options that make it easy to get started and effectively manage your repositories.
|
|
@@ -135,7 +136,7 @@ When *batchfetch* encounters an untracked file, it displays an error message to
|
|
|
135
136
|
|
|
136
137
|
Here is an example of a *batchfetch.yaml* file that enables *batchfetch* to accept a list of untracked files:
|
|
137
138
|
|
|
138
|
-
```
|
|
139
|
+
```yaml
|
|
139
140
|
options:
|
|
140
141
|
ignore_untracked:
|
|
141
142
|
- ./test
|
|
@@ -161,7 +162,8 @@ Batchfetch is fast, not only because it runs Git commands in parallel, but also
|
|
|
161
162
|
When the user has specifies a revision (branch or commit reference), Batchfetch only performs a `git fetch` if that revision does not exist locally. If the revision is already up to date, it simply proceeds to the next repository in the queue.
|
|
162
163
|
|
|
163
164
|
That's why it is highly recommended to always specify the revision to speed up Batchfetch, if speed is important to you. Here is an example of a `batchfetch.yaml` file where the branch (`1.1.0`) or commit reference (`b9c6d9b6134b4981760893254f804a371ffbc899`) is specified:
|
|
164
|
-
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
165
167
|
tasks:
|
|
166
168
|
- git: https://github.com/jamescherti/outline-indent.el
|
|
167
169
|
revision: "1.1.0"
|
|
@@ -171,12 +173,59 @@ tasks:
|
|
|
171
173
|
revision: b9c6d9b6134b4981760893254f804a371ffbc899
|
|
172
174
|
```
|
|
173
175
|
|
|
176
|
+
### How to customize Git clone, merge, and update strategies?
|
|
177
|
+
|
|
178
|
+
Batchfetch allows you to define advanced options for interacting with Git repositories. These parameters can be declared globally under the `options` block to apply to all tasks, or individually within a specific task to override the global defaults.
|
|
179
|
+
|
|
180
|
+
* `git_clone_args`: A list of extra arguments to pass to `git clone`.
|
|
181
|
+
* `git_merge_args`: A list of extra arguments to pass to `git merge`.
|
|
182
|
+
* `git_update_strategy`: Specifies how updates should be applied. Valid options are `"merge"` (default), `"rebase"`, or `"reset"`.
|
|
183
|
+
* `git_pull`: A boolean indicating whether to run Git pull/fetch operations. Set to `false` to disable updating entirely (default: `true`).
|
|
184
|
+
|
|
185
|
+
Here is an example demonstrating both global and local configurations:
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
options:
|
|
191
|
+
# Apply these defaults to all tasks
|
|
192
|
+
git_update_strategy: reset
|
|
193
|
+
git_clone_args:
|
|
194
|
+
- --recurse-submodules
|
|
195
|
+
|
|
196
|
+
tasks:
|
|
197
|
+
- git: https://github.com/jamescherti/compile-angel.el
|
|
198
|
+
git_pull: false # Do not attempt to update this repo
|
|
199
|
+
|
|
200
|
+
- git: https://github.com/jamescherti/outline-indent.el
|
|
201
|
+
# Override global strategy specifically for this task
|
|
202
|
+
git_update_strategy: merge
|
|
203
|
+
git_merge_args:
|
|
204
|
+
- --no-ff
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### How to configure additional Git remotes?
|
|
209
|
+
|
|
210
|
+
You can define additional remotes for a Git repository using the `remote` option. Pass a list of key-value pairs where the key is the remote name and the value is the corresponding URL. Batchfetch will automatically ensure these remotes are present and point to the correct URLs.
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
---
|
|
214
|
+
tasks:
|
|
215
|
+
- git: https://github.com/jamescherti/easysession.el
|
|
216
|
+
path: emacs/easysession
|
|
217
|
+
remote:
|
|
218
|
+
upstream: https://github.com/name/repo
|
|
219
|
+
upstream2: https://github.com/name/repo2
|
|
220
|
+
```
|
|
221
|
+
|
|
174
222
|
### How to execute a command before and after a task?
|
|
175
223
|
|
|
176
224
|
To execute a command both before and after a specific task, you can define the `exec_before` and `exec_after` directives within the task configuration. These directives specify commands to be executed at the respective stages of the task lifecycle.
|
|
177
225
|
|
|
178
226
|
Here is an example:
|
|
179
|
-
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
180
229
|
---
|
|
181
230
|
tasks:
|
|
182
231
|
- git: https://github.com/jamescherti/easysession.el
|
|
@@ -187,11 +236,12 @@ tasks:
|
|
|
187
236
|
|
|
188
237
|
### How to make batchfetch handle only one path?
|
|
189
238
|
|
|
190
|
-
To configure `batchfetch` to handle a specific path, you can define your tasks in a `batchfetch.
|
|
239
|
+
To configure `batchfetch` to handle a specific path, you can define your tasks in a `batchfetch.yaml` file and pass the desired path as an argument to the `batchfetch` command.
|
|
191
240
|
|
|
192
|
-
#### Example `batchfetch.
|
|
241
|
+
#### Example `batchfetch.yaml` file:
|
|
193
242
|
|
|
194
243
|
In the following example, the `easysession` task clones two Git repositories:
|
|
244
|
+
|
|
195
245
|
```yaml
|
|
196
246
|
---
|
|
197
247
|
tasks:
|
|
@@ -208,7 +258,7 @@ To make `batchfetch` clone only `easysession`, pass its path as an argument:
|
|
|
208
258
|
batchfetch easysession
|
|
209
259
|
```
|
|
210
260
|
|
|
211
|
-
This will execute only the task corresponding to the `easysession` path, skipping all others in the `batchfetch.
|
|
261
|
+
This will execute only the task corresponding to the `easysession` path, skipping all others in the `batchfetch.yaml` file.
|
|
212
262
|
|
|
213
263
|
### How can I configure batchfetch to load a file other than batchfetch.yaml?
|
|
214
264
|
|
|
@@ -227,7 +277,7 @@ batchfetch
|
|
|
227
277
|
|
|
228
278
|
## License
|
|
229
279
|
|
|
230
|
-
Copyright (C) 2024-
|
|
280
|
+
Copyright (C) 2024-2026 [James Cherti](https://www.jamescherti.com)
|
|
231
281
|
|
|
232
282
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
233
283
|
|
|
@@ -46,7 +46,7 @@ tasks:
|
|
|
46
46
|
delete: true
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
Execute the `batchfetch` command from the same directory as `batchfetch.
|
|
49
|
+
Execute the `batchfetch` command from the same directory as `batchfetch.yaml` to make it clone or update the local copies of the repositories above.
|
|
50
50
|
|
|
51
51
|
## Command-line options
|
|
52
52
|
|
|
@@ -60,7 +60,7 @@ Efficiently clone/pull multiple Git repositories in parallel.
|
|
|
60
60
|
positional arguments:
|
|
61
61
|
target This is a target path that batchfetch is supposed to
|
|
62
62
|
handle. When no target is specified, execute the tasks
|
|
63
|
-
of all target paths defined in the batchfetch.
|
|
63
|
+
of all target paths defined in the batchfetch.yaml list
|
|
64
64
|
of tasks.
|
|
65
65
|
|
|
66
66
|
options:
|
|
@@ -83,6 +83,7 @@ options:
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
## Features
|
|
86
|
+
|
|
86
87
|
- Git Clone and Fetch/Merge: Clones the repositories and their submodules, ensuring that all the repositories are always up-to-date by fetching and merging changes.
|
|
87
88
|
- Parallel Operations: Utilizes threads to simultaneously Git clone or pull multiple repositories, dramatically reducing wait times.
|
|
88
89
|
- User-Friendly Interface: Provides simple and straightforward command-line options that make it easy to get started and effectively manage your repositories.
|
|
@@ -101,7 +102,7 @@ When *batchfetch* encounters an untracked file, it displays an error message to
|
|
|
101
102
|
|
|
102
103
|
Here is an example of a *batchfetch.yaml* file that enables *batchfetch* to accept a list of untracked files:
|
|
103
104
|
|
|
104
|
-
```
|
|
105
|
+
```yaml
|
|
105
106
|
options:
|
|
106
107
|
ignore_untracked:
|
|
107
108
|
- ./test
|
|
@@ -127,7 +128,8 @@ Batchfetch is fast, not only because it runs Git commands in parallel, but also
|
|
|
127
128
|
When the user has specifies a revision (branch or commit reference), Batchfetch only performs a `git fetch` if that revision does not exist locally. If the revision is already up to date, it simply proceeds to the next repository in the queue.
|
|
128
129
|
|
|
129
130
|
That's why it is highly recommended to always specify the revision to speed up Batchfetch, if speed is important to you. Here is an example of a `batchfetch.yaml` file where the branch (`1.1.0`) or commit reference (`b9c6d9b6134b4981760893254f804a371ffbc899`) is specified:
|
|
130
|
-
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
131
133
|
tasks:
|
|
132
134
|
- git: https://github.com/jamescherti/outline-indent.el
|
|
133
135
|
revision: "1.1.0"
|
|
@@ -137,12 +139,59 @@ tasks:
|
|
|
137
139
|
revision: b9c6d9b6134b4981760893254f804a371ffbc899
|
|
138
140
|
```
|
|
139
141
|
|
|
142
|
+
### How to customize Git clone, merge, and update strategies?
|
|
143
|
+
|
|
144
|
+
Batchfetch allows you to define advanced options for interacting with Git repositories. These parameters can be declared globally under the `options` block to apply to all tasks, or individually within a specific task to override the global defaults.
|
|
145
|
+
|
|
146
|
+
* `git_clone_args`: A list of extra arguments to pass to `git clone`.
|
|
147
|
+
* `git_merge_args`: A list of extra arguments to pass to `git merge`.
|
|
148
|
+
* `git_update_strategy`: Specifies how updates should be applied. Valid options are `"merge"` (default), `"rebase"`, or `"reset"`.
|
|
149
|
+
* `git_pull`: A boolean indicating whether to run Git pull/fetch operations. Set to `false` to disable updating entirely (default: `true`).
|
|
150
|
+
|
|
151
|
+
Here is an example demonstrating both global and local configurations:
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
options:
|
|
157
|
+
# Apply these defaults to all tasks
|
|
158
|
+
git_update_strategy: reset
|
|
159
|
+
git_clone_args:
|
|
160
|
+
- --recurse-submodules
|
|
161
|
+
|
|
162
|
+
tasks:
|
|
163
|
+
- git: https://github.com/jamescherti/compile-angel.el
|
|
164
|
+
git_pull: false # Do not attempt to update this repo
|
|
165
|
+
|
|
166
|
+
- git: https://github.com/jamescherti/outline-indent.el
|
|
167
|
+
# Override global strategy specifically for this task
|
|
168
|
+
git_update_strategy: merge
|
|
169
|
+
git_merge_args:
|
|
170
|
+
- --no-ff
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### How to configure additional Git remotes?
|
|
175
|
+
|
|
176
|
+
You can define additional remotes for a Git repository using the `remote` option. Pass a list of key-value pairs where the key is the remote name and the value is the corresponding URL. Batchfetch will automatically ensure these remotes are present and point to the correct URLs.
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
---
|
|
180
|
+
tasks:
|
|
181
|
+
- git: https://github.com/jamescherti/easysession.el
|
|
182
|
+
path: emacs/easysession
|
|
183
|
+
remote:
|
|
184
|
+
upstream: https://github.com/name/repo
|
|
185
|
+
upstream2: https://github.com/name/repo2
|
|
186
|
+
```
|
|
187
|
+
|
|
140
188
|
### How to execute a command before and after a task?
|
|
141
189
|
|
|
142
190
|
To execute a command both before and after a specific task, you can define the `exec_before` and `exec_after` directives within the task configuration. These directives specify commands to be executed at the respective stages of the task lifecycle.
|
|
143
191
|
|
|
144
192
|
Here is an example:
|
|
145
|
-
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
146
195
|
---
|
|
147
196
|
tasks:
|
|
148
197
|
- git: https://github.com/jamescherti/easysession.el
|
|
@@ -153,11 +202,12 @@ tasks:
|
|
|
153
202
|
|
|
154
203
|
### How to make batchfetch handle only one path?
|
|
155
204
|
|
|
156
|
-
To configure `batchfetch` to handle a specific path, you can define your tasks in a `batchfetch.
|
|
205
|
+
To configure `batchfetch` to handle a specific path, you can define your tasks in a `batchfetch.yaml` file and pass the desired path as an argument to the `batchfetch` command.
|
|
157
206
|
|
|
158
|
-
#### Example `batchfetch.
|
|
207
|
+
#### Example `batchfetch.yaml` file:
|
|
159
208
|
|
|
160
209
|
In the following example, the `easysession` task clones two Git repositories:
|
|
210
|
+
|
|
161
211
|
```yaml
|
|
162
212
|
---
|
|
163
213
|
tasks:
|
|
@@ -174,7 +224,7 @@ To make `batchfetch` clone only `easysession`, pass its path as an argument:
|
|
|
174
224
|
batchfetch easysession
|
|
175
225
|
```
|
|
176
226
|
|
|
177
|
-
This will execute only the task corresponding to the `easysession` path, skipping all others in the `batchfetch.
|
|
227
|
+
This will execute only the task corresponding to the `easysession` path, skipping all others in the `batchfetch.yaml` file.
|
|
178
228
|
|
|
179
229
|
### How can I configure batchfetch to load a file other than batchfetch.yaml?
|
|
180
230
|
|
|
@@ -193,7 +243,7 @@ batchfetch
|
|
|
193
243
|
|
|
194
244
|
## License
|
|
195
245
|
|
|
196
|
-
Copyright (C) 2024-
|
|
246
|
+
Copyright (C) 2024-2026 [James Cherti](https://www.jamescherti.com)
|
|
197
247
|
|
|
198
248
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
199
249
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2024-
|
|
3
|
+
# Copyright (C) 2024-2026 James Cherti
|
|
4
4
|
# URL: https://github.com/jamescherti/batchfetch
|
|
5
5
|
#
|
|
6
6
|
# This program is free software: you can redistribute it and/or modify it under
|
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
# You should have received a copy of the GNU General Public License along with
|
|
17
17
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
18
|
#
|
|
19
|
-
"Base class used to run tasks in parallel."
|
|
19
|
+
"""Base class used to run tasks in parallel."""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
20
22
|
|
|
21
23
|
import os
|
|
22
24
|
from copy import deepcopy
|
|
23
25
|
from pathlib import Path
|
|
24
|
-
from typing import Any
|
|
26
|
+
from typing import Any
|
|
25
27
|
|
|
26
28
|
from schema import Optional, Or, Schema
|
|
27
29
|
|
|
@@ -29,7 +31,7 @@ from .helpers import run_indent_str
|
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
class BatchFetchError(Exception):
|
|
32
|
-
"""Exception raised by
|
|
34
|
+
"""Exception raised by batchfetch functions."""
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
class DataAlreadyInitialized(Exception):
|
|
@@ -37,21 +39,25 @@ class DataAlreadyInitialized(Exception):
|
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
class TaskBase:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
"""Base class representing a general task to be executed."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, data: dict[str, Any], options: dict[str, Any]) -> None:
|
|
45
|
+
"""Initialize the task with specific data and options."""
|
|
46
|
+
self.global_options_schema: dict[Any, Any] = {}
|
|
47
|
+
self.global_options_values: dict[str, Any] = options
|
|
43
48
|
|
|
44
|
-
self.task_schema:
|
|
45
|
-
self.task_default_values:
|
|
49
|
+
self.task_schema: dict[Any, Any] = {}
|
|
50
|
+
self.task_default_values: dict[str, Any] = {}
|
|
46
51
|
|
|
47
52
|
self._item_values = data
|
|
48
53
|
|
|
49
54
|
# Variables
|
|
50
|
-
self.values:
|
|
51
|
-
self.options:
|
|
55
|
+
self.values: dict[str, Any] = {}
|
|
56
|
+
self.options: dict[str, Any] = {}
|
|
52
57
|
self._values_initialized = False
|
|
53
58
|
|
|
54
|
-
def _initialize_data(self):
|
|
59
|
+
def _initialize_data(self) -> None:
|
|
60
|
+
"""Initialize the options and data values for the task."""
|
|
55
61
|
if self._values_initialized:
|
|
56
62
|
raise DataAlreadyInitialized
|
|
57
63
|
|
|
@@ -76,10 +82,12 @@ class TaskBase:
|
|
|
76
82
|
"changed": False,
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
def validate_schema(self):
|
|
85
|
+
def validate_schema(self) -> None:
|
|
86
|
+
"""Validate the schema of the task data and options."""
|
|
80
87
|
self._initialize_data()
|
|
81
88
|
|
|
82
|
-
def __getitem__(self, key):
|
|
89
|
+
def __getitem__(self, key: str) -> Any:
|
|
90
|
+
"""Retrieve an item from the task values or options."""
|
|
83
91
|
self._initialize_data()
|
|
84
92
|
|
|
85
93
|
if key in self.values:
|
|
@@ -88,14 +96,15 @@ class TaskBase:
|
|
|
88
96
|
if key in self.options:
|
|
89
97
|
return self.options[key]
|
|
90
98
|
|
|
91
|
-
raise KeyError(f"The item '{key}' was not found in '{self.values}")
|
|
99
|
+
raise KeyError(f"The item '{key}' was not found in '{self.values}'")
|
|
92
100
|
|
|
93
101
|
|
|
94
102
|
class TaskBatchFetch(TaskBase):
|
|
95
103
|
"""Plugin downloader base class."""
|
|
96
104
|
|
|
97
|
-
def __init__(self, data:
|
|
98
|
-
|
|
105
|
+
def __init__(self, data: dict[str, Any], options: dict[str, Any]) -> None:
|
|
106
|
+
"""Initialize the batchfetch task plugin."""
|
|
107
|
+
new_options: dict[str, Any] = {"exec_before": [],
|
|
99
108
|
"exec_after": [],
|
|
100
109
|
"ignore_untracked": []}
|
|
101
110
|
new_options.update(options)
|
|
@@ -107,13 +116,13 @@ class TaskBatchFetch(TaskBase):
|
|
|
107
116
|
self.env = os.environ.copy()
|
|
108
117
|
|
|
109
118
|
# Default
|
|
110
|
-
self.global_options_schema:
|
|
119
|
+
self.global_options_schema: dict[Any, Any] = {
|
|
111
120
|
Optional("exec_before"): Or([str], str),
|
|
112
121
|
Optional("exec_after"): Or([str], str),
|
|
113
122
|
Optional("ignore_untracked"): Or([str], str),
|
|
114
123
|
}
|
|
115
124
|
|
|
116
|
-
self.task_schema:
|
|
125
|
+
self.task_schema: dict[Any, Any] = {
|
|
117
126
|
Optional("path"): str,
|
|
118
127
|
Optional("delete"): bool,
|
|
119
128
|
|
|
@@ -124,12 +133,13 @@ class TaskBatchFetch(TaskBase):
|
|
|
124
133
|
Optional("ignore_untracked"): Or([str], str),
|
|
125
134
|
}
|
|
126
135
|
|
|
127
|
-
self.task_default_values:
|
|
136
|
+
self.task_default_values: dict[str, Any] = {
|
|
128
137
|
# Optional items
|
|
129
138
|
"delete": False,
|
|
130
139
|
}
|
|
131
140
|
|
|
132
|
-
def _initialize_data(self):
|
|
141
|
+
def _initialize_data(self) -> None:
|
|
142
|
+
"""Safely initialize data for the batchfetch task."""
|
|
133
143
|
try:
|
|
134
144
|
super()._initialize_data()
|
|
135
145
|
except DataAlreadyInitialized:
|
|
@@ -138,14 +148,16 @@ class TaskBatchFetch(TaskBase):
|
|
|
138
148
|
# Mark values as initialized
|
|
139
149
|
self._values_initialized = True
|
|
140
150
|
|
|
141
|
-
def _local_task_exec(self, *args, **kwargs):
|
|
151
|
+
def _local_task_exec(self, *args: Any, **kwargs: Any) -> None:
|
|
152
|
+
"""Execute a local task command and capture its output."""
|
|
142
153
|
stdout = run_indent_str(env=self.env, spaces=self.indent,
|
|
143
154
|
*args, **kwargs)
|
|
144
155
|
if not stdout.endswith("\n"):
|
|
145
156
|
stdout += "\n"
|
|
146
157
|
self.add_output(stdout)
|
|
147
158
|
|
|
148
|
-
def _exec_before(self, cwd: os.PathLike = Path(".")):
|
|
159
|
+
def _exec_before(self, cwd: os.PathLike = Path(".")) -> None:
|
|
160
|
+
"""Execute pre-task commands defined in options and task items."""
|
|
149
161
|
self._initialize_data()
|
|
150
162
|
if self["delete"]:
|
|
151
163
|
return
|
|
@@ -162,9 +174,10 @@ class TaskBatchFetch(TaskBase):
|
|
|
162
174
|
if cmd:
|
|
163
175
|
self._local_task_exec(cmd, cwd=str(cwd))
|
|
164
176
|
|
|
165
|
-
def _exec_after(self, cwd: os.PathLike = Path(".")):
|
|
177
|
+
def _exec_after(self, cwd: os.PathLike = Path(".")) -> None:
|
|
178
|
+
"""Execute post-task commands if the task was changed successfully."""
|
|
166
179
|
self._initialize_data()
|
|
167
|
-
if self["delete"] or not self.is_changed():
|
|
180
|
+
if self["delete"] or self.is_error() or not self.is_changed():
|
|
168
181
|
return
|
|
169
182
|
|
|
170
183
|
# Local
|
|
@@ -180,32 +193,39 @@ class TaskBatchFetch(TaskBase):
|
|
|
180
193
|
self._local_task_exec(cmd, cwd=str(cwd))
|
|
181
194
|
|
|
182
195
|
def is_changed(self) -> bool:
|
|
196
|
+
"""Return True if the task execution resulted in changes."""
|
|
183
197
|
self._initialize_data()
|
|
184
198
|
return bool(self.values["result"]["changed"])
|
|
185
199
|
|
|
186
|
-
def set_changed(self, changed: bool):
|
|
200
|
+
def set_changed(self, changed: bool) -> None:
|
|
201
|
+
"""Set the changed status of the task."""
|
|
187
202
|
self._initialize_data()
|
|
188
203
|
self.values["result"]["changed"] = changed
|
|
189
204
|
|
|
190
205
|
def get_changed(self) -> bool:
|
|
206
|
+
"""Return the changed status of the task without initializing data."""
|
|
191
207
|
try:
|
|
192
208
|
return bool(self.values["result"]["changed"])
|
|
193
209
|
except KeyError:
|
|
194
210
|
return False
|
|
195
211
|
|
|
196
212
|
def is_error(self) -> bool:
|
|
213
|
+
"""Return True if the task encountered an error."""
|
|
197
214
|
self._initialize_data()
|
|
198
215
|
return bool(self.values["result"]["error"])
|
|
199
216
|
|
|
200
|
-
def set_error(self, error: bool):
|
|
217
|
+
def set_error(self, error: bool) -> None:
|
|
218
|
+
"""Set the error status of the task."""
|
|
201
219
|
self._initialize_data()
|
|
202
220
|
self.values["result"]["error"] = error
|
|
203
221
|
|
|
204
|
-
def set_output(self, output: str):
|
|
222
|
+
def set_output(self, output: str) -> None:
|
|
223
|
+
"""Set the output string of the task."""
|
|
205
224
|
self._initialize_data()
|
|
206
225
|
self.values["result"]["output"] = output
|
|
207
226
|
|
|
208
|
-
def add_output(self, output: str):
|
|
227
|
+
def add_output(self, output: str) -> None:
|
|
228
|
+
"""Append a string to the output of the task."""
|
|
209
229
|
self._initialize_data()
|
|
210
230
|
self.values["result"]["output"] += output
|
|
211
231
|
|
|
@@ -214,6 +234,7 @@ class TaskBatchFetch(TaskBase):
|
|
|
214
234
|
self._initialize_data()
|
|
215
235
|
return str(self.values["result"]["output"])
|
|
216
236
|
|
|
217
|
-
def update(self):
|
|
237
|
+
def update(self) -> dict[str, Any]:
|
|
238
|
+
"""Update the task data and return the current values."""
|
|
218
239
|
self._initialize_data()
|
|
219
240
|
return self.values
|