@@ -78,7 +78,7 @@ def getPullRequest(self, number):
78
78
def isContributor (self , username ):
79
79
if not self .contributors :
80
80
contributor_list = self .repository .iter_contributors ()
81
- self .contributors = [contributor [ 'login' ] for contributor in contributor_list ]
81
+ self .contributors = [str ( contributor ) for contributor in contributor_list ]
82
82
return username in self .contributors
83
83
84
84
def isCollaborator (username ):
@@ -94,6 +94,7 @@ class PullRequest:
94
94
labels = False
95
95
def __init__ (self , repository , number ):
96
96
self .repository = repository
97
+ self .consensus = repository .getConsensus ()
97
98
self .number = number
98
99
self .pr = self .repository .client .pull_request (self .repository .user , self .repository .name , number )
99
100
@@ -105,6 +106,11 @@ def __init__(self, repository, number):
105
106
self .yes = []
106
107
self .no = []
107
108
self .abstain = []
109
+
110
+ self .contributors_yes = []
111
+ self .contributors_no = []
112
+ self .contributors_abstain = []
113
+
108
114
self .users = []
109
115
self .doubles = []
110
116
for reaction in reactions :
@@ -115,6 +121,10 @@ def __init__(self, repository, number):
115
121
if username in self .doubles :
116
122
continue
117
123
124
+ if 'blacklist' in self .repository .rules and self .repository .rules ['blacklist' ]:
125
+ if username in self .repository .blacklist :
126
+ continue
127
+
118
128
if 'collaborators_only' in self .repository .rules and self .repository .rules ['collaborators_only' ]:
119
129
if not isCollaborator (username ):
120
130
continue
@@ -138,17 +148,38 @@ def __init__(self, repository, number):
138
148
self .no .remove (username )
139
149
if username in self .abstain :
140
150
self .abstain .remove (username )
151
+ if username in self .contributors_yes :
152
+ self .contributors_yes .remove (username )
153
+ if username in self .contributors_no :
154
+ self .contributors_no .remove (username )
155
+ if username in self .contributors_abstain :
156
+ self .contributors_abstain .remove (username )
141
157
continue
142
158
143
159
if content == '+1' :
144
- self .yes .append (user ['login' ])
145
160
self .users .append (user ['login' ])
161
+ self .yes .append (user ['login' ])
162
+ if self .repository .isContributor (user ['login' ]):
163
+ self .contributors_yes .append (user ['login' ])
146
164
elif content == '-1' :
147
- self .no .append (user ['login' ])
148
165
self .users .append (user ['login' ])
166
+ self .no .append (user ['login' ])
167
+ if seld .repository .isContributor (user ['login' ]):
168
+ self .contributors_no .append (user ['login' ])
149
169
elif content == 'confused' :
150
- self .abstain .append (user ['login' ])
151
170
self .users .append (user ['login' ])
171
+ self .abstain .append (user ['login' ])
172
+ if seld .repository .isContributor (user ['login' ]):
173
+ self .contributors_abstain .append (user ['login' ])
174
+
175
+ files = self .pr .iter_files ()
176
+ self .changes_consensus = False
177
+ self .changes_license = False
178
+ for changed_file in files :
179
+ if changed_file .filename == '.gitconsensus.yaml' :
180
+ self .changes_consensus = True
181
+ if changed_file .filename .lower ().startswith ('license' ):
182
+ self .changes_license = True
152
183
153
184
def hoursSinceLastCommit (self ):
154
185
commits = self .pr .iter_commits ()
@@ -175,14 +206,19 @@ def hoursSinceLastUpdate(self):
175
206
return hoursOpen
176
207
return hoursSinceCommit
177
208
209
+ def changesConsensus (self ):
210
+ return self .changes_consensus
211
+
212
+ def changesLicense (self ):
213
+ return self .changes_license
214
+
178
215
def getIssue (self ):
179
216
return self .repository .repository .issue (self .number )
180
217
181
218
def validate (self ):
182
219
if self .repository .rules == False :
183
220
return False
184
- consenttest = self .repository .getConsensus ()
185
- return consenttest .validate (self )
221
+ return self .consensus .validate (self )
186
222
187
223
def shouldClose (self ):
188
224
if 'timeout' in self .repository .rules :
@@ -193,11 +229,13 @@ def shouldClose(self):
193
229
def close (self ):
194
230
self .pr .close ()
195
231
self .addLabels (['gc-closed' ])
232
+ self .cleanInfoLabels ()
196
233
self .commentAction ('closed' )
197
234
198
235
def vote_merge (self ):
199
236
self .pr .merge ('GitConsensus Merge' )
200
237
self .addLabels (['gc-merged' ])
238
+ self .cleanInfoLabels ()
201
239
202
240
if 'extra_labels' in self .repository .rules and self .repository .rules ['extra_labels' ]:
203
241
self .addLabels ([
@@ -208,18 +246,53 @@ def vote_merge(self):
208
246
])
209
247
self .commentAction ('merged' )
210
248
249
+ def addInfoLabels (self ):
250
+ labels = self .getLabelList ()
251
+
252
+ licenseMessage = 'License Change'
253
+ if self .changesLicense ():
254
+ self .addLabels ([licenseMessage ])
255
+ else :
256
+ self .removeLabels ([licenseMessage ])
257
+
258
+ consensusMessage = 'Consensus Change'
259
+ if self .changesConsensus ():
260
+ self .addLabels ([consensusMessage ])
261
+ else :
262
+ self .removeLabels ([consensusMessage ])
263
+
264
+ hasQuorumMessage = 'Has Quorum'
265
+ needsQuorumMessage = 'Needs Votes'
266
+ if self .consensus .hasQuorum (self ):
267
+ self .addLabels ([hasQuorumMessage ])
268
+ self .removeLabels ([needsQuorumMessage ])
269
+ else :
270
+ self .removeLabels ([hasQuorumMessage ])
271
+ self .addLabels ([needsQuorumMessage ])
272
+
273
+ passingMessage = 'Passing'
274
+ failingMessage = 'Failing'
275
+ if self .consensus .hasVotes (self ):
276
+ self .addLabels ([passingMessage ])
277
+ self .removeLabels ([failingMessage ])
278
+ else :
279
+ self .removeLabels ([passingMessage ])
280
+ self .addLabels ([failingMessage ])
281
+
282
+ def cleanInfoLabels (self ):
283
+ self .removeLabels (['Failing' , 'Passing' , 'Needs Votes' , 'Has Quorum' ])
284
+
211
285
def commentAction (self , action ):
212
286
table = self .buildVoteTable ()
213
- consensus = self .repository .getConsensus ()
214
287
message = message_template % (
215
288
action ,
216
289
str (len (self .yes )),
217
290
str (len (self .no )),
218
291
str (len (self .abstain )),
219
292
str (len (self .users )),
220
293
table ,
221
- consensus .hasQuorum (self ),
222
- consensus .hasVotes (self )
294
+ self . consensus .hasQuorum (self ),
295
+ self . consensus .hasVotes (self )
223
296
)
224
297
225
298
if len (self .doubles ) > 0 :
@@ -251,11 +324,19 @@ def buildVoteTable(self):
251
324
table = "%s\n %s" % (table , row )
252
325
return table
253
326
254
-
255
327
def addLabels (self , labels ):
328
+ existing = self .getLabelList ()
256
329
issue = self .getIssue ()
257
330
for label in labels :
258
- issue .add_labels (label )
331
+ if label not in existing :
332
+ issue .add_labels (label )
333
+
334
+ def removeLabels (self , labels ):
335
+ existing = self .getLabelList ()
336
+ issue = self .getIssue ()
337
+ for label in labels :
338
+ if label in existing :
339
+ issue .remove_label (label )
259
340
260
341
def addComment (self , comment_string ):
261
342
return self .getIssue ().create_comment (comment_string )
@@ -320,8 +401,13 @@ def hasAged(self, pr):
320
401
if hours >= self .rules ['mergedelay' ]:
321
402
return True
322
403
if 'delayoverride' in self .rules and self .rules ['delayoverride' ]:
404
+ if pr .changesConsensus () or pr .changesLicense ():
405
+ return False
406
+ if 'mergedelaymin' in self .rules and self .rules ['mergedelaymin' ]:
407
+ if hours < self .rules ['mergedelaymin' ]:
408
+ return False
323
409
if len (pr .no ) > 0 :
324
410
return False
325
- if len (pr .yes ) >= self .rules ['delayoverride' ]:
411
+ if len (pr .contributors_yes ) >= self .rules ['delayoverride' ]:
326
412
return True
327
413
return False
0 commit comments