-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhooklib.py
More file actions
103 lines (82 loc) · 2.59 KB
/
hooklib.py
File metadata and controls
103 lines (82 loc) · 2.59 KB
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
"""Hook helpers library
You can use this library to make it easier to write hooks
that work with multiple source control system (git, svn, hg ...).
It currently only works for git.
See https://github.com/charignon/hooklib for examples"""
import threading
import sys
from Queue import Queue
from hooklib_input import inputparser
def runhooks(phase, hooks, parallel=False):
if parallel:
runner = parallelhookrunner(phase)
else:
runner = hookrunner(phase)
for h in hooks:
runner.register(h)
ret = runner.evaluate()
log = runner.log.read()
if log:
sys.stderr.write("\n".join(log)+"\n")
if not ret:
sys.exit(1)
class hooklog(object):
"""Collect logs from running hooks"""
def __init__(self):
self.msgs = []
def write(self, msg):
self.msgs.append(msg)
def read(self):
return self.msgs
@staticmethod
def aggregate(logs):
msgs = []
for l in logs:
msgs.extend(l.read())
ret = hooklog()
ret.msgs = msgs
return ret
class hookrunner(object):
def __init__(self, phase=None, phases=None):
self.runlist = []
if phases is not None:
self.revdata = inputparser.fromphases(phases).parse()
else:
self.revdata = inputparser.fromphase(phase).parse()
def register(self, h, blocking=True):
self.runlist.append((h, blocking))
def evaluate(self):
self.log = hooklog()
success = True
for h, blocking in self.runlist:
hookpass = h().check(self.log, self.revdata)
# Stop evaluating after failure on blocking hook
if not hookpass and blocking:
return False
if not hookpass:
success = False
return success
class parallelhookrunner(hookrunner):
def evaluateone(self, hook):
log = hooklog()
hookpass = hook().check(log, self.revdata)
self.resultqueue.put((hookpass, log))
def evaluate(self):
threads = []
self.resultqueue = Queue()
for h, _ in self.runlist:
t = threading.Thread(target=self.evaluateone, args=(h, ))
threads.append(t)
t.start()
for t in threads:
t.join()
res, logs = [], []
for h in range(len(self.runlist)):
r, l = self.resultqueue.get()
res.append(r)
logs.append(l)
self.log = hooklog.aggregate(logs)
return all(res)
class basehook(object):
"""A basehook to be subclassed by user implemented hooks"""
pass