111887Sandreas.sandberg@arm.com#!/bin/sh 211887Sandreas.sandberg@arm.com# From Gerrit Code Review 2.13.5-2617-gba50ae91fd 311887Sandreas.sandberg@arm.com# 411887Sandreas.sandberg@arm.com# Part of Gerrit Code Review (https://www.gerritcodereview.com/) 511887Sandreas.sandberg@arm.com# 611887Sandreas.sandberg@arm.com# Copyright (C) 2009 The Android Open Source Project 711887Sandreas.sandberg@arm.com# 811887Sandreas.sandberg@arm.com# Licensed under the Apache License, Version 2.0 (the "License"); 911887Sandreas.sandberg@arm.com# you may not use this file except in compliance with the License. 1011887Sandreas.sandberg@arm.com# You may obtain a copy of the License at 1111887Sandreas.sandberg@arm.com# 1211887Sandreas.sandberg@arm.com# http://www.apache.org/licenses/LICENSE-2.0 1311887Sandreas.sandberg@arm.com# 1411887Sandreas.sandberg@arm.com# Unless required by applicable law or agreed to in writing, software 1511887Sandreas.sandberg@arm.com# distributed under the License is distributed on an "AS IS" BASIS, 1611887Sandreas.sandberg@arm.com# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1711887Sandreas.sandberg@arm.com# See the License for the specific language governing permissions and 1811887Sandreas.sandberg@arm.com# limitations under the License. 1911887Sandreas.sandberg@arm.com# 2011887Sandreas.sandberg@arm.com 2111887Sandreas.sandberg@arm.comunset GREP_OPTIONS 2211887Sandreas.sandberg@arm.com 2311887Sandreas.sandberg@arm.comCHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed" 2411887Sandreas.sandberg@arm.comMSG="$1" 2511887Sandreas.sandberg@arm.com 2611887Sandreas.sandberg@arm.com# Check for, and add if missing, a unique Change-Id 2711887Sandreas.sandberg@arm.com# 2811887Sandreas.sandberg@arm.comadd_ChangeId() { 2911887Sandreas.sandberg@arm.com clean_message=`sed -e ' 3011887Sandreas.sandberg@arm.com /^diff --git .*/{ 3111887Sandreas.sandberg@arm.com s/// 3211887Sandreas.sandberg@arm.com q 3311887Sandreas.sandberg@arm.com } 3411887Sandreas.sandberg@arm.com /^Signed-off-by:/d 3511887Sandreas.sandberg@arm.com /^#/d 3611887Sandreas.sandberg@arm.com ' "$MSG" | git stripspace` 3711887Sandreas.sandberg@arm.com if test -z "$clean_message" 3811887Sandreas.sandberg@arm.com then 3911887Sandreas.sandberg@arm.com return 4011887Sandreas.sandberg@arm.com fi 4111887Sandreas.sandberg@arm.com 4211887Sandreas.sandberg@arm.com # Do not add Change-Id to temp commits 4311887Sandreas.sandberg@arm.com if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!' 4411887Sandreas.sandberg@arm.com then 4511887Sandreas.sandberg@arm.com return 4611887Sandreas.sandberg@arm.com fi 4711887Sandreas.sandberg@arm.com 4811887Sandreas.sandberg@arm.com if test "false" = "`git config --bool --get gerrit.createChangeId`" 4911887Sandreas.sandberg@arm.com then 5011887Sandreas.sandberg@arm.com return 5111887Sandreas.sandberg@arm.com fi 5211887Sandreas.sandberg@arm.com 5311887Sandreas.sandberg@arm.com # Does Change-Id: already exist? if so, exit (no change). 5411887Sandreas.sandberg@arm.com if grep -i '^Change-Id:' "$MSG" >/dev/null 5511887Sandreas.sandberg@arm.com then 5611887Sandreas.sandberg@arm.com return 5711887Sandreas.sandberg@arm.com fi 5811887Sandreas.sandberg@arm.com 5911887Sandreas.sandberg@arm.com id=`_gen_ChangeId` 6011887Sandreas.sandberg@arm.com T="$MSG.tmp.$$" 6111887Sandreas.sandberg@arm.com AWK=awk 6211887Sandreas.sandberg@arm.com if [ -x /usr/xpg4/bin/awk ]; then 6311887Sandreas.sandberg@arm.com # Solaris AWK is just too broken 6411887Sandreas.sandberg@arm.com AWK=/usr/xpg4/bin/awk 6511887Sandreas.sandberg@arm.com fi 6611887Sandreas.sandberg@arm.com 6711887Sandreas.sandberg@arm.com # Get core.commentChar from git config or use default symbol 6811887Sandreas.sandberg@arm.com commentChar=`git config --get core.commentChar` 6911887Sandreas.sandberg@arm.com commentChar=${commentChar:-#} 7011887Sandreas.sandberg@arm.com 7111887Sandreas.sandberg@arm.com # How this works: 7211887Sandreas.sandberg@arm.com # - parse the commit message as (textLine+ blankLine*)* 7311887Sandreas.sandberg@arm.com # - assume textLine+ to be a footer until proven otherwise 7411887Sandreas.sandberg@arm.com # - exception: the first block is not footer (as it is the title) 7511887Sandreas.sandberg@arm.com # - read textLine+ into a variable 7611887Sandreas.sandberg@arm.com # - then count blankLines 7711887Sandreas.sandberg@arm.com # - once the next textLine appears, print textLine+ blankLine* as these 7811887Sandreas.sandberg@arm.com # aren't footer 7911887Sandreas.sandberg@arm.com # - in END, the last textLine+ block is available for footer parsing 8011887Sandreas.sandberg@arm.com $AWK ' 8111887Sandreas.sandberg@arm.com BEGIN { 8211887Sandreas.sandberg@arm.com # while we start with the assumption that textLine+ 8311887Sandreas.sandberg@arm.com # is a footer, the first block is not. 8411887Sandreas.sandberg@arm.com isFooter = 0 8511887Sandreas.sandberg@arm.com footerComment = 0 8611887Sandreas.sandberg@arm.com blankLines = 0 8711887Sandreas.sandberg@arm.com } 8811887Sandreas.sandberg@arm.com 8911887Sandreas.sandberg@arm.com # Skip lines starting with commentChar without any spaces before it. 9011887Sandreas.sandberg@arm.com /^'"$commentChar"'/ { next } 9111887Sandreas.sandberg@arm.com 9211887Sandreas.sandberg@arm.com # Skip the line starting with the diff command and everything after it, 9311887Sandreas.sandberg@arm.com # up to the end of the file, assuming it is only patch data. 9411887Sandreas.sandberg@arm.com # If more than one line before the diff was empty, strip all but one. 9511887Sandreas.sandberg@arm.com /^diff --git / { 9611887Sandreas.sandberg@arm.com blankLines = 0 9711887Sandreas.sandberg@arm.com while (getline) { } 9811887Sandreas.sandberg@arm.com next 9911887Sandreas.sandberg@arm.com } 10011887Sandreas.sandberg@arm.com 10111887Sandreas.sandberg@arm.com # Count blank lines outside footer comments 10211887Sandreas.sandberg@arm.com /^$/ && (footerComment == 0) { 10311887Sandreas.sandberg@arm.com blankLines++ 10411887Sandreas.sandberg@arm.com next 10511887Sandreas.sandberg@arm.com } 10611887Sandreas.sandberg@arm.com 10711887Sandreas.sandberg@arm.com # Catch footer comment 10811887Sandreas.sandberg@arm.com /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) { 10911887Sandreas.sandberg@arm.com footerComment = 1 11011887Sandreas.sandberg@arm.com } 11111887Sandreas.sandberg@arm.com 11211887Sandreas.sandberg@arm.com /]$/ && (footerComment == 1) { 11311887Sandreas.sandberg@arm.com footerComment = 2 11411887Sandreas.sandberg@arm.com } 11511887Sandreas.sandberg@arm.com 11611887Sandreas.sandberg@arm.com # We have a non-blank line after blank lines. Handle this. 11711887Sandreas.sandberg@arm.com (blankLines > 0) { 11811887Sandreas.sandberg@arm.com print lines 11911887Sandreas.sandberg@arm.com for (i = 0; i < blankLines; i++) { 12011887Sandreas.sandberg@arm.com print "" 12111887Sandreas.sandberg@arm.com } 12211887Sandreas.sandberg@arm.com 12311887Sandreas.sandberg@arm.com lines = "" 12411887Sandreas.sandberg@arm.com blankLines = 0 12511887Sandreas.sandberg@arm.com isFooter = 1 12611887Sandreas.sandberg@arm.com footerComment = 0 12711887Sandreas.sandberg@arm.com } 12811887Sandreas.sandberg@arm.com 12911887Sandreas.sandberg@arm.com # Detect that the current block is not the footer 13011887Sandreas.sandberg@arm.com (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) { 13111887Sandreas.sandberg@arm.com isFooter = 0 13211887Sandreas.sandberg@arm.com } 13311887Sandreas.sandberg@arm.com 13411887Sandreas.sandberg@arm.com { 13511887Sandreas.sandberg@arm.com # We need this information about the current last comment line 13611887Sandreas.sandberg@arm.com if (footerComment == 2) { 13711887Sandreas.sandberg@arm.com footerComment = 0 13811887Sandreas.sandberg@arm.com } 13911887Sandreas.sandberg@arm.com if (lines != "") { 14011887Sandreas.sandberg@arm.com lines = lines "\n"; 14111887Sandreas.sandberg@arm.com } 14211887Sandreas.sandberg@arm.com lines = lines $0 14311887Sandreas.sandberg@arm.com } 14411887Sandreas.sandberg@arm.com 14511887Sandreas.sandberg@arm.com # Footer handling: 14611887Sandreas.sandberg@arm.com # If the last block is considered a footer, splice in the Change-Id at the 14711887Sandreas.sandberg@arm.com # right place. 14811887Sandreas.sandberg@arm.com # Look for the right place to inject Change-Id by considering 14911887Sandreas.sandberg@arm.com # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first, 15011887Sandreas.sandberg@arm.com # then Change-Id, then everything else (eg. Signed-off-by:). 15111887Sandreas.sandberg@arm.com # 15211887Sandreas.sandberg@arm.com # Otherwise just print the last block, a new line and the Change-Id as a 15311887Sandreas.sandberg@arm.com # block of its own. 15411887Sandreas.sandberg@arm.com END { 15511887Sandreas.sandberg@arm.com unprinted = 1 15611887Sandreas.sandberg@arm.com if (isFooter == 0) { 15711887Sandreas.sandberg@arm.com print lines "\n" 15811887Sandreas.sandberg@arm.com lines = "" 15911887Sandreas.sandberg@arm.com } 16011887Sandreas.sandberg@arm.com changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):" 16111887Sandreas.sandberg@arm.com numlines = split(lines, footer, "\n") 16211887Sandreas.sandberg@arm.com for (line = 1; line <= numlines; line++) { 16311887Sandreas.sandberg@arm.com if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) { 16411887Sandreas.sandberg@arm.com unprinted = 0 16511887Sandreas.sandberg@arm.com print "Change-Id: I'"$id"'" 16611887Sandreas.sandberg@arm.com } 16711887Sandreas.sandberg@arm.com print footer[line] 16811887Sandreas.sandberg@arm.com } 16911887Sandreas.sandberg@arm.com if (unprinted) { 17011887Sandreas.sandberg@arm.com print "Change-Id: I'"$id"'" 17111887Sandreas.sandberg@arm.com } 17211887Sandreas.sandberg@arm.com }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T" 17311887Sandreas.sandberg@arm.com} 17411887Sandreas.sandberg@arm.com_gen_ChangeIdInput() { 17511887Sandreas.sandberg@arm.com echo "tree `git write-tree`" 17611887Sandreas.sandberg@arm.com if parent=`git rev-parse "HEAD^0" 2>/dev/null` 17711887Sandreas.sandberg@arm.com then 17811887Sandreas.sandberg@arm.com echo "parent $parent" 17911887Sandreas.sandberg@arm.com fi 18011887Sandreas.sandberg@arm.com echo "author `git var GIT_AUTHOR_IDENT`" 18111887Sandreas.sandberg@arm.com echo "committer `git var GIT_COMMITTER_IDENT`" 18211887Sandreas.sandberg@arm.com echo 18311887Sandreas.sandberg@arm.com printf '%s' "$clean_message" 18411887Sandreas.sandberg@arm.com} 18511887Sandreas.sandberg@arm.com_gen_ChangeId() { 18611887Sandreas.sandberg@arm.com _gen_ChangeIdInput | 18711887Sandreas.sandberg@arm.com git hash-object -t commit --stdin 18811887Sandreas.sandberg@arm.com} 18911887Sandreas.sandberg@arm.com 19011887Sandreas.sandberg@arm.com 19111887Sandreas.sandberg@arm.comadd_ChangeId 192