commit 667311ebbd6fe6c43da8eb5abc1e34e30fb5b911 Author: teor teor@torproject.org Date: Fri Aug 9 00:18:56 2019 +1000
scripts/git: Add test branch support to the git scripts
Add a -t <test-branch-prefix> argument to git-merge-forward.sh and git-push-all.sh, which makes these scripts create, merge forward, and push test branches.
Add a -r <remote-name> argument to git-push-all.sh, so the script can push test branches to a personal remote.
Closes ticket 31314. --- changes/ticket31314 | 6 ++ scripts/git/git-merge-forward.sh | 150 +++++++++++++++++++++++++++++++++------ scripts/git/git-push-all.sh | 94 +++++++++++++++++++++--- 3 files changed, 218 insertions(+), 32 deletions(-)
diff --git a/changes/ticket31314 b/changes/ticket31314 new file mode 100644 index 000000000..e1d9fb767 --- /dev/null +++ b/changes/ticket31314 @@ -0,0 +1,6 @@ + o Minor features (git scripts): + - Add a -t <test-branch-prefix> argument to git-merge-forward.sh and + git-push-all.sh, which makes these scripts create, merge forward, and + push test branches. Closes ticket 31314. + - Add a -r <remote-name> argument to git-push-all.sh, so the script can + push test branches to a personal remote. Closes ticket 31314. diff --git a/scripts/git/git-merge-forward.sh b/scripts/git/git-merge-forward.sh index e2b5bde49..1f4ddb85e 100755 --- a/scripts/git/git-merge-forward.sh +++ b/scripts/git/git-merge-forward.sh @@ -33,20 +33,45 @@ TOR_WKT_NAME=${TOR_WKT_NAME:-"tor-wkt"} # Configuration of the branches that needs merging. The values are in order: # (0) current maint/release branch name # (1) previous maint/release name to merge into (0) +# (only used in merge forward mode) # (2) Full path of the git worktree +# (3) current branch suffix +# (maint branches only, only used in test branch mode) +# (4) previous test branch suffix to merge into (3) +# (maint branches only, only used in test branch mode) # -# As an example: +# Merge forward example: # $ cd <PATH/TO/WORKTREE> (2) # $ git checkout maint-0.3.5 (0) # $ git pull # $ git merge maint-0.3.4 (1) # +# Test branch example: +# $ cd <PATH/TO/WORKTREE> (2) +# $ git checkout -b ticket99999_035 (3) +# $ git checkout maint-0.3.5 (0) +# $ git pull +# $ git checkout ticket99999_035 +# $ git merge maint-0.3.5 +# $ git merge ticket99999_034 (4) +# # First set of arrays are the maint-* branch and then the release-* branch. # New arrays need to be in the WORKTREE= array else they aren't considered. -MAINT_035=( "maint-0.3.5" "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" ) -MAINT_040=( "maint-0.4.0" "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.0" ) -MAINT_041=( "maint-0.4.1" "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.1" ) -MAINT_MASTER=( "master" "maint-0.4.1" "$GIT_PATH/$TOR_MASTER_NAME" ) +# +# Only used in test branch mode +# There is no previous branch to merge forward, so the second and fifth items +# must be blank ("") +MAINT_029_TB=( "maint-0.2.9" "" "$GIT_PATH/$TOR_WKT_NAME/maint-0.2.9" \ + "_029" "") +# Used in maint/release merge and test branch modes +MAINT_035=( "maint-0.3.5" "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" \ + "_035" "_029") +MAINT_040=( "maint-0.4.0" "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.0" \ + "_040" "_035") +MAINT_041=( "maint-0.4.1" "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.1" \ + "_041" "_040") +MAINT_MASTER=( "master" "maint-0.4.1" "$GIT_PATH/$TOR_MASTER_NAME" \ + "_master" "_041")
RELEASE_029=( "release-0.2.9" "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/release-0.2.9" ) RELEASE_035=( "release-0.3.5" "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/release-0.3.5" ) @@ -60,6 +85,7 @@ ORIGIN_PATH="$GIT_PATH/$TOR_MASTER_NAME"
# SC2034 -- shellcheck thinks that these are unused. We know better. ACTUALLY_THESE_ARE_USED=<<EOF +${MAINT_029_TB[0]} ${MAINT_035[0]} ${MAINT_040[0]} ${MAINT_041[0]} @@ -78,11 +104,19 @@ EOF # that would have been executed for each worktree. DRY_RUN=0
-while getopts "n" opt; do +# Controlled by the -t <test-branch-prefix> option. The test branch base +# name option makes git-merge-forward.sh create new test branches: +# <tbbn>_029, <tbbn>_035, ... , <tbbn>_master, and merge forward. +TEST_BRANCH_PREFIX= + +while getopts "nt:" opt; do case "$opt" in n) DRY_RUN=1 echo " *** DRY RUN MODE ***" ;; + t) TEST_BRANCH_PREFIX="$OPTARG" + echo " *** CREATING TEST BRANCHES: ${TEST_BRANCH_PREFIX}_nnn ***" + ;; *) exit 1 ;; @@ -93,22 +127,44 @@ done # Git worktrees to manage # ###########################
-# List of all worktrees to work on. All defined above. Ordering is important. -# Always the maint-* branch BEFORE then the release-*. -WORKTREE=( - RELEASE_029[@] +if [ -z "$TEST_BRANCH_PREFIX" ]; then + + # maint/release merge mode + # + # List of all worktrees to work on. All defined above. Ordering is important. + # Always the maint-* branch BEFORE then the release-*. + WORKTREE=( + RELEASE_029[@] + + MAINT_035[@] + RELEASE_035[@] + + MAINT_040[@] + RELEASE_040[@] + + MAINT_041[@] + RELEASE_041[@] + + MAINT_MASTER[@] + ) + +else + + # Test branch mode: merge to maint only, and create a new branch for 0.2.9 + WORKTREE=( + MAINT_029_TB[@] + + MAINT_035[@]
- MAINT_035[@] - RELEASE_035[@] + MAINT_040[@]
- MAINT_040[@] - RELEASE_040[@] + MAINT_041[@]
- MAINT_041[@] - RELEASE_041[@] + MAINT_MASTER[@] + ) + +fi
- MAINT_MASTER[@] -) COUNT=${#WORKTREE[@]}
############# @@ -161,6 +217,19 @@ function switch_branch fi }
+# Checkout a new branch with the given branch name. +function new_branch +{ + local cmd="git checkout -b $1" + printf " %s Creating new branch %s..." "$MARKER" "$1" + if [ $DRY_RUN -eq 0 ]; then + msg=$( eval "$cmd" 2>&1 ) + validate_ret $? "$msg" + else + printf "\n %s\n" "${IWTH}$cmd${CNRM}" + fi +} + # Pull the given branch name. function pull_branch { @@ -236,16 +305,51 @@ for ((i=0; i<COUNT; i++)); do current=${!WORKTREE[$i]:0:1} previous=${!WORKTREE[$i]:1:1} repo_path=${!WORKTREE[$i]:2:1} + # default to merge forward mode + test_current= + test_previous= + target_current="$current" + target_previous="$previous" + if [ "$TEST_BRANCH_PREFIX" ]; then + test_current_suffix=${!WORKTREE[$i]:3:1} + test_current=${TEST_BRANCH_PREFIX}${test_current_suffix} + # the current test branch, if present, or maint/release branch, if not + target_current="$test_current" + test_previous_suffix=${!WORKTREE[$i]:4:1} + if [ "$test_previous_suffix" ]; then + test_previous=${TEST_BRANCH_PREFIX}${test_previous_suffix} + # the previous test branch, if present, or maint/release branch, if not + target_previous="$test_previous" + fi + fi
- printf "%s Handling branch \n" "$MARKER" "${BYEL}$current${CNRM}" + printf "%s Handling branch \n" "$MARKER" "${BYEL}$target${CNRM}"
# Go into the worktree to start merging. goto_repo "$repo_path" - # Checkout the current branch + if [ "$test_current" ]; then + # Create a test branch from the currently checked-out branch/commit + new_branch "$test_current" + fi + # Checkout the current maint/release branch switch_branch "$current" - # Update the current branch with an origin merge to get the latest. + # Update the current maint/release branch with an origin merge to get the + # latest updates merge_branch_origin "$current" - # Example: + if [ "$test_current" ]; then + # Checkout the test branch + switch_branch "$test_current" + # Merge the updated maint branch into the test branch + merge_branch "$current" "$test_current" + fi + # Merge the previous branch into the target branch + # Merge Forward Example: # merge maint-0.2.9 into maint-0.3.5. - merge_branch "$previous" "$current" + # Test Branch Example: + # merge bug99999_029 into bug99999_035. + # Skip the merge if the previous branch does not exist + # (there's nothing to merge forward into the oldest test branch) + if [ "$target_previous" ]; then + merge_branch "$target_previous" "$target_current" + fi done diff --git a/scripts/git/git-push-all.sh b/scripts/git/git-push-all.sh index 617f24cdc..f3bbe8b77 100755 --- a/scripts/git/git-push-all.sh +++ b/scripts/git/git-push-all.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash
-# Usage: git-push-all.sh <git-opts> +# Usage: git-push-all.sh -t <test-branch-prefix> -r <remote-name> <git-opts> # env vars: TOR_UPSTREAM_REMOTE_NAME=upstream TOR_PUSH_DELAY=0 # git-opts: --no-atomic --dry-run (any other git push option) # @@ -17,10 +17,49 @@ set -e # Don't change this configuration - set the env vars in your .profile # # The upstream remote which git.torproject.org/tor.git points to. +# In test branch mode, override this setting with -r <remote-name> UPSTREAM_REMOTE=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"} # Add a delay between pushes, so CI runs on the most important branches first PUSH_DELAY=${TOR_PUSH_DELAY:-0}
+####################### +# Argument processing # +####################### + +# Controlled by the -t <test-branch-prefix> option. The test branch base +# name option makes git-merge-forward.sh create new test branches: +# <tbbn>_029, <tbbn>_035, ... , <tbbn>_master, and merge forward. +TEST_BRANCH_PREFIX= + +while getopts ":r:t:" opt; do + case "$opt" in + r) UPSTREAM_REMOTE="$OPTARG" + echo " *** PUSHING TO REMOTE: ${UPSTREAM_REMOTE} ***" + shift + shift + OPTIND=$[$OPTIND - 2] + ;; + t) TEST_BRANCH_PREFIX="$OPTARG" + echo " *** PUSHING TEST BRANCHES: ${TEST_BRANCH_PREFIX}_nnn ***" + shift + shift + OPTIND=$[$OPTIND - 2] + ;; + *) + # Assume git push will handle the option + ;; + esac +done + +if [ "$TEST_BRANCH_PREFIX" ]; then + if [ "$UPSTREAM_REMOTE" = ${TOR_UPSTREAM_REMOTE_NAME:-"upstream"} ]; then + echo "Pushing test branches ${TEST_BRANCH_PREFIX}_nnn to " \ + "$UPSTREAM_REMOTE is not allowed." + echo "Usage: $0 -r <remote-name> -t <test-branch-prefix> <git-opts>" + exit 1 + fi +fi + ######################## # Git branches to push # ######################## @@ -33,6 +72,32 @@ PUSH_BRANCHES=$(echo \ {release,maint}-0.2.9 \ )
+if [ -z "$TEST_BRANCH_PREFIX" ]; then + + # maint/release push mode + # + # List of branches to push. Ordering is not important. + PUSH_BRANCHES=$(echo \ + master \ + {release,maint}-0.4.1 \ + {release,maint}-0.4.0 \ + {release,maint}-0.3.5 \ + {release,maint}-0.2.9 \ + ) +else + + # Test branch mode: merge to maint only, and create a new branch for 0.2.9 + # + # List of branches to push. Ordering is not important. + PUSH_BRANCHES=$(echo \ + ${TEST_BRANCH_PREFIX}_master \ + ${TEST_BRANCH_PREFIX}_041 \ + ${TEST_BRANCH_PREFIX}_040 \ + ${TEST_BRANCH_PREFIX}_035 \ + ${TEST_BRANCH_PREFIX}_029 \ + ) +fi + ############### # Entry point # ############### @@ -48,18 +113,29 @@ if [ "$PUSH_DELAY" -le 0 ]; then else PUSH_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | sort -V) MASTER_BRANCH=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep master) - MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep maint) - RELEASE_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep release | \ - tr "\n" " ") - printf "Pushing with %ss delays, so CI runs in this order:\n%s\n%s\n%s\n" \ - "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES" "$RELEASE_BRANCHES" + if [ -z "$TEST_BRANCH_PREFIX" ]; then + MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep maint) + RELEASE_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep release | \ + tr "\n" " ") + printf "Pushing with %ss delays, so CI runs in this order:\n%s\n%s\n%s\n" \ + "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES" "$RELEASE_BRANCHES" + else + # Actually test branches based on maint branches + MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep -v master) + printf "Pushing with %ss delays, so CI runs in this order:\n%s\n%s\n" \ + "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES" + # No release branches + RELEASE_BRANCHES= + fi git push "$@" "$UPSTREAM_REMOTE" "$MASTER_BRANCH" sleep "$PUSH_DELAY" # shellcheck disable=SC2086 for b in $MAINT_BRANCHES; do - git push "$@" "$UPSTREAM_REMOTE" $b + git push "$@" "$UPSTREAM_REMOTE" "$b" sleep "$PUSH_DELAY" done - # shellcheck disable=SC2086 - git push --atomic "$@" "$UPSTREAM_REMOTE" $RELEASE_BRANCHES + if [ "$RELEASE_BRANCHES" ]; then + # shellcheck disable=SC2086 + git push --atomic "$@" "$UPSTREAM_REMOTE" $RELEASE_BRANCHES + fi fi