polygit 0.2.0__tar.gz → 0.3.1__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
1
  Metadata-Version: 2.4
2
2
  Name: polygit
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: Manage multiple git repos from a single .pgit config file.
5
5
  Project-URL: Repository, https://gitlab.com/gary.schaetz/public/polygit
6
6
  Author-email: Gary Schaetz <gary@schaetzkc.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "polygit"
7
- version = "0.2.0"
7
+ version = "0.3.1"
8
8
  description = "Manage multiple git repos from a single .pgit config file."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE.txt" }
@@ -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,21 @@ 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"{_G}↓{_RST}"
23
+ ERR = f"{_R}✗{_RST}"
24
+ WARN = f"{_Y}⚠{_RST}"
25
+ NEW = f"{_C}+{_RST}"
26
+
11
27
 
12
28
  def _emit(lines):
13
29
  """Print a block of lines atomically."""
@@ -53,36 +69,39 @@ def is_dirty(d):
53
69
 
54
70
 
55
71
  def _commit_and_push(d, label, msg):
56
- lines = [f"Committing {label}..."]
72
+ lines = [f" Committing {label}..."]
57
73
  subprocess.run(["git", "-C", str(d), "add", "-A"], capture_output=True)
58
74
  subprocess.run(["git", "-C", str(d), "commit", "-m", msg], capture_output=True)
59
75
  result = subprocess.run(["git", "-C", str(d), "push"], capture_output=True, text=True)
60
76
  if result.returncode != 0:
61
- lines.append(f" Push failed: {result.stderr.strip()}")
77
+ lines.append(f"{ERR} {label}: push failed — {result.stderr.strip().splitlines()[0]}")
62
78
  else:
63
- lines.append(f" Pushed.")
79
+ lines.append(f"{UPD} {label}: pushed")
64
80
  _emit(lines)
65
81
 
66
82
 
67
83
  def _sync_one(platform, local_path, remote_path, d):
68
84
  url = f"{HOSTS[platform]}:{remote_path}.git"
85
+ label = f"{platform}/{local_path}"
69
86
  if (d / ".git").exists():
70
87
  result = subprocess.run(
71
88
  ["git", "-C", str(d), "fetch", "--all", "-q"],
72
89
  capture_output=True, text=True
73
90
  )
74
- lines = [f"Fetched {platform}/{local_path}"]
75
- if result.stderr.strip():
76
- lines.append(f" {result.stderr.strip()}")
91
+ if result.returncode != 0:
92
+ lines = [f"{ERR} {label}: {result.stderr.strip().splitlines()[0]}"]
93
+ else:
94
+ lines = [f"{OK} {_DIM}{label}{_RST}"]
77
95
  else:
78
96
  d.parent.mkdir(parents=True, exist_ok=True)
79
97
  result = subprocess.run(
80
98
  ["git", "clone", url, str(d)],
81
99
  capture_output=True, text=True
82
100
  )
83
- lines = [f"Cloned {platform}/{local_path}"]
84
101
  if result.returncode != 0:
85
- lines.append(f" Error: {result.stderr.strip()}")
102
+ lines = [f"{ERR} {label}: {result.stderr.strip().splitlines()[0]}"]
103
+ else:
104
+ lines = [f"{NEW} {label}: cloned"]
86
105
  _emit(lines)
87
106
 
88
107
 
@@ -98,20 +117,26 @@ def _pull_one(platform, local_path, d):
98
117
  capture_output=True, text=True
99
118
  )
100
119
  if result.returncode != 0:
101
- lines.append(f"{label}: error — {result.stderr.strip()}")
120
+ err = result.stderr.strip()
121
+ if "no tracking information" in err or "no upstream" in err.lower():
122
+ lines.append(f"{WARN} {label}: no upstream branch set")
123
+ else:
124
+ lines.append(f"{ERR} {label}: {err.splitlines()[0]}")
102
125
  elif result.stdout.strip() and result.stdout.strip() != "Already up to date.":
103
- lines.append(f"{label}: {result.stdout.strip()}")
126
+ lines.append(f"{UPD} {label}:")
127
+ for ln in result.stdout.strip().splitlines():
128
+ lines.append(f" {ln}")
104
129
  else:
105
- lines.append(f"{label}: up to date")
130
+ lines.append(f"{OK} {_DIM}{label}{_RST}")
106
131
  if stashed:
107
132
  pop = subprocess.run(
108
133
  ["git", "-C", str(d), "stash", "pop"],
109
134
  capture_output=True, text=True
110
135
  )
111
136
  if pop.returncode != 0:
112
- lines.append(f" Warning: stash pop had conflicts")
137
+ lines.append(f" {_Y}warning:{_RST} stash pop had conflicts in {label}")
113
138
  else:
114
- lines.append(f" Stash restored.")
139
+ lines.append(f" stash restored")
115
140
  _emit(lines)
116
141
 
117
142
 
@@ -143,11 +168,11 @@ def cmd_status(config, base):
143
168
  for platform, local_path, output in sorted(results):
144
169
  if output:
145
170
  found_dirty = True
146
- print(f"\n{platform}/{local_path}:")
171
+ print(f"\n{_Y}~{_RST} {platform}/{local_path}:")
147
172
  for line in output.splitlines():
148
173
  print(f" {line}")
149
174
  if not found_dirty:
150
- print("All repos are clean.")
175
+ print(f"{OK} All repos are clean.")
151
176
 
152
177
 
153
178
  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