@@ -280,6 +280,163 @@ validate_commit_message() {
280
280
test $? -eq 1 || add_warning 1 " Do not start the subject line with whitespace"
281
281
}
282
282
283
+ unset GREP_OPTIONS
284
+
285
+ CHANGE_ID_AFTER= " Bug|Issue|Test"
286
+ MSG= " $1 "
287
+
288
+ # Ensure that a unique Change-Id is present, and generate one if it is not.
289
+ #
290
+ # Partially taken from Gerrit Code Review 3.3.0-56-gbcecc47463
291
+ add_change_id () {
292
+ clean_message=` sed -e '
293
+ /^diff --git .*/{
294
+ s///
295
+ q
296
+ }
297
+ /^Signed-off-by:/d
298
+ /^#/d
299
+ ' " $MSG " | git stripspace`
300
+ if test -z " $clean_message "
301
+ then
302
+ return
303
+ fi
304
+
305
+ # Does Change-Id: already exist? if so, exit (no change).
306
+ if grep -i ' ^Change-Id:' " $MSG " > /dev/null
307
+ then
308
+ return
309
+ fi
310
+
311
+ id=` _gen_changeid`
312
+ T=" $MSG .tmp.$$ "
313
+ AWK=awk
314
+
315
+ # Get core.commentChar from git config or use default symbol
316
+ commentChar=` git config --get core.commentChar`
317
+ commentChar=${commentChar:-# }
318
+
319
+ # How this works:
320
+ # - parse the commit message as (textLine+ blankLine*)*
321
+ # - assume textLine+ to be a footer until proven otherwise
322
+ # - exception: the first block is not footer (as it is the title)
323
+ # - read textLine+ into a variable
324
+ # - then count blankLines
325
+ # - once the next textLine appears, print textLine+ blankLine* as these
326
+ # aren't footer
327
+ # - in END, the last textLine+ block is available for footer parsing
328
+ awk '
329
+ BEGIN {
330
+ # while we start with the assumption that textLine+
331
+ # is a footer, the first block is not.
332
+ isFooter = 0
333
+ footerComment = 0
334
+ blankLines = 0
335
+ }
336
+
337
+ # Skip lines starting with commentChar without any spaces before it.
338
+ /^' " $commentChar " ' / { next }
339
+
340
+ # Skip the line starting with the diff command and everything after it,
341
+ # up to the end of the file, assuming it is only patch data.
342
+ # If more than one line before the diff was empty, strip all but one.
343
+ /^diff --git / {
344
+ blankLines = 0
345
+ while (getline) { }
346
+ next
347
+ }
348
+
349
+ # Count blank lines outside footer comments
350
+ /^$/ && (footerComment == 0) {
351
+ blankLines++
352
+ next
353
+ }
354
+
355
+ # Catch footer comment
356
+ /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
357
+ footerComment = 1
358
+ }
359
+
360
+ /]$/ && (footerComment == 1) {
361
+ footerComment = 2
362
+ }
363
+
364
+ # We have a non-blank line after blank lines. Handle this.
365
+ (blankLines > 0) {
366
+ print lines
367
+ for (i = 0; i < blankLines; i++) {
368
+ print ""
369
+ }
370
+
371
+ lines = ""
372
+ blankLines = 0
373
+ isFooter = 1
374
+ footerComment = 0
375
+ }
376
+
377
+ # Detect that the current block is not the footer
378
+ (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
379
+ isFooter = 0
380
+ }
381
+
382
+ {
383
+ # We need this information about the current last comment line
384
+ if (footerComment == 2) {
385
+ footerComment = 0
386
+ }
387
+ if (lines != "") {
388
+ lines = lines "\n";
389
+ }
390
+ lines = lines $0
391
+ }
392
+
393
+ # Footer handling:
394
+ # If the last block is considered a footer, splice in the Change-Id at the
395
+ # right place.
396
+ # Look for the right place to inject Change-Id by considering
397
+ # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
398
+ # then Change-Id, then everything else (eg. Signed-off-by:).
399
+ #
400
+ # Otherwise just print the last block, a new line and the Change-Id as a
401
+ # block of its own.
402
+ END {
403
+ unprinted = 1
404
+ if (isFooter == 0) {
405
+ print lines "\n"
406
+ lines = ""
407
+ }
408
+ changeIdAfter = "^(" tolower("' " $CHANGE_ID_AFTER " ' ") "):"
409
+ numlines = split(lines, footer, "\n")
410
+ for (line = 1; line <= numlines; line++) {
411
+ if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
412
+ unprinted = 0
413
+ print "Change-Id: I' " $id " ' "
414
+ }
415
+ print footer[line]
416
+ }
417
+ if (unprinted) {
418
+ print "Change-Id: I' " $id " ' "
419
+ }
420
+ }' " $MSG " > " $T " && mv " $T " " $MSG " || rm -f " $T "
421
+ }
422
+
423
+ _gen_changeid_input () {
424
+ echo " tree ` git write-tree` "
425
+ if parent=` git rev-parse " HEAD^0" 2> /dev/null`
426
+ then
427
+ echo " parent $parent "
428
+ fi
429
+ echo " author ` git var GIT_AUTHOR_IDENT` "
430
+ echo " committer ` git var GIT_COMMITTER_IDENT` "
431
+ echo
432
+ printf ' %s' " $clean_message "
433
+ }
434
+
435
+ _gen_changeid () {
436
+ _gen_changeid_input |
437
+ git hash-object -t commit --stdin
438
+ }
439
+
283
440
#
284
441
# It's showtime.
285
442
#
@@ -300,6 +457,8 @@ while true; do
300
457
301
458
validate_commit_message
302
459
460
+ add_change_id
461
+
303
462
# if there are no WARNINGS are empty then we're good to break out of here
304
463
test ${# WARNINGS[@]} -eq 0 && exit 0;
305
464
0 commit comments