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 35TEMP_BRANCH=$BRANCHNAME-temporary-branch-created-by-script 36VERSION_FILE="src/version.cc" 37CHANGELOG_ENTRY_FILE="$PERSISTFILE_BASENAME-changelog-entry" 38PATCH_FILE="$PERSISTFILE_BASENAME-patch" 39PATCH_OUTPUT_FILE="$PERSISTFILE_BASENAME-patch-output" 40COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg" 41TOUCHED_FILES_FILE="$PERSISTFILE_BASENAME-touched-files" 42TRUNK_REVISION_FILE="$PERSISTFILE_BASENAME-trunkrevision" 43START_STEP=0 44CURRENT_STEP=0 45 46die() { 47 [[ -n "$1" ]] && echo "Error: $1" 48 echo "Exiting." 49 exit 1 50} 51 52confirm() { 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 62delete_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. 77persist() { 78 local VARNAME=$1 79 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 80 echo "${!VARNAME}" > $FILE 81} 82 83restore() { 84 local VARNAME=$1 85 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 86 local VALUE="$(cat $FILE)" 87 eval "$VARNAME=\"$VALUE\"" 88} 89 90restore_if_unset() { 91 local VARNAME=$1 92 [[ -z "${!VARNAME}" ]] && restore "$VARNAME" 93 [[ -z "${!VARNAME}" ]] && die "Variable '$VARNAME' could not be restored." 94} 95 96initial_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 106common_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 128common_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. 138read_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} 146restore_version_if_unset() { 147 for v in MAJOR MINOR BUILD PATCH; do 148 restore_if_unset "$1$v" 149 done 150} 151 152upload_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 163wait_for_lgtm() { 164 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \ 165change. (If you need to iterate on the patch or double check that it's \ 166sane, do so in another shell, but remember to not change the headline of \ 167the 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. 177apply_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 184stage_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