batchfetch 1.3.4__tar.gz → 1.3.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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: batchfetch
3
- Version: 1.3.4
3
+ Version: 1.3.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
@@ -17,12 +17,26 @@ Classifier: Topic :: Utilities
17
17
  Requires-Python: >=3.6, <4
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: colorama
21
+ Requires-Dist: schema
22
+ Requires-Dist: setproctitle
23
+ Requires-Dist: PyYAML
24
+ Dynamic: author
25
+ Dynamic: classifier
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: home-page
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
20
34
 
21
35
  # Batchfetch - Efficiently clone or pull multiple Git repositories in parallel
22
36
 
23
37
  ## Introduction
24
38
 
25
- Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management, freeing you up to focus on what truly matters: your workflow.
39
+ Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management.
26
40
 
27
41
  But why use Batchfetch? Because it is extremely fast, cloning repositories quickly by running Git operations in parallel. It intelligently detects whether a `git fetch` is needed, further speeding up the process of downloading data from repositories. Additionally, it allows specifying the revision (for Git), ensuring that the cloned repository matches the exact version you require.
28
42
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management, freeing you up to focus on what truly matters: your workflow.
5
+ Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management.
6
6
 
7
7
  But why use Batchfetch? Because it is extremely fast, cloning repositories quickly by running Git operations in parallel. It intelligently detects whether a `git fetch` is needed, further speeding up the process of downloading data from repositories. Additionally, it allows specifying the revision (for Git), ensuring that the cloned repository matches the exact version you require.
8
8
 
@@ -42,7 +42,9 @@ class BatchFetchCli:
42
42
  """Command-line-interface that downloads."""
43
43
 
44
44
  def __init__(self, max_workers: int, verbose: bool, check_untracked: bool,
45
- targets: List[str]):
45
+ targets: List[str], cwd: os.PathLike):
46
+ os.chdir(cwd)
47
+ self._cwd = cwd
46
48
  self._logger = logging.getLogger(self.__class__.__name__)
47
49
  self.targets = {Path(item).absolute() for item in targets}
48
50
  self.cfg: dict = {}
@@ -111,6 +113,7 @@ class BatchFetchCli:
111
113
  # Paths specified in the batchfetch.yaml file
112
114
  untracked_paths = None
113
115
  if "options" in yaml_dict and \
116
+ isinstance(yaml_dict["options"], dict) and \
114
117
  "ignore_untracked" in yaml_dict["options"]:
115
118
  untracked_paths = \
116
119
  yaml_dict["options"]["ignore_untracked"]
@@ -175,10 +178,7 @@ class BatchFetchCli:
175
178
  if str(dest_path) in dict_local_dir \
176
179
  or str(dest_path2) in dict_local_dir:
177
180
  err_str = ("More than one task have the " +
178
- f"destination path (" +
179
- str(task[keyword]) + " and " +
180
- str(dict_local_dir[(str(dest_path))]) +
181
- ")")
181
+ f"destination path: {dest_path2}")
182
182
  raise BatchFetchError(err_str)
183
183
 
184
184
  dict_local_dir[str(dest_path)] = batchfetch_instance[keyword]
@@ -310,8 +310,8 @@ class BatchFetchCli:
310
310
  err_str = "The following files need to be deleted:\n"
311
311
  for path in untracked_paths:
312
312
  err_str += (" - " +
313
- str(path) +
314
- ("/" if path.is_dir() else "") +
313
+ str(path.relative_to(self._cwd)) +
314
+ (os.sep if path.is_dir() else "") +
315
315
  "\n")
316
316
  err_str += ("The paths above are not managed by batchfetch."
317
317
  " To retain them, add them to the "
@@ -427,17 +427,10 @@ def command_line_interface():
427
427
  sys.argv[1:]))
428
428
 
429
429
  args = parse_args()
430
- done = []
431
- file = Path(args.file).absolute()
432
- file_resolved = file.absolute()
433
- if not file_resolved:
434
- print(f"Error: cannot resolve the path {file}",
435
- file=sys.stderr)
436
- sys.exit(1)
437
-
438
- done.append(file_resolved)
430
+ file = Path(args.file)
431
+ file_abs = file.absolute()
439
432
 
440
- args.directory = args.directory if args.directory else file.parent
433
+ args.directory = args.directory if args.directory else file_abs.parent
441
434
  if args.verbose and args.jobs:
442
435
  print(f"[FILE] {file}")
443
436
  print(f"[DIR] {args.directory}")
@@ -445,13 +438,13 @@ def command_line_interface():
445
438
  print(f"[CHECK UNTRACKED] {args.check_untracked}")
446
439
  print()
447
440
 
448
- os.chdir(args.directory)
449
441
  try:
450
442
  batchfetch_cli = BatchFetchCli(
451
443
  verbose=args.verbose,
452
444
  max_workers=args.jobs,
453
445
  check_untracked=args.check_untracked,
454
446
  targets=args.targets,
447
+ cwd=args.directory,
455
448
  )
456
449
 
457
450
  batchfetch_cli.load(file)
@@ -117,7 +117,7 @@ class BatchFetchGit(TaskBatchFetch):
117
117
 
118
118
  self.add_output(f"[GIT {update_type}] {self[self.main_key]}"
119
119
  + (f" (Ref: {self['revision']})"
120
- if self["revision"] else "") + "\n")
120
+ if self["revision"] else "") + "\n")
121
121
 
122
122
  try:
123
123
  # Delete
@@ -130,32 +130,34 @@ class BatchFetchGit(TaskBatchFetch):
130
130
 
131
131
  # Update
132
132
  if self.git_local_dir.is_dir():
133
+ do_git_fetch = self["git_pull"]
134
+
133
135
  # Pre exec
134
- self._update_current_branch_name()
136
+ if do_git_fetch:
137
+ self._update_current_branch_name()
138
+
135
139
  self._repo_fix_remote_origin()
136
140
  self._exec_before(cwd=self.git_local_dir)
137
141
 
138
142
  if not self["revision"]:
139
143
  self.values["revision"] = self._run_get_firstline(
140
- "git symbolic-ref refs/remotes/origin/HEAD"
141
- ).split("/")[-1]
144
+ "git symbolic-ref --short HEAD")
142
145
  if not self["revision"]:
143
146
  raise BatchFetchError(
144
147
  "Unable to determine the default origin branch"
145
148
  )
146
149
 
147
150
  self.add_output(self.indent_spaces +
148
- f"[INFO] Update revision to: '" +
151
+ "[INFO] Update revision to: '" +
149
152
  self["revision"] + "'\n")
150
153
 
151
- git_fetch_done = self._repo_fetch()
154
+ if do_git_fetch:
155
+ git_fetch_done = self._repo_fetch()
152
156
 
153
- git_branch_changed = False
154
- git_branch_changed = self._repo_fix_branch()
157
+ self._repo_fix_branch()
155
158
 
156
- git_merge_done = False
157
159
  if git_fetch_done:
158
- git_merge_done = self._git_merge()
160
+ self._git_merge()
159
161
 
160
162
  if self.get_changed():
161
163
  self._exec_after(cwd=self.git_local_dir)
@@ -192,6 +194,8 @@ class BatchFetchGit(TaskBatchFetch):
192
194
 
193
195
  :param cmd: Command to be executed. Can be a list or a string.
194
196
  :param kwargs: Additional keyword arguments for Popen.
197
+ :cwd: Current working directory.
198
+ :env: Environment variables.
195
199
  :return: Tuple containing two lists: stdout lines and stderr lines.
196
200
  """
197
201
  if not cwd:
@@ -264,11 +268,10 @@ class BatchFetchGit(TaskBatchFetch):
264
268
  # Merge
265
269
  do_git_fetch = self["git_pull"]
266
270
  do_git_fetch = False
267
- commit_ref = None
268
271
 
269
272
  try:
270
273
  # Check if the revision such as
271
- stdout, _ = self._run(["git", "cat-file", "-e", self["revision"]])
274
+ _, _ = self._run(["git", "cat-file", "-e", self["revision"]])
272
275
  except subprocess.CalledProcessError:
273
276
  do_git_fetch = True
274
277
  self.add_output(
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: batchfetch
3
- Version: 1.3.4
3
+ Version: 1.3.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
@@ -17,12 +17,26 @@ Classifier: Topic :: Utilities
17
17
  Requires-Python: >=3.6, <4
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: colorama
21
+ Requires-Dist: schema
22
+ Requires-Dist: setproctitle
23
+ Requires-Dist: PyYAML
24
+ Dynamic: author
25
+ Dynamic: classifier
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: home-page
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
20
34
 
21
35
  # Batchfetch - Efficiently clone or pull multiple Git repositories in parallel
22
36
 
23
37
  ## Introduction
24
38
 
25
- Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management, freeing you up to focus on what truly matters: your workflow.
39
+ Batchfetch is a command-line tool designed to clone, fetch, and merge multiple Git repositories simultaneously. With Batchfetch, you no longer need to manually manage each repository one by one. It automates the tedious aspects of repository management.
26
40
 
27
41
  But why use Batchfetch? Because it is extremely fast, cloning repositories quickly by running Git operations in parallel. It intelligently detects whether a `git fetch` is needed, further speeding up the process of downloading data from repositories. Additionally, it allows specifying the revision (for Git), ensuring that the cloned repository matches the exact version you require.
28
42
 
@@ -11,4 +11,5 @@ batchfetch.egg-info/SOURCES.txt
11
11
  batchfetch.egg-info/dependency_links.txt
12
12
  batchfetch.egg-info/entry_points.txt
13
13
  batchfetch.egg-info/requires.txt
14
- batchfetch.egg-info/top_level.txt
14
+ batchfetch.egg-info/top_level.txt
15
+ tests/test_helpers.py
@@ -22,7 +22,7 @@ from setuptools import find_packages, setup
22
22
 
23
23
  setup(
24
24
  name="batchfetch",
25
- version="1.3.4",
25
+ version="1.3.6",
26
26
  packages=find_packages(),
27
27
  description="Efficiently clone and pull multiple Git repositories.",
28
28
  license="GPLv3",
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # Copyright (C) 2024-2025 James Cherti
4
+ # URL: https://github.com/jamescherti/batchfetch
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+ """Unit tests."""
19
+
20
+ from pathlib import Path
21
+
22
+ from batchfetch import helpers
23
+
24
+ DATA_PATH = Path(".").joinpath("tests", "data").absolute()
25
+ SCRIPT_RUN_SIMPLE = DATA_PATH / "test-run_simple.sh"
26
+ TEST_MD5SUM_FILE = DATA_PATH / "test-md5sum.txt"
27
+
28
+
29
+ def test_md5sum():
30
+ md5sum = helpers.md5sum(TEST_MD5SUM_FILE)
31
+ assert md5sum == "f31e127edc87a6aa2eb01b7d94d2ec58"
32
+
33
+
34
+ def test_run_simple():
35
+ # Stdout
36
+ stdout_lines, stderr_lines = helpers.run_simple(str(SCRIPT_RUN_SIMPLE))
37
+ assert stdout_lines == ['Test 1.',
38
+ 'Test 2.',
39
+ 'Test 3.']
40
+ assert stderr_lines == ['Test 3.']
41
+
42
+
43
+ def test_indent_raw_output():
44
+ list_str = \
45
+ helpers.indent_raw_output(["Test 1.", "Test 2."])
46
+
47
+ assert list_str == [" Test 1.", " Test 2."]
48
+
49
+
50
+ def test_run_indent():
51
+ stdout_lines, stderr_lines = helpers.run_indent(str(SCRIPT_RUN_SIMPLE))
52
+ assert stdout_lines == [f' [RUN] {str(SCRIPT_RUN_SIMPLE)}',
53
+ ' Test 1.',
54
+ ' Test 2.',
55
+ ' Test 3.']
56
+ assert stderr_lines == [' Test 3.']
File without changes
@@ -1,4 +1,4 @@
1
- PyYAML
2
1
  colorama
3
2
  schema
4
3
  setproctitle
4
+ PyYAML
File without changes