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" 39COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg" 40TRUNK_REVISION_FILE="$PERSISTFILE_BASENAME-trunkrevision" 41START_STEP=0 42CURRENT_STEP=0 43 44die() { 45 [[ -n "$1" ]] && echo "Error: $1" 46 echo "Exiting." 47 exit 1 48} 49 50confirm() { 51 echo -n "$1 [Y/n] " 52 read ANSWER 53 if [[ -z "$ANSWER" || "$ANSWER" == "Y" || "$ANSWER" == "y" ]] ; then 54 return 0 55 else 56 return 1 57 fi 58} 59 60delete_branch() { 61 local MATCH=$(git branch | grep "$1" | awk '{print $NF}' | grep -x $1) 62 if [ "$MATCH" == "$1" ] ; then 63 confirm "Branch $1 exists, do you want to delete it?" 64 if [ $? -eq 0 ] ; then 65 git branch -D $1 || die "Deleting branch '$1' failed." 66 echo "Branch $1 deleted." 67 else 68 die "Can't continue. Please delete branch $1 and try again." 69 fi 70 fi 71} 72 73# Persist and restore variables to support canceling/resuming execution 74# of this script. 75persist() { 76 local VARNAME=$1 77 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 78 local VALUE="${!VARNAME}" 79 if [ -z "$VALUE" ] ; then 80 VALUE="__EMPTY__" 81 fi 82 echo "$VALUE" > $FILE 83} 84 85restore() { 86 local VARNAME=$1 87 local FILE="$PERSISTFILE_BASENAME-$VARNAME" 88 local VALUE="$(cat $FILE)" 89 [[ -z "$VALUE" ]] && die "Variable '$VARNAME' could not be restored." 90 if [ "$VALUE" == "__EMPTY__" ] ; then 91 VALUE="" 92 fi 93 eval "$VARNAME=\"$VALUE\"" 94} 95 96restore_if_unset() { 97 local VARNAME=$1 98 [[ -z "${!VARNAME}" ]] && restore "$VARNAME" 99} 100 101initial_environment_checks() { 102 # Cancel if this is not a git checkout. 103 [[ -d .git ]] \ 104 || die "This is not a git checkout, this script won't work for you." 105 106 # Cancel if EDITOR is unset or not executable. 107 [[ -n "$EDITOR" && -x "$(which $EDITOR)" ]] \ 108 || die "Please set your EDITOR environment variable, you'll need it." 109} 110 111common_prepare() { 112 # Check for a clean workdir. 113 [[ -z "$(git status -s -uno)" ]] \ 114 || die "Workspace is not clean. Please commit or undo your changes." 115 116 # Persist current branch. 117 CURRENT_BRANCH=$(git status -s -b -uno | grep "^##" | awk '{print $2}') 118 persist "CURRENT_BRANCH" 119 120 # Fetch unfetched revisions. 121 git svn fetch || die "'git svn fetch' failed." 122 123 # Get ahold of a safe temporary branch and check it out. 124 if [ "$CURRENT_BRANCH" != "$TEMP_BRANCH" ] ; then 125 delete_branch $TEMP_BRANCH 126 git checkout -b $TEMP_BRANCH 127 fi 128 129 # Delete the branch that will be created later if it exists already. 130 delete_branch $BRANCHNAME 131} 132 133common_cleanup() { 134 restore_if_unset "CURRENT_BRANCH" 135 git checkout -f $CURRENT_BRANCH 136 [[ "$TEMP_BRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TEMP_BRANCH 137 [[ "$BRANCHNAME" != "$CURRENT_BRANCH" ]] && git branch -D $BRANCHNAME 138 # Clean up all temporary files. 139 rm -f "$PERSISTFILE_BASENAME"* 140} 141 142# These two functions take a prefix for the variable names as first argument. 143read_and_persist_version() { 144 for v in MAJOR_VERSION MINOR_VERSION BUILD_NUMBER PATCH_LEVEL; do 145 VARNAME="$1${v%%_*}" 146 VALUE=$(grep "#define $v" "$VERSION_FILE" | awk '{print $NF}') 147 eval "$VARNAME=\"$VALUE\"" 148 persist "$VARNAME" 149 done 150} 151restore_version_if_unset() { 152 for v in MAJOR MINOR BUILD PATCH; do 153 restore_if_unset "$1$v" 154 done 155} 156 157upload_step() { 158 let CURRENT_STEP+=1 159 if [ $START_STEP -le $CURRENT_STEP ] ; then 160 echo ">>> Step $CURRENT_STEP: Upload for code review." 161 echo -n "Please enter the email address of a V8 reviewer for your patch: " 162 read REVIEWER 163 git cl upload -r "$REVIEWER" --send-mail \ 164 || die "'git cl upload' failed, please try again." 165 fi 166} 167 168wait_for_lgtm() { 169 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \ 170change. (If you need to iterate on the patch or double check that it's \ 171sane, do so in another shell, but remember to not change the headline of \ 172the uploaded CL." 173 unset ANSWER 174 while [ "$ANSWER" != "LGTM" ] ; do 175 [[ -n "$ANSWER" ]] && echo "That was not 'LGTM'." 176 echo -n "> " 177 read ANSWER 178 done 179} 180 181wait_for_resolving_conflicts() { 182 echo "Applying the patch \"$1\" failed. Either type \"ABORT<Return>\", or \ 183resolve the conflicts, stage *all* touched files with 'git add', and \ 184type \"RESOLVED<Return>\"" 185 unset ANSWER 186 while [ "$ANSWER" != "RESOLVED" ] ; do 187 [[ "$ANSWER" == "ABORT" ]] && die "Applying the patch failed." 188 [[ -n "$ANSWER" ]] && echo "That was not 'RESOLVED' or 'ABORT'." 189 echo -n "> " 190 read ANSWER 191 done 192} 193 194# Takes a file containing the patch to apply as first argument. 195apply_patch() { 196 git apply --index --reject $REVERSE_PATCH "$1" || \ 197 wait_for_resolving_conflicts "$1"; 198} 199