git-push-all.sh 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #!/usr/bin/env bash
  2. # Usage: git-push-all.sh -t <test-branch-prefix> -r <remote-name> -s
  3. # -- <git-opts>
  4. # env vars: TOR_UPSTREAM_REMOTE_NAME=upstream TOR_PUSH_DELAY=0
  5. # git-opts: --no-atomic --dry-run (any other git push option)
  6. #
  7. # TOR_PUSH_DELAY pushes the master and maint branches separately, so that CI
  8. # runs in a sensible order.
  9. # push --atomic is the default when TOR_PUSH_DELAY=0, and for release branches.
  10. set -e
  11. #################
  12. # Configuration #
  13. #################
  14. # Don't change this configuration - set the env vars in your .profile
  15. #
  16. # git push command and default arguments
  17. GIT_PUSH=${TOR_GIT_PUSH:-"git push --atomic"}
  18. # The upstream remote which git.torproject.org/tor.git points to.
  19. DEFAULT_UPSTREAM_REMOTE=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
  20. # Push to a different upstream remote using -r <remote-name>
  21. UPSTREAM_REMOTE=${DEFAULT_UPSTREAM_REMOTE}
  22. # Add a delay between pushes, so CI runs on the most important branches first
  23. PUSH_DELAY=${TOR_PUSH_DELAY:-0}
  24. # Push (1) or skip (0) test branches that are the same as an upstream
  25. # maint/master branch. Push if you are testing that the CI environment still
  26. # works on old code, skip if you are testing new code in the branch.
  27. # Default: skip unchanged branches.
  28. # Inverted by the -s option.
  29. PUSH_SAME=${TOR_PUSH_SAME:-0}
  30. #######################
  31. # Argument processing #
  32. #######################
  33. # Controlled by the -t <test-branch-prefix> option. The test branch base
  34. # name option makes git-merge-forward.sh create new test branches:
  35. # <tbbn>_029, <tbbn>_035, ... , <tbbn>_master, and merge forward.
  36. TEST_BRANCH_PREFIX=
  37. while getopts ":r:st:" opt; do
  38. case "$opt" in
  39. r) UPSTREAM_REMOTE="$OPTARG"
  40. echo " *** PUSHING TO REMOTE: ${UPSTREAM_REMOTE} ***"
  41. shift
  42. shift
  43. OPTIND=$[$OPTIND - 2]
  44. ;;
  45. s) PUSH_SAME=$[! "$PUSH_SAME" ]
  46. if [ "$PUSH_SAME" -eq 0 ]; then
  47. echo " *** SKIPPING UNCHANGED TEST BRANCHES ***"
  48. else
  49. echo " *** PUSHING UNCHANGED TEST BRANCHES ***"
  50. fi
  51. shift
  52. OPTIND=$[$OPTIND - 1]
  53. ;;
  54. t) TEST_BRANCH_PREFIX="$OPTARG"
  55. echo " *** PUSHING TEST BRANCHES: ${TEST_BRANCH_PREFIX}_nnn ***"
  56. shift
  57. shift
  58. OPTIND=$[$OPTIND - 2]
  59. ;;
  60. *)
  61. # Assume we're done with script arguments,
  62. # and git push will handle the option
  63. break
  64. ;;
  65. esac
  66. done
  67. # getopts doesn't allow "-" as an option character,
  68. # so we have to handle -- manually
  69. if [ "$1" = "--" ]; then
  70. shift
  71. fi
  72. echo "Calling git push --atomic $@ <branches>"
  73. if [ "$TEST_BRANCH_PREFIX" ]; then
  74. if [ "$UPSTREAM_REMOTE" = ${TOR_UPSTREAM_REMOTE_NAME:-"upstream"} ]; then
  75. echo "Pushing test branches ${TEST_BRANCH_PREFIX}_nnn to " \
  76. "$UPSTREAM_REMOTE is not allowed."
  77. echo "Usage: $0 -r <remote-name> -t <test-branch-prefix> <git-opts>"
  78. exit 1
  79. fi
  80. fi
  81. ################################
  82. # Git upstream remote branches #
  83. ################################
  84. DEFAULT_UPSTREAM_BRANCHES=
  85. if [ "$DEFAULT_UPSTREAM_REMOTE" != "$UPSTREAM_REMOTE" ]; then
  86. DEFAULT_UPSTREAM_BRANCHES=`echo \
  87. ${DEFAULT_UPSTREAM_REMOTE}/master \
  88. ${DEFAULT_UPSTREAM_REMOTE}/{release,maint}-0.4.1 \
  89. ${DEFAULT_UPSTREAM_REMOTE}/{release,maint}-0.4.0 \
  90. ${DEFAULT_UPSTREAM_REMOTE}/{release,maint}-0.3.5 \
  91. ${DEFAULT_UPSTREAM_REMOTE}/{release,maint}-0.2.9 \
  92. `
  93. fi
  94. UPSTREAM_BRANCHES=`echo \
  95. ${UPSTREAM_REMOTE}/master \
  96. ${UPSTREAM_REMOTE}/{release,maint}-0.4.1 \
  97. ${UPSTREAM_REMOTE}/{release,maint}-0.4.0 \
  98. ${UPSTREAM_REMOTE}/{release,maint}-0.3.5 \
  99. ${UPSTREAM_REMOTE}/{release,maint}-0.2.9 \
  100. `
  101. ########################
  102. # Git branches to push #
  103. ########################
  104. PUSH_BRANCHES=$(echo \
  105. master \
  106. {release,maint}-0.4.1 \
  107. {release,maint}-0.4.0 \
  108. {release,maint}-0.3.5 \
  109. {release,maint}-0.2.9 \
  110. )
  111. if [ -z "$TEST_BRANCH_PREFIX" ]; then
  112. # maint/release push mode
  113. #
  114. # List of branches to push. Ordering is not important.
  115. PUSH_BRANCHES=$(echo \
  116. master \
  117. {release,maint}-0.4.1 \
  118. {release,maint}-0.4.0 \
  119. {release,maint}-0.3.5 \
  120. {release,maint}-0.2.9 \
  121. )
  122. else
  123. # Test branch mode: merge to maint only, and create a new branch for 0.2.9
  124. #
  125. # List of branches to push. Ordering is not important.
  126. PUSH_BRANCHES=$(echo \
  127. ${TEST_BRANCH_PREFIX}_master \
  128. ${TEST_BRANCH_PREFIX}_041 \
  129. ${TEST_BRANCH_PREFIX}_040 \
  130. ${TEST_BRANCH_PREFIX}_035 \
  131. ${TEST_BRANCH_PREFIX}_029 \
  132. )
  133. fi
  134. ###############
  135. # Entry point #
  136. ###############
  137. # Skip the test branches that are the same as the upstream branches
  138. if [ "$PUSH_SAME" -eq 0 -a "$TEST_BRANCH_PREFIX" ]; then
  139. NEW_PUSH_BRANCHES=
  140. for b in $PUSH_BRANCHES; do
  141. PUSH_COMMIT=`git rev-parse $b`
  142. SKIP_UPSTREAM=
  143. for u in $DEFAULT_UPSTREAM_BRANCHES $UPSTREAM_BRANCHES; do
  144. UPSTREAM_COMMIT=`git rev-parse "$u"`
  145. if [ "$PUSH_COMMIT" = "$UPSTREAM_COMMIT" ]; then
  146. SKIP_UPSTREAM="$u"
  147. fi
  148. done
  149. if [ "$SKIP_UPSTREAM" ]; then
  150. printf "Skipping unchanged: %s remote: %s\n" \
  151. "$b" "$SKIP_UPSTREAM"
  152. else
  153. if [ "$NEW_PUSH_BRANCHES" ]; then
  154. NEW_PUSH_BRANCHES="${NEW_PUSH_BRANCHES} ${b}"
  155. else
  156. NEW_PUSH_BRANCHES="${b}"
  157. fi
  158. fi
  159. done
  160. PUSH_BRANCHES=${NEW_PUSH_BRANCHES}
  161. fi
  162. if [ "$PUSH_DELAY" -le 0 ]; then
  163. echo "Pushing $PUSH_BRANCHES"
  164. # We know that there are no spaces in any branch within $PUSH_BRANCHES, so
  165. # it is safe to use it unquoted. (This also applies to the other shellcheck
  166. # exceptions below.)
  167. #
  168. # Push all the branches at the same time
  169. # shellcheck disable=SC2086
  170. $GIT_PUSH "$@" "$UPSTREAM_REMOTE" $PUSH_BRANCHES
  171. else
  172. # Push the branches in optimal CI order, with a delay between each push
  173. PUSH_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | sort -V)
  174. MASTER_BRANCH=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep master)
  175. if [ -z "$TEST_BRANCH_PREFIX" ]; then
  176. MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep maint)
  177. RELEASE_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep release | \
  178. tr "\n" " ")
  179. printf "Pushing with %ss delays, so CI runs in this order:\n%s\n%s\n%s\n" \
  180. "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES" "$RELEASE_BRANCHES"
  181. else
  182. # Actually test branches based on maint branches
  183. MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\n" | grep -v master)
  184. printf "Pushing with %ss delays, so CI runs in this order:\n%s\n%s\n" \
  185. "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES"
  186. # No release branches
  187. RELEASE_BRANCHES=
  188. fi
  189. $GIT_PUSH "$@" "$UPSTREAM_REMOTE" "$MASTER_BRANCH"
  190. sleep "$PUSH_DELAY"
  191. # shellcheck disable=SC2086
  192. for b in $MAINT_BRANCHES; do
  193. $GIT_PUSH "$@" "$UPSTREAM_REMOTE" "$b"
  194. sleep "$PUSH_DELAY"
  195. done
  196. if [ "$RELEASE_BRANCHES" ]; then
  197. # shellcheck disable=SC2086
  198. $GIT_PUSH "$@" "$UPSTREAM_REMOTE" $RELEASE_BRANCHES
  199. fi
  200. fi