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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/python
from subprocess import check_output, STDOUT, CalledProcessError
import os
import time
import argparse
import logging
import stat
# Root location of git repos
GITROOT = "/srv/repositories"
# Export filename
EXPORT_FILE = "git-daemon-export-ok"
logging.basicConfig()
log = logging.getLogger('check-git-repos')
def run_command(cmd, dir):
log.debug("executing %s in %s", cmd, dir)
try:
out = check_output(cmd, stderr=STDOUT,
cwd=dir)
except CalledProcessError as e:
return e.returncode, e.output
return 0, out
def update_server_info(path):
return run_command(["git", "update-server-info"], path)
def get_file_refs(path):
filerefs = {}
with open(os.path.join(path, "info/refs")) as f:
for line in f:
if line:
data = line.split()
filerefs[data[1]] = data[0]
return filerefs
def get_git_refs(path):
ret, out = run_command(["git", "show-ref", "-d"], path)
lines = out.split("\n")
gitrefs = {}
for line in lines:
if line:
data = line.split()
gitrefs[data[1]] = data[0]
return gitrefs
def perms_check(file):
st_mode = os.stat(file).st_mode
mode = stat.S_IFREG | stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | \
stat.S_IROTH
if st_mode != mode:
log.warn("Permissions wrong for file %s, changing %s=>%s", file,
oct(st_mode), oct(mode))
os.chmod(file, mode)
def get_repos():
paths = []
for root, dirs, files in os.walk(GITROOT, followlinks=True):
if root.endswith(".git/info"):
if "refs" in files:
log.debug("found refs file %s", root+"/refs")
repo_path = os.path.dirname(root)
repo_name = os.path.basename(os.path.normpath(repo_path))
if repo_name != "gitolite-admin.git":
paths.append(repo_path)
return paths
def check_ref_status(path):
filerefs = get_file_refs(path)
gitrefs = get_git_refs(path)
diff = set(filerefs.items()) ^ set(gitrefs.items())
if len(diff) > 0:
log.warn("%s refs file out of date, diff: %s", path, diff)
ret, out = update_server_info(path)
if ret != 0 or out != "":
log.error("error processing %s, exited %i", path, ret)
log.error(out)
def check_file_exists(filepath, islink=False, linkpath=None):
if not os.path.exists(filepath):
log.warn("%s not found", filepath)
else:
if islink:
if not os.path.islink(filepath):
log.warn("%s is not a link as expected", filepath)
if linkpath:
if os.path.realpath(filepath) != linkpath:
log.warn("%s does not link to %s", filepath, linkpath)
def process(paths):
for path in paths:
refsfile = os.path.join(path, "info/refs")
perms_check(refsfile)
perms_check(path+"/objects/info/packs")
# check_file_exists(os.path.join(path, EXPORT_FILE))
check_file_exists(path+"/hooks/post-update", True)
check_ref_status(path)
if __name__ == '__main__':
oldumask = os.umask(0022)
parser = argparse.ArgumentParser(
description='Check git repositories')
parser.add_argument('--log', default='WARN',
choices=('WARN', 'INFO', 'DEBUG'),
help='Logging level to use. Default=%(default)s')
args = parser.parse_args()
log.setLevel(getattr(logging, args.log))
pathlist = get_repos()
process(pathlist)
os.umask(oldumask)
|