; doc/emacs/misc.texi (Network Security): Fix typo.
[emacs.git] / admin / automerge
blobe88711f8d6dd0b37be4214d3225bafd1eee8c98f
1 #!/bin/bash
2 ### automerge - automatically merge the Emacs release branch to master
4 ## Copyright (C) 2018 Free Software Foundation, Inc.
6 ## Author: Glenn Morris <rgm@gnu.org>
8 ## This file is part of GNU Emacs.
10 ## GNU Emacs is free software: you can redistribute it and/or modify
11 ## it under the terms of the GNU General Public License as published by
12 ## the Free Software Foundation, either version 3 of the License, or
13 ## (at your option) any later version.
15 ## GNU Emacs is distributed in the hope that it will be useful,
16 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ## GNU General Public License for more details.
20 ## You should have received a copy of the GNU General Public License
21 ## along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
23 ### Commentary:
25 ## Automatically merge the Emacs release branch to master.
26 ## If the merge succeeds, optionally build and test the results,
27 ## and then push it.
28 ## Intended usage:
29 ## Have a dedicated git directory just for this.
30 ## Have a cron job that calls this script with -r -p.
32 ## Modifying a running shell script can have unpredictable results,
33 ## so the paranoid will first make a copy of this script, and then run
34 ## it with the -d option in the repository directory, in case a pull
35 ## updates this script while it is working.
37 die () # write error to stderr and exit
39 [ $# -gt 0 ] && echo "$PN: $@" >&2
40 exit 1
43 PN=${0##*/} # basename of script
44 PD=${0%/*}
46 [ "$PD" = "$0" ] && PD=. # if PATH includes PWD
48 usage ()
50 cat 1>&2 <<EOF
51 Usage: ${PN} [-b] [-d] [-e emacs] [-n nmin] [-p] [-r] [-t] [-- mflags]
52 Merge the Emacs release branch to master.
53 Passes any non-option args to make (eg -- -j2).
54 Options:
55 -d: no initial cd to parent of script directory
56 -e: Emacs executable to use for the initial merge (default $emacs)
57 -n: minimum number of commits to try merging (default $nmin)
58 -b: try to build after merging
59 -t: try to check after building
60 -p: if merge, build, check all succeed, push when finished (caution!)
61 -r: start by doing a hard reset (caution!) and pull
62 EOF
63 exit 1
67 ## Defaults.
69 emacs=emacs
70 nmin=10
71 build=
72 test=
73 push=
74 quiet=
75 reset=
76 nocd=
78 while getopts ":hbde:n:pqrt" option ; do
79 case $option in
80 (h) usage ;;
82 (b) build=1 ;;
84 (d) nocd=1 ;;
86 (e) emacs=$OPTARG ;;
88 (n) nmin=$OPTARG ;;
90 (p) push=1 ;;
92 (q) quiet=1 ;;
94 (r) reset=1 ;;
96 (t) test=1 ;;
98 (\?) die "Bad option -$OPTARG" ;;
100 (:) die "Option -$OPTARG requires an argument" ;;
102 (*) die "getopts error" ;;
103 esac
104 done
105 shift $(( --OPTIND ))
106 OPTIND=1
109 [ "$nocd" ] || {
110 cd $PD # this should be the admin directory
111 cd ../
114 [ -d admin ] || die "Could not locate admin directory"
116 [ -e .git ] || die "No .git"
119 ## Does not work 100% because a lot of Emacs batch output comes on
120 ## stderr (?).
121 [ "$quiet" ] && exec 1> /dev/null
124 [ "$push" ] && test=1
125 [ "$test" ] && build=1
128 tempfile=/tmp/$PN.$$
130 trap "rm -f $tempfile 2> /dev/null" EXIT
133 [ -e Makefile ] && [ "$build" ] && {
134 echo "Cleaning..."
135 make maintainer-clean >& /dev/null
139 [ "$reset" ] && {
140 echo "Resetting..."
141 git reset -q --hard origin/master || die "reset error"
143 echo "Pulling..."
144 git pull -q --ff-only || die "pull error"
148 rev=$(git rev-parse HEAD)
150 [ $(git rev-parse @{u}) = $rev ] || die "Local state does not match origin"
153 merge ()
155 echo "Merging..."
157 if $emacs --batch -Q -l ./admin/gitmerge.el \
158 --eval "(setq gitmerge-minimum-missing $nmin)" -f gitmerge \
159 >| $tempfile 2>&1; then
160 echo "merged ok"
161 return 0
163 else
164 grep -E "Nothing to merge|Number of missing commits" $tempfile && \
165 exit 0
167 cat "$tempfile" 1>&2
169 die "merge error"
174 merge
177 [ "$build" ] || exit 0
180 echo "Running autoreconf..."
182 autoreconf -i -I m4 2>| $tempfile
184 retval=$?
186 ## Annoyingly, autoreconf puts the "installing `./foo' messages on stderr.
187 if [ "$quiet" ]; then
188 grep -v 'installing `\.' $tempfile 1>&2
189 else
190 cat "$tempfile" 1>&2
193 [ $retval -ne 0 ] && die "autoreconf error"
196 echo "Running ./configure..."
198 ## Minimize required packages.
199 ./configure --without-x || die "configure error"
202 echo "Building..."
204 make "$@" || die "make error"
206 echo "Build finished ok"
209 [ "$test" ] || exit 0
212 echo "Testing..."
214 ## We just want a fast pass/fail, we don't want to debug.
215 make "$@" check TEST_LOAD_EL=no || die "check error"
217 echo "Tests finished ok"
220 [ "$push" ] || exit 0
223 ## In case someone else pushed while we were working.
224 echo "Checking for remote changes..."
225 git fetch || die "fetch error"
227 [ $(git rev-parse @{u}) = $rev ] || {
229 echo "Upstream has changed"
231 ## Rebasing would be incorrect, since it would rewrite the
232 ## (already published) release branch commits.
233 ## Ref eg http://lists.gnu.org/r/emacs-devel/2014-12/msg01435.html
234 ## Instead, we throw away what we just did, and do the merge again.
235 echo "Resetting..."
236 git reset --hard $rev
238 echo "Pulling..."
239 git pull --ff-only || die "pull error"
241 merge
243 ## If the merge finished ok again, we don't bother doing a second
244 ## build and test.
247 echo "Pushing..."
248 git push || die "push error"
251 exit 0
253 ### automerge ends here