Skip to content
This repository was archived by the owner on Jun 23, 2024. It is now read-only.

Commit dacbe6f

Browse files
committed
Use gitpython
1 parent 170f088 commit dacbe6f

File tree

4 files changed

+29
-115
lines changed

4 files changed

+29
-115
lines changed

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pygithub>=1.59.0
22
python-dateutil>=2.8.2
33
requests>=2.31.0
4-
tabulate>=0.9.0
4+
tabulate>=0.9.0
5+
gitpython>=3.1.37

sync/cli/Parameters.py

+3-27
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ def configure_parser_github(cls, sub_parsers):
281281
metavar="GITHUB_TOKEN",
282282
type=str,
283283
default=cls._github_token,
284-
help="GitHub REST API Token for PyGitHub. "
285-
"This can be defined in env as 'GITHUB_TOKEN', default: {0}.".format("%(default)s")
284+
help="GitHub REST API Token for PyGitHub, same as 'export GITHUB_TOKEN=...'."
286285
)
287286

288287
@classmethod
@@ -412,7 +411,7 @@ def add_parser_env(cls, p, add_quiet=False):
412411
"-q",
413412
"--quiet",
414413
action="store_true",
415-
help="Disable all logging piped through stdout."
414+
help="Show only error logs (piped through stderr)."
416415
)
417416

418417
env.add_argument(
@@ -436,7 +435,7 @@ def add_parser_git(cls, p, add_set_size=True):
436435
dest="git_branch",
437436
metavar="GIT_BRANCH",
438437
type=str,
439-
default=get_current_branch(cls._root_folder),
438+
default=GitUtils.current_branch(cls._root_folder),
440439
help="Define branch to push, current: {0}.".format("%(default)s")
441440
)
442441

@@ -451,26 +450,3 @@ def add_parser_git(cls, p, add_set_size=True):
451450
)
452451

453452
return git
454-
455-
@classmethod
456-
def add_parser_quiet(cls, p):
457-
p.add_argument(
458-
"-q",
459-
"--quiet",
460-
action="store_true",
461-
help="Show only error logs (piped through stderr)."
462-
)
463-
464-
@classmethod
465-
def add_parser_help(cls, p):
466-
p.add_argument(
467-
"-h",
468-
"--help",
469-
action=_HelpAction,
470-
help="Show this help message and exit.",
471-
)
472-
473-
474-
def get_current_branch(root_folder: Path):
475-
GitUtils.set_cwd_folder(root_folder)
476-
return GitUtils.current_branch()

sync/core/Sync.py

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import concurrent.futures
2-
import subprocess
32
from concurrent.futures import ThreadPoolExecutor
43
from datetime import datetime
54

5+
from git import Repo
66
from tabulate import tabulate
77

88
from .Config import Config
@@ -13,7 +13,7 @@
1313
TrackJson
1414
)
1515
from ..track import BaseTracks, LocalTracks, GithubTracks
16-
from ..utils import Log, GitUtils
16+
from ..utils import Log
1717

1818

1919
class Sync:
@@ -156,16 +156,13 @@ def update(self, module_ids=None, force=False, single=False, **kwargs):
156156

157157
def push_by_git(self, branch):
158158
json_file = self._json_folder.joinpath(ModulesJson.filename())
159-
if not GitUtils.is_enable():
160-
self._log.e("push_by_git: git command not found")
161-
return
162-
163159
timestamp = ModulesJson.load(json_file).get_timestamp()
164160
msg = f"Update by CLI ({datetime.fromtimestamp(timestamp)})"
165161

166-
subprocess.run(["git", "add", "."], cwd=self._root_folder.as_posix())
167-
subprocess.run(["git", "commit", "-m", msg], cwd=self._root_folder.as_posix())
168-
subprocess.run(["git", "push", "-u", "origin", branch], cwd=self._root_folder.as_posix())
162+
repo = Repo(self._root_folder)
163+
repo.git.add(all=True)
164+
repo.index.commit(msg)
165+
repo.remote().push(branch)
169166

170167
def get_versions_diff(self):
171168
headers = ["id", "name", "version"]

sync/utils/GitUtils.py

+18-78
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,35 @@
11
import functools
22
import os
33
import shutil
4-
import subprocess
5-
from datetime import datetime
64
from pathlib import Path
7-
from subprocess import CalledProcessError
85
from typing import Optional
96

10-
from dateutil.parser import parse
11-
from requests import HTTPError
7+
from git import Repo, InvalidGitRepositoryError, GitCommandError
128

139

1410
class GitUtils:
15-
_cwd_folder = None
16-
17-
@classmethod
18-
def set_cwd_folder(cls, cwd: Optional[Path] = None):
19-
cls._cwd_folder = cwd
20-
2111
@classmethod
2212
@functools.lru_cache()
23-
def exec(cls, cmd: str) -> str:
24-
return subprocess.run(
25-
args=cmd.split(" "),
26-
stdout=subprocess.PIPE,
27-
stderr=subprocess.DEVNULL,
28-
cwd=cls._cwd_folder
29-
).stdout.decode("utf-8").strip()
30-
31-
@classmethod
32-
def version(cls) -> str:
33-
return cls.exec("git --version")
34-
35-
@classmethod
36-
def is_enable(cls) -> bool:
37-
return cls.version() is not None
38-
39-
@classmethod
40-
def branch_all(cls) -> str:
41-
return cls.exec("git branch --all")
42-
43-
@classmethod
44-
def current_branch(cls) -> str:
45-
for out in cls.branch_all().splitlines():
46-
if not out.startswith("*"):
47-
continue
48-
49-
out = out.strip().split(maxsplit=1)
50-
return out[-1]
51-
52-
@classmethod
53-
def commit_id(cls) -> str:
54-
return cls.exec("git rev-parse --short HEAD")
55-
56-
@classmethod
57-
def commit_count(cls) -> int:
58-
return int(cls.exec("git rev-list --count HEAD"))
59-
60-
@classmethod
61-
def has_tag(cls, name: str) -> bool:
62-
return cls.exec(f"git tag -l {name}") != ""
13+
def current_branch(cls, repo_dir: Path) -> Optional[str]:
14+
try:
15+
return Repo(repo_dir).active_branch.name
16+
except InvalidGitRepositoryError:
17+
return None
6318

6419
@classmethod
6520
def clone_and_zip(cls, url: str, out: Path) -> float:
66-
out.parent.mkdir(parents=True, exist_ok=True)
6721
repo_dir = out.with_suffix("")
68-
69-
if not cls.is_enable():
70-
raise RuntimeError("git command not found")
22+
if repo_dir.exists():
23+
shutil.rmtree(repo_dir)
7124

7225
try:
73-
subprocess.run(
74-
args=["git", "clone", url, repo_dir.as_posix(), "--depth=1"],
75-
cwd=out.parent.as_posix(),
76-
stderr=subprocess.DEVNULL,
77-
check=True
78-
)
79-
except CalledProcessError:
26+
repo = Repo.clone_from(url, repo_dir)
27+
last_committed = float(repo.commit().committed_date)
28+
except GitCommandError:
8029
shutil.rmtree(repo_dir, ignore_errors=True)
81-
raise HTTPError(f"clone failed: {url}")
82-
83-
try:
84-
result = subprocess.run(
85-
["git", "log", "--format=%cd"],
86-
stdout=subprocess.PIPE,
87-
stderr=subprocess.DEVNULL,
88-
cwd=repo_dir.as_posix()
89-
).stdout.decode("utf-8")
90-
91-
last_committed = parse(result).timestamp()
92-
except CalledProcessError:
93-
last_committed = datetime.now().timestamp()
30+
raise GitCommandError(f"clone failed: {url}")
9431

95-
for path in repo_dir.rglob("*"):
32+
for path in repo_dir.iterdir():
9633
if path.name.startswith(".git"):
9734
if path.is_dir():
9835
shutil.rmtree(path, ignore_errors=True)
@@ -103,7 +40,10 @@ def clone_and_zip(cls, url: str, out: Path) -> float:
10340

10441
os.utime(path, (last_committed, last_committed))
10542

106-
shutil.make_archive(repo_dir.as_posix(), format="zip", root_dir=repo_dir)
107-
shutil.rmtree(repo_dir)
43+
try:
44+
shutil.make_archive(repo_dir.as_posix(), format="zip", root_dir=repo_dir)
45+
shutil.rmtree(repo_dir)
46+
except FileNotFoundError:
47+
raise FileNotFoundError(f"archive failed: {repo_dir.as_posix()}")
10848

10949
return last_committed

0 commit comments

Comments
 (0)