1 # Copyright 2012 the V8 project authors. All rights reserved. 2 # Redistribution and use in source and binary forms, with or without 3 # modification, are permitted provided that the following conditions are 4 # met: 5 # 6 # * Redistributions of source code must retain the above copyright 7 # notice, this list of conditions and the following disclaimer. 8 # * Redistributions in binary form must reproduce the above 9 # copyright notice, this list of conditions and the following 10 # disclaimer in the documentation and/or other materials provided 11 # with the distribution. 12 # * Neither the name of Google Inc. nor the names of its 13 # contributors may be used to endorse or promote products derived 14 # from this software without specific prior written permission. 15 # 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 # This file contains common function definitions for various other shell 29 # scripts in this directory. It is not meant to be executed by itself. 30 31 # Important: before including this file, the following variables must be set: 32 # - BRANCHNAME 33 # - PERSISTFILE_BASENAME 34 35 TEMP_BRANCH=$BRANCHNAME-temporary-branch-created-by-script 36 VERSION_FILE="src/version.cc" 37 CHANGELOG_ENTRY_FILE="$PERSISTFILE_BASENAME-changelog-entry" 38 PATCH_FILE="$PERSISTFILE_BASENAME-patch" 39 PATCH_OUTPUT_FILE="$PERSISTFILE_BASENAME-patch-output" 40 COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg" 41 TOUCHED_FILES_FILE="$PERSISTFILE_BASENAME-touched-files" 42 TRUNK_REVISION_FILE="$PERSISTFILE_BASENAME-trunkrevision" 43 START_STEP=0 44 CURRENT_STEP=0 45 46 die() { 47 [[ -n "$1" ]] && echo "Error: $1" 48 echo "Exiting." 49 exit 1 50 } 51 52 confirm() { 53 echo -n "$1 [Y/n] " 54 read ANSWER 55 if [[ -z "$ANSWER" || "$ANSWER" == "Y" || "$ANSWER" == "y" ]] ; then 56 return 0 57 else 58 return 1 59 fi 60 } 61 62 delete_branch() { 63 local MATCH=$(git branch | grep "$1" | awk '{print $NF}' | grep -x $1) 64 if [ "$MATCH" == "$1" ] ; then 65 confirm "Branch $1 exists, do you want to delete it?" 66 if [ $? -eq 0 ] ; then 67 git branch -D $1 || die "Deleting branch '$1' failed." 68 echo "Branch $1 deleted." 69 else 70 die "Can't continue. Please delete branch $1 and try again." 71 fi 72 fi 73 } 74 75 # Persist and restore variables to support canceling/resuming execution 76 # of this script. 77 persist() { 78 local VARNAME=$1 79 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 80 echo "${!VARNAME}" > $FILE 81 } 82 83 restore() { 84 local VARNAME=$1 85 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 86 local VALUE="$(cat $FILE)" 87 eval "$VARNAME=\"$VALUE\"" 88 } 89 90 restore_if_unset() { 91 local VARNAME=$1 92 [[ -z "${!VARNAME}" ]] && restore "$VARNAME" 93 [[ -z "${!VARNAME}" ]] && die "Variable '$VARNAME' could not be restored." 94 } 95 96 initial_environment_checks() { 97 # Cancel if this is not a git checkout. 98 [[ -d .git ]] \ 99 || die "This is not a git checkout, this script won't work for you." 100 101 # Cancel if EDITOR is unset or not executable. 102 [[ -n "$EDITOR" && -x "$(which $EDITOR)" ]] \ 103 || die "Please set your EDITOR environment variable, you'll need it." 104 } 105 106 common_prepare() { 107 # Check for a clean workdir. 108 [[ -z "$(git status -s -uno)" ]] \ 109 || die "Workspace is not clean. Please commit or undo your changes." 110 111 # Persist current branch. 112 CURRENT_BRANCH=$(git status -s -b -uno | grep "^##" | awk '{print $2}') 113 persist "CURRENT_BRANCH" 114 115 # Fetch unfetched revisions. 116 git svn fetch || die "'git svn fetch' failed." 117 118 # Get ahold of a safe temporary branch and check it out. 119 if [ "$CURRENT_BRANCH" != "$TEMP_BRANCH" ] ; then 120 delete_branch $TEMP_BRANCH 121 git checkout -b $TEMP_BRANCH 122 fi 123 124 # Delete the branch that will be created later if it exists already. 125 delete_branch $BRANCHNAME 126 } 127 128 common_cleanup() { 129 restore_if_unset "CURRENT_BRANCH" 130 git checkout -f $CURRENT_BRANCH 131 [[ "$TEMP_BRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TEMP_BRANCH 132 [[ "$BRANCHNAME" != "$CURRENT_BRANCH" ]] && git branch -D $BRANCHNAME 133 # Clean up all temporary files. 134 rm -f "$PERSISTFILE_BASENAME"* 135 } 136 137 # These two functions take a prefix for the variable names as first argument. 138 read_and_persist_version() { 139 for v in MAJOR_VERSION MINOR_VERSION BUILD_NUMBER PATCH_LEVEL; do 140 VARNAME="$1${v%%_*}" 141 VALUE=$(grep "#define $v" "$VERSION_FILE" | awk '{print $NF}') 142 eval "$VARNAME=\"$VALUE\"" 143 persist "$VARNAME" 144 done 145 } 146 restore_version_if_unset() { 147 for v in MAJOR MINOR BUILD PATCH; do 148 restore_if_unset "$1$v" 149 done 150 } 151 152 upload_step() { 153 let CURRENT_STEP+=1 154 if [ $START_STEP -le $CURRENT_STEP ] ; then 155 echo ">>> Step $CURRENT_STEP: Upload for code review." 156 echo -n "Please enter the email address of a V8 reviewer for your patch: " 157 read REVIEWER 158 git cl upload -r "$REVIEWER" --send-mail \ 159 || die "'git cl upload' failed, please try again." 160 fi 161 } 162 163 wait_for_lgtm() { 164 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \ 165 change. (If you need to iterate on the patch or double check that it's \ 166 sane, do so in another shell, but remember to not change the headline of \ 167 the uploaded CL." 168 unset ANSWER 169 while [ "$ANSWER" != "LGTM" ] ; do 170 [[ -n "$ANSWER" ]] && echo "That was not 'LGTM'." 171 echo -n "> " 172 read ANSWER 173 done 174 } 175 176 # Takes a file containing the patch to apply as first argument. 177 apply_patch() { 178 patch -p1 < "$1" > "$PATCH_OUTPUT_FILE" || \ 179 { cat "$PATCH_OUTPUT_FILE" && die "Applying the patch failed."; } 180 tee < "$PATCH_OUTPUT_FILE" >(awk '{print $NF}' >> "$TOUCHED_FILES_FILE") 181 rm "$PATCH_OUTPUT_FILE" 182 } 183 184 stage_files() { 185 # Stage added and modified files. 186 TOUCHED_FILES=$(cat "$TOUCHED_FILES_FILE") 187 for FILE in $TOUCHED_FILES ; do 188 git add "$FILE" 189 done 190 # Stage deleted files. 191 DELETED_FILES=$(git status -s -uno --porcelain | grep "^ D" \ 192 | awk '{print $NF}') 193 for FILE in $DELETED_FILES ; do 194 git rm "$FILE" 195 done 196 rm -f "$TOUCHED_FILES_FILE" 197 } 198