polygit 0.2.0__tar.gz → 0.3.0__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.
- {polygit-0.2.0 → polygit-0.3.0}/PKG-INFO +1 -1
- {polygit-0.2.0 → polygit-0.3.0}/pyproject.toml +1 -1
- {polygit-0.2.0 → polygit-0.3.0}/src/polygit/repo.py +39 -15
- {polygit-0.2.0 → polygit-0.3.0}/.gitignore +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/.gitlab-ci.yml +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/LICENSE.txt +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/README.md +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/src/polygit/__init__.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/src/polygit/cli.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/src/polygit/config.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/src/polygit/repos.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/tests/__init__.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/tests/test_polygit.py +0 -0
- {polygit-0.2.0 → polygit-0.3.0}/uv.lock +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import subprocess
|
|
2
|
+
import sys
|
|
2
3
|
import threading
|
|
3
4
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
4
5
|
from datetime import datetime
|
|
@@ -8,6 +9,20 @@ from .config import HOSTS
|
|
|
8
9
|
_print_lock = threading.Lock()
|
|
9
10
|
MAX_WORKERS = 8
|
|
10
11
|
|
|
12
|
+
_USE_COLOR = sys.stdout.isatty()
|
|
13
|
+
|
|
14
|
+
_G = "\033[32m" if _USE_COLOR else "" # green
|
|
15
|
+
_R = "\033[31m" if _USE_COLOR else "" # red
|
|
16
|
+
_C = "\033[36m" if _USE_COLOR else "" # cyan
|
|
17
|
+
_Y = "\033[33m" if _USE_COLOR else "" # yellow
|
|
18
|
+
_DIM = "\033[2m" if _USE_COLOR else "" # dim
|
|
19
|
+
_RST = "\033[0m" if _USE_COLOR else "" # reset
|
|
20
|
+
|
|
21
|
+
OK = f"{_G}✓{_RST}"
|
|
22
|
+
UPD = f"{_C}↓{_RST}"
|
|
23
|
+
ERR = f"{_R}✗{_RST}"
|
|
24
|
+
NEW = f"{_C}+{_RST}"
|
|
25
|
+
|
|
11
26
|
|
|
12
27
|
def _emit(lines):
|
|
13
28
|
"""Print a block of lines atomically."""
|
|
@@ -53,36 +68,39 @@ def is_dirty(d):
|
|
|
53
68
|
|
|
54
69
|
|
|
55
70
|
def _commit_and_push(d, label, msg):
|
|
56
|
-
lines = [f"Committing {label}..."]
|
|
71
|
+
lines = [f" Committing {label}..."]
|
|
57
72
|
subprocess.run(["git", "-C", str(d), "add", "-A"], capture_output=True)
|
|
58
73
|
subprocess.run(["git", "-C", str(d), "commit", "-m", msg], capture_output=True)
|
|
59
74
|
result = subprocess.run(["git", "-C", str(d), "push"], capture_output=True, text=True)
|
|
60
75
|
if result.returncode != 0:
|
|
61
|
-
lines.append(f"
|
|
76
|
+
lines.append(f"{ERR} {label}: push failed — {result.stderr.strip().splitlines()[0]}")
|
|
62
77
|
else:
|
|
63
|
-
lines.append(f"
|
|
78
|
+
lines.append(f"{UPD} {label}: pushed")
|
|
64
79
|
_emit(lines)
|
|
65
80
|
|
|
66
81
|
|
|
67
82
|
def _sync_one(platform, local_path, remote_path, d):
|
|
68
83
|
url = f"{HOSTS[platform]}:{remote_path}.git"
|
|
84
|
+
label = f"{platform}/{local_path}"
|
|
69
85
|
if (d / ".git").exists():
|
|
70
86
|
result = subprocess.run(
|
|
71
87
|
["git", "-C", str(d), "fetch", "--all", "-q"],
|
|
72
88
|
capture_output=True, text=True
|
|
73
89
|
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
if result.returncode != 0:
|
|
91
|
+
lines = [f"{ERR} {label}: {result.stderr.strip().splitlines()[0]}"]
|
|
92
|
+
else:
|
|
93
|
+
lines = [f"{OK} {_DIM}{label}{_RST}"]
|
|
77
94
|
else:
|
|
78
95
|
d.parent.mkdir(parents=True, exist_ok=True)
|
|
79
96
|
result = subprocess.run(
|
|
80
97
|
["git", "clone", url, str(d)],
|
|
81
98
|
capture_output=True, text=True
|
|
82
99
|
)
|
|
83
|
-
lines = [f"Cloned {platform}/{local_path}"]
|
|
84
100
|
if result.returncode != 0:
|
|
85
|
-
lines
|
|
101
|
+
lines = [f"{ERR} {label}: {result.stderr.strip().splitlines()[0]}"]
|
|
102
|
+
else:
|
|
103
|
+
lines = [f"{NEW} {label}: cloned"]
|
|
86
104
|
_emit(lines)
|
|
87
105
|
|
|
88
106
|
|
|
@@ -98,20 +116,26 @@ def _pull_one(platform, local_path, d):
|
|
|
98
116
|
capture_output=True, text=True
|
|
99
117
|
)
|
|
100
118
|
if result.returncode != 0:
|
|
101
|
-
|
|
119
|
+
err = result.stderr.strip()
|
|
120
|
+
if "no tracking information" in err or "no upstream" in err.lower():
|
|
121
|
+
lines.append(f"{ERR} {label}: no upstream branch set")
|
|
122
|
+
else:
|
|
123
|
+
lines.append(f"{ERR} {label}: {err.splitlines()[0]}")
|
|
102
124
|
elif result.stdout.strip() and result.stdout.strip() != "Already up to date.":
|
|
103
|
-
lines.append(f"{
|
|
125
|
+
lines.append(f"{UPD} {label}:")
|
|
126
|
+
for ln in result.stdout.strip().splitlines():
|
|
127
|
+
lines.append(f" {ln}")
|
|
104
128
|
else:
|
|
105
|
-
lines.append(f"{label}
|
|
129
|
+
lines.append(f"{OK} {_DIM}{label}{_RST}")
|
|
106
130
|
if stashed:
|
|
107
131
|
pop = subprocess.run(
|
|
108
132
|
["git", "-C", str(d), "stash", "pop"],
|
|
109
133
|
capture_output=True, text=True
|
|
110
134
|
)
|
|
111
135
|
if pop.returncode != 0:
|
|
112
|
-
lines.append(f"
|
|
136
|
+
lines.append(f" {_Y}warning:{_RST} stash pop had conflicts in {label}")
|
|
113
137
|
else:
|
|
114
|
-
lines.append(f"
|
|
138
|
+
lines.append(f" stash restored")
|
|
115
139
|
_emit(lines)
|
|
116
140
|
|
|
117
141
|
|
|
@@ -143,11 +167,11 @@ def cmd_status(config, base):
|
|
|
143
167
|
for platform, local_path, output in sorted(results):
|
|
144
168
|
if output:
|
|
145
169
|
found_dirty = True
|
|
146
|
-
print(f"\n{platform}/{local_path}:")
|
|
170
|
+
print(f"\n{_Y}~{_RST} {platform}/{local_path}:")
|
|
147
171
|
for line in output.splitlines():
|
|
148
172
|
print(f" {line}")
|
|
149
173
|
if not found_dirty:
|
|
150
|
-
print("All repos are clean.")
|
|
174
|
+
print(f"{OK} All repos are clean.")
|
|
151
175
|
|
|
152
176
|
|
|
153
177
|
def cmd_pull(config, base):
|
|
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
|
|
File without changes
|
|
File without changes
|