1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
#!/usr/bin/env python3
"""
sync-cgit-descs.py — update repo.desc= in /etc/cgitrc from gitolite description files.
Only updates existing repo blocks. Never adds new blocks or removes repos.
Skips repos whose description file is missing or contains the gitolite default.
"""
import argparse
import os
import re
import sys
CGITRC = "/etc/cgitrc"
REPO_BASE = "/var/lib/gitolite3/repositories"
GITOLITE_DEFAULT = "Unnamed repository"
def read_description(repo_url):
path = os.path.join(REPO_BASE, repo_url + ".git", "description")
if not os.path.exists(path):
return None
desc = open(path).read().strip()
if not desc or GITOLITE_DEFAULT in desc:
return None
return desc
def sync(cgitrc_path, dry_run=False):
with open(cgitrc_path) as f:
lines = f.readlines()
out = []
i = 0
changes = 0
while i < len(lines):
line = lines[i]
m = re.match(r"^repo\.url=(.+)", line.rstrip())
if m:
repo_url = m.group(1)
desc = read_description(repo_url)
out.append(line)
i += 1
# consume lines until next repo block or EOF, updating repo.desc= if found
desc_written = False
block = []
while i < len(lines):
next_line = lines[i]
if re.match(r"^repo\.url=", next_line):
break
if re.match(r"^#?repo\.desc=", next_line):
if desc:
new_line = f"repo.desc={desc}\n"
if next_line.rstrip() != new_line.rstrip():
print(f" {repo_url}: '{next_line.rstrip()}' -> '{new_line.rstrip()}'")
changes += 1
block.append(new_line)
else:
block.append(next_line)
desc_written = True
else:
block.append(next_line)
i += 1
# insert repo.desc= after repo.url= if not found in block
if not desc_written and desc:
block.insert(0, f"repo.desc={desc}\n")
print(f" {repo_url}: inserted repo.desc={desc}")
changes += 1
out.extend(block)
else:
out.append(line)
i += 1
if changes == 0:
print("No changes.")
return
if dry_run:
print(f"\n-- dry run: {changes} change(s), not writing --")
else:
with open(cgitrc_path, "w") as f:
f.writelines(out)
print(f"\nWrote {changes} change(s) to {cgitrc_path}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--cgitrc", default=CGITRC, help=f"cgitrc path (default: {CGITRC})")
parser.add_argument("--repo-base", default=REPO_BASE, help=f"gitolite repos dir (default: {REPO_BASE})")
parser.add_argument("--dry-run", action="store_true", help="print changes without writing")
args = parser.parse_args()
REPO_BASE = args.repo_base
if not os.path.exists(args.cgitrc):
print(f"error: {args.cgitrc} not found", file=sys.stderr)
sys.exit(1)
sync(args.cgitrc, dry_run=args.dry_run)
|