32
32
# OS specific configuration for terminal attributes
33
33
ATTR_RESET = ''
34
34
ATTR_PR = ''
35
+ ATTR_NAME = ''
36
+ ATTR_WARN = ''
35
37
COMMIT_FORMAT = '%H %s (%an)%d'
36
38
if os .name == 'posix' : # if posix, assume we can use basic terminal escapes
37
39
ATTR_RESET = '\033 [0m'
38
40
ATTR_PR = '\033 [1;36m'
41
+ ATTR_NAME = '\033 [0;36m'
42
+ ATTR_WARN = '\033 [1;31m'
39
43
COMMIT_FORMAT = '%C(bold blue)%H%Creset %s %C(cyan)(%an)%Creset%C(green)%d%Creset'
40
44
41
45
def git_config_get (option , default = None ):
@@ -164,18 +168,36 @@ def tree_sha512sum(commit='HEAD'):
164
168
return overall .hexdigest ()
165
169
166
170
def get_acks_from_comments (head_commit , comments ):
167
- assert len (head_commit ) == 6
168
- ack_str = '\n \n ACKs for commit {}:\n ' .format (head_commit )
171
+ # Look for abbreviated commit id, because not everyone wants to type/paste
172
+ # the whole thing and the chance of collisions within a PR is small enough
173
+ head_abbrev = head_commit [0 :6 ]
174
+ acks = []
169
175
for c in comments :
170
- review = [l for l in c ['body' ].split ('\r \n ' ) if 'ACK' in l and head_commit in l ]
176
+ review = [l for l in c ['body' ].split ('\r \n ' ) if 'ACK' in l and head_abbrev in l ]
171
177
if review :
172
- ack_str += ' {}:\n ' .format (c ['user' ]['login' ])
173
- ack_str += ' {}\n ' .format (review [0 ])
178
+ acks .append ((c ['user' ]['login' ], review [0 ]))
179
+ return acks
180
+
181
+ def make_acks_message (head_commit , acks ):
182
+ if acks :
183
+ ack_str = '\n \n ACKs for top commit:\n ' .format (head_commit )
184
+ for name , msg in acks :
185
+ ack_str += ' {}:\n ' .format (name )
186
+ ack_str += ' {}\n ' .format (msg )
187
+ else :
188
+ ack_str = '\n \n Top commit has no ACKs.\n '
174
189
return ack_str
175
190
176
- def print_merge_details (pull , title , branch , base_branch , head_branch ):
191
+ def print_merge_details (pull , title , branch , base_branch , head_branch , acks ):
177
192
print ('%s#%s%s %s %sinto %s%s' % (ATTR_RESET + ATTR_PR ,pull ,ATTR_RESET ,title ,ATTR_RESET + ATTR_PR ,branch ,ATTR_RESET ))
178
193
subprocess .check_call ([GIT ,'log' ,'--graph' ,'--topo-order' ,'--pretty=format:' + COMMIT_FORMAT ,base_branch + '..' + head_branch ])
194
+ if acks is not None :
195
+ if acks :
196
+ print ('{}ACKs:{}' .format (ATTR_PR , ATTR_RESET ))
197
+ for (name , message ) in acks :
198
+ print ('* {} {}({}){}' .format (message , ATTR_NAME , name , ATTR_RESET ))
199
+ else :
200
+ print ('{}Top commit has no ACKs!{}' .format (ATTR_WARN , ATTR_RESET ))
179
201
180
202
def parse_arguments ():
181
203
epilog = '''
@@ -225,9 +247,6 @@ def main():
225
247
info = retrieve_pr_info (repo ,pull ,ghtoken )
226
248
if info is None :
227
249
sys .exit (1 )
228
- comments = retrieve_pr_comments (repo ,pull ,ghtoken ) + retrieve_pr_reviews (repo ,pull ,ghtoken )
229
- if comments is None :
230
- sys .exit (1 )
231
250
title = info ['title' ].strip ()
232
251
body = info ['body' ].strip ()
233
252
# precedence order for destination branch argument:
@@ -257,6 +276,8 @@ def main():
257
276
sys .exit (3 )
258
277
try :
259
278
subprocess .check_call ([GIT ,'log' ,'-q' ,'-1' ,'refs/heads/' + head_branch ], stdout = devnull , stderr = stdout )
279
+ head_commit = subprocess .check_output ([GIT ,'log' ,'-1' ,'--pretty=format:%H' ,head_branch ]).decode ('utf-8' )
280
+ assert len (head_commit ) == 40
260
281
except subprocess .CalledProcessError :
261
282
print ("ERROR: Cannot find head of pull request #%s on %s." % (pull ,host_repo ), file = stderr )
262
283
sys .exit (3 )
@@ -281,7 +302,6 @@ def main():
281
302
message = firstline + '\n \n '
282
303
message += subprocess .check_output ([GIT ,'log' ,'--no-merges' ,'--topo-order' ,'--pretty=format:%H %s (%an)' ,base_branch + '..' + head_branch ]).decode ('utf-8' )
283
304
message += '\n \n Pull request description:\n \n ' + body .replace ('\n ' , '\n ' ) + '\n '
284
- message += get_acks_from_comments (head_commit = subprocess .check_output ([GIT ,'log' ,'-1' ,'--pretty=format:%H' ,head_branch ]).decode ('utf-8' )[:6 ], comments = comments )
285
305
try :
286
306
subprocess .check_call ([GIT ,'merge' ,'-q' ,'--commit' ,'--no-edit' ,'--no-ff' ,'--no-gpg-sign' ,'-m' ,message .encode ('utf-8' ),head_branch ])
287
307
except subprocess .CalledProcessError :
@@ -299,20 +319,14 @@ def main():
299
319
if len (symlink_files ) > 0 :
300
320
sys .exit (4 )
301
321
302
- # Put tree SHA512 into the message
322
+ # Compute SHA512 of git tree (to be able to detect changes before sign-off)
303
323
try :
304
324
first_sha512 = tree_sha512sum ()
305
- message += '\n \n Tree-SHA512: ' + first_sha512
306
325
except subprocess .CalledProcessError :
307
326
print ("ERROR: Unable to compute tree hash" )
308
327
sys .exit (4 )
309
- try :
310
- subprocess .check_call ([GIT ,'commit' ,'--amend' ,'--no-gpg-sign' ,'-m' ,message .encode ('utf-8' )])
311
- except subprocess .CalledProcessError :
312
- print ("ERROR: Cannot update message." , file = stderr )
313
- sys .exit (4 )
314
328
315
- print_merge_details (pull , title , branch , base_branch , head_branch )
329
+ print_merge_details (pull , title , branch , base_branch , head_branch , None )
316
330
print ()
317
331
318
332
# Run test command if configured.
@@ -345,8 +359,24 @@ def main():
345
359
print ("ERROR: Tree hash changed unexpectedly" ,file = stderr )
346
360
sys .exit (8 )
347
361
362
+ # Retrieve PR comments and ACKs and add to commit message, store ACKs to print them with commit
363
+ # description
364
+ comments = retrieve_pr_comments (repo ,pull ,ghtoken ) + retrieve_pr_reviews (repo ,pull ,ghtoken )
365
+ if comments is None :
366
+ print ("ERROR: Could not fetch PR comments and reviews" ,file = stderr )
367
+ sys .exit (1 )
368
+ acks = get_acks_from_comments (head_commit = head_commit , comments = comments )
369
+ message += make_acks_message (head_commit = head_commit , acks = acks )
370
+ # end message with SHA512 tree hash, then update message
371
+ message += '\n \n Tree-SHA512: ' + first_sha512
372
+ try :
373
+ subprocess .check_call ([GIT ,'commit' ,'--amend' ,'--no-gpg-sign' ,'-m' ,message .encode ('utf-8' )])
374
+ except subprocess .CalledProcessError :
375
+ print ("ERROR: Cannot update message." , file = stderr )
376
+ sys .exit (4 )
377
+
348
378
# Sign the merge commit.
349
- print_merge_details (pull , title , branch , base_branch , head_branch )
379
+ print_merge_details (pull , title , branch , base_branch , head_branch , acks )
350
380
while True :
351
381
reply = ask_prompt ("Type 's' to sign off on the above merge, or 'x' to reject and exit." ).lower ()
352
382
if reply == 's' :
0 commit comments