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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
#! /usr/bin/env python
"""
This is a git hook meant to warn the alternative arches folks about package
that turned off building on alternative arches.
"""
from __future__ import print_function
import os
import smtplib
import subprocess
import sys
from email.mime.text import MIMEText
abspath = os.path.abspath(os.environ['GIT_DIR'])
PATTERNS = ('+ExclusiveArch:', '+ExcludeArch:', '+%ifarch', '+%ifnarch',
'-ExclusiveArch:', '-ExcludeArch:', '-%ifarch', '-%ifnarch')
FROM_EMAIL = 'githook-noreply@fedoraproject.org'
TO_MAIL = 'arch-excludes@lists.fedoraproject.org'
CGIT_URL = 'https://src.fedoraproject.org/cgit/%s/commit/?id=%s'
EMAIL_SEND = True
SMTP_SERVER = 'localhost'
SMTP_PORT = 25
DEBUG = False
TEXT = u"""
The package %(pkg)s has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %%ifarch/%%ifnarch) in commit(s):
%(url)s.
Change:
%(change)s
Thanks.
Full change:
============
%(full_change)s
"""
def read_output(cmd, abspath, input=None, keepends=False, **kw):
""" Read the output from the given command to run """
if input:
stdin = subprocess.PIPE
else:
stdin = None
if DEBUG:
print('command called:', cmd)
procs = subprocess.Popen(
cmd,
stdin=stdin,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=abspath,
**kw)
(out, err) = procs.communicate(input)
retcode = procs.wait()
if retcode:
print('ERROR: %s =-- %s' % (cmd, retcode))
print(out)
print(err)
if not keepends:
out = out.rstrip('\n\r')
return out
def read_git_output(args, abspath, input=None, keepends=False, **kw):
"""Read the output of a Git command."""
return read_output(
['git'] + args, abspath, input=input, keepends=keepends, **kw)
def read_git_lines(args, abspath, keepends=False, **kw):
"""Return the lines output by Git command.
Return as single lines, with newlines stripped off."""
return read_git_output(
args, abspath, keepends=keepends, **kw
).splitlines(keepends)
def get_revs_between(oldrev, newrev, abspath, refname):
""" Yield revisions between HEAD and BASE. """
cmd = ['rev-list', '%s...%s' % (oldrev, newrev)]
if set(newrev) == set('0'):
cmd = ['rev-list', '%s' % oldrev]
elif set(oldrev) == set('0') or set(oldrev) == set('^0'):
head = get_default_branch(abspath)
cmd = ['rev-list', '%s' % newrev, '^%s' % head]
if head in refname:
cmd = ['rev-list', '%s' % newrev]
return read_git_lines(cmd, abspath)
def send_email(text, subject, to_mail): # pragma: no cover
''' Send an email with the specified information.
:arg text: the content of the email to send
:arg subject: the subject of the email
:arg to_mail: a string representing a list of recipient separated by a
coma
'''
if not to_mail:
return
from_email = FROM_EMAIL
if not EMAIL_SEND:
print('******EMAIL******')
print('From: %s' % from_email)
print('To: %s' % to_mail)
print('Subject: %s' % subject)
print('Contents:')
print(text.encode('utf-8'))
print('*****/EMAIL******')
return
smtp = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
for mailto in to_mail.split(','):
msg = MIMEText(text.encode('utf-8'), 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = from_email
# Send the message via our own SMTP server, but don't include the
# envelope header.
msg['To'] = mailto
try:
smtp.sendmail(
from_email,
[mailto],
msg.as_string())
except smtplib.SMTPException as err:
pagure.LOG.exception(err)
smtp.quit()
return msg
def run_as_post_receive_hook():
''' Check what was changed in the commit(s) and warn the alternative-arch
folks if either ExclusiveArch or ExcludesArch are changed.
'''
for line in sys.stdin:
if DEBUG:
print('Received:', line.strip())
(oldrev, newrev, refname) = line.strip().split(' ', 2)
# Skip all the branches that are not master and do not start with an 'f'
# ie: personal branches and epel
if not refname.startswith(('refs/heads/master', 'refs/heads/f')):
continue
new_commits_list = get_revs_between(oldrev, newrev, abspath, refname)
if DEBUG:
print('List of commits:', new_commits_list)
full_change = ''
exclude_arch = {}
for commit in new_commits_list:
if DEBUG:
print('Diff of commit:', commit)
full_change += '\n'
for line in read_git_lines(['show', commit], abspath):
full_change += '%s\n' % line
if DEBUG:
print(line)
if line.strip().startswith(PATTERNS):
exclude_arch[commit] = line.strip()
if DEBUG:
print('Commit %s selected' % commit)
if exclude_arch:
print('* Notifying alternative-arch people')
package = '/'.join(abspath.rsplit(os.path.sep, 2)[-2:])
if DEBUG:
print('Package:', package)
links = []
diffs = exclude_arch.values()
for commit in exclude_arch:
links.append(
CGIT_URL % (package, commit)
)
send_email(
text=TEXT % dict(
pkg=package, url='\n'.join(links), change="\n".join(diffs),
full_change=full_change
),
subject='Architecture specific change in %s' % package,
to_mail=TO_MAIL
)
if __name__ == '__main__':
run_as_post_receive_hook()
|