* lisp/emacs-lisp/package.el (package-menu--perform-transaction):
[emacs.git] / admin / quick-install-emacs
blob911b39b4f60a30f99bef2529088d9f15797c8ef4
1 #!/bin/sh
2 ### quick-install-emacs --- do a halfway-decent job of installing emacs quickly
4 ## Copyright (C) 2001-2015 Free Software Foundation, Inc.
6 ## Author: Miles Bader <miles@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 <http://www.gnu.org/licenses/>.
24 ### Commentary:
26 ## This script is mainly intended for emacs maintainer or pretesters who
27 ## install emacs very often. See the --help output for more details.
30 PUBLIC_LIBSRC_BINARIES='emacsclient etags ctags ebrowse'
32 AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile$ Makefile.in$ makefile$ makefile.w32-in$ stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile"
34 # Prune old binaries lying around in the source tree
35 PRUNE=no
36 # Re-install files even if they already exist
37 FORCE=no
38 # Command verbose flag
39 VERBOSE=''
41 me="`basename $0`"
43 # Install commands (if the user specifies the `--verbose' option, it is
44 # passed to these commands, so that feature only works if these commands
45 # implement it too)
46 LINK='cp -lf'
47 COPY='cp -f'
48 REMOVE='rm -r'
49 MKDIR='mkdir -p'
51 # Used to execute commands once we create them
52 EXEC='sh'
54 NAWK=/usr/bin/nawk
56 # avoid non-standard command output from non-C locales
57 unset LANG LC_ALL LC_MESSAGES
59 # Some messages
60 USAGE="Usage: $me [OPTION...] BUILD_TREE [PREFIX]"
61 TRY="Try "\`"$me --help' for more information."
63 # Parse command-line options
64 while :; do
65 case "$1" in
66 -n|--dry-run)
67 EXEC=cat; shift;;
68 -p|--prune)
69 PRUNE=yes; shift;;
70 -P|--no-prune)
71 PRUNE=no; shift;;
72 --prune-only)
73 PRUNE=only; shift;;
74 -f|--force)
75 FORCE=yes; shift;;
76 -v|--verbose)
77 VERBOSE="-v"; shift;;
78 --help)
79 cat <<EOF
80 $USAGE
81 Install emacs quickly
83 -n, --dry-run print installation commands instead of
84 executing them
86 -f, --force install even files that haven't changed
87 -v, --verbose print messages describing what is done
89 -p, --prune prune old generated files
90 -P, --no-prune don't prune old generated files (default)
91 --prune-only prune old generated files, but don't install
93 --help display this help and exit
94 --version output version information and exit
96 $me install emacs \`incrementally,' that is, it will
97 install only those files that have changed since the last time it was
98 invoked, and remove any obsolete files from the installation
99 directories. It also uses hard-links into the source and build trees to
100 do the install, so it uses much less space than the default Makefile
101 install target; however, this also means that $me can
102 not install onto a disk partition other than the one on which the source
103 and build directories reside.
105 Optionally, $me can also remove old versions of
106 automatically generated files that are version-specific (such as the
107 versioned emacs executables in the \`src' directory).
108 The latter action is called \`pruning,' and
109 can be enabled using the \`-p' or \`--prune' options.
111 exit 0
113 --version)
114 cat <<EOF
115 $me 1.6
117 Written by Miles Bader <miles@gnu.org>
119 exit 0
121 -[!-]?*)
122 # split concatenated single-letter options apart
123 FIRST="$1"; shift
124 set -- `echo $FIRST | sed 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
127 echo 1>&2 "$me: unrecognized option "\`"$1'"
128 echo 1>&2 "$TRY"
129 exit 1
132 break;
133 esac
134 done
136 LINK_CMD="$LINK $VERBOSE"
137 REMOVE_CMD="$REMOVE $VERBOSE"
139 case $# in
140 1) BUILD="$1";;
141 2) BUILD="$1"; prefix="$2";;
143 echo 1>&2 "$USAGE"
144 echo 1>&2 "$TRY"
145 exit 1
147 esac
149 if test ! -d "$BUILD"; then
150 echo 1>&2 "$me: $BUILD: Build tree not found"
151 exit 2
152 elif test ! -r "$BUILD/config.status"; then
153 echo 1>&2 "$me: $BUILD: Not a proper build tree, config.status not found"
154 exit 2
157 CONFIG_STATUS="$BUILD/config.status"
158 get_config_var ()
160 { sed -n "s/^S[[]\"$1\"[]]=\"\([^\"]*\)\"/\1/p" $CONFIG_STATUS | sed q | grep ''; } ||
161 { sed -n "s/^s\(.\)@$1@\1\(|#_!!_#|\)*\(.*\)\1.*$/\3/p" $CONFIG_STATUS | sed q | grep ''; } ||
163 echo 1>&2 "$me: $1: Configuration variable not found in $CONFIG_STATUS"
164 exit 4
168 test x"$SRC" = x && { SRC="`get_config_var srcdir`" || exit 4 ; }
169 test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; }
170 test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; }
172 VERSION=`
173 sed -n 's/^AC_INIT(emacs,[ ]*\([^ )]*\).*/\1/p' <$SRC/configure.ac
174 ` || exit 4
175 test -n "$VERSION" || { echo >&2 "$me: no version in configure.ac"; exit 4; }
177 DST_SHARE="$prefix/share/emacs/$VERSION"
178 DST_BIN="$prefix/bin"
179 DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
181 # There are various common places for the info dir to be, so try to
182 # use whatever's already there, defaulting to (and preferring)
183 # .../share/info.
185 DST_INFO=''
186 for D in "$prefix/share/info" "$prefix/info"; do
187 if test -d "$D"; then
188 DST_INFO="$D"
189 break
191 done
192 DST_INFO=${DST_INFO:-"$prefix/share/info"}
194 maybe_mkdir ()
196 if ! test -d "$1"; then
197 $MKDIR $VERBOSE "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
201 maybe_mkdir "$DST_BIN"
202 maybe_mkdir "$DST_SHARE"
203 maybe_mkdir "$DST_SHARE/site-lisp"
204 maybe_mkdir "$DST_LIBEXEC"
205 maybe_mkdir "$DST_INFO"
207 ( # start of command-generating sub-shell
209 PRUNED=""
210 if test x"$PRUNE" != xno; then
211 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
212 echo $REMOVE_CMD $D
213 PRUNED="$PRUNED $D"
214 done
217 test x"$PRUNE" = xonly && exit 0
219 maybe_emit_copy ()
221 if test "$FORCE" = yes || ! cmp -s $1 $2; then
222 echo $LINK_CMD $1 $2
226 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
227 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
229 for F in $PUBLIC_LIBSRC_BINARIES; do
230 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
231 done
233 if test x"$SRC" = x"$BUILD"; then
234 PFXS="$BUILD"
235 else
236 PFXS="$SRC $BUILD"
239 for SUBDIR in lisp leim etc lib-src info; do
240 # defaults
241 SHARED=no
242 FORCED=''
243 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
245 # Set subdir-specific values
246 case $SUBDIR in
247 lisp|leim)
248 DST="$DST_SHARE/$SUBDIR"
250 etc)
251 DST="$DST_SHARE/$SUBDIR"
252 # COPYING is in the avoid list, but there should be a copy of it in
253 # the install etc dir, so make that here.
254 FORCED="$DST/COPYING"
256 lib-src)
257 DST="$DST_LIBEXEC"
258 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES)\$)" | tr ' ' '|'`"
260 info)
261 DST="$DST_INFO"
262 SHARED=yes
264 esac
266 for PFX in $PFXS; do
267 if [ -d $PFX/$SUBDIR ]; then
268 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
269 if [ -d $DST/$DIR ]; then
270 echo Directory $DST/$DIR exists
271 else
272 echo Directory $DST/$DIR non-existent
273 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
274 maybe_mkdir $DST/$DIR
277 done
278 diff -sqr $PFX/$SUBDIR $DST
280 done | $NAWK '
281 BEGIN {
282 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
283 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
284 dst_pat = "^'"$DST"'/"
285 dst_pfx = "'"$DST"'/"
286 avoid_pat = "'"$AVOID_PAT"'"
287 force = ("'"$FORCE"'" == "yes")
288 shared = ("'"$SHARED"'" == "yes")
289 init_bool_array(pruned, "'"$PRUNED"'")
290 init_bool_array(forced, "'"$FORCED"'")
292 function init_bool_array(array, string, a,k)
294 split (string, a)
295 for (k in a)
296 array[a[k]] = 1
298 function install(src, dst)
300 if (! (src in pruned)) {
301 cp[src] = dst;
302 from[dst] = src;
303 delete rm[dst];
306 function update(src, dst, copy)
308 if (src in pruned) {
309 rm[dst] = 1;
310 delete from[dst]
311 } else {
312 if (copy)
313 cp[src] = dst;
314 from[dst] = src;
315 delete rm[dst];
318 function uninstall(dst)
320 if (!(dst in from))
321 rm[dst] = 1;
323 /^Directory / {
324 if ($2 ~ avoid_pat) {
325 if ($NF == "exists")
326 uninstall($2)
327 } else
328 update(0, $2, 0)
329 next
331 /^Files / {
332 if ($4 ~ avoid_pat && !($4 in forced))
333 uninstall($4)
334 else if ($NF == "identical")
335 update($2, $4, force)
336 else
337 update($2, $4, 1)
338 next
340 /^Only / {
341 pfx = $3
342 sub (/:$/, "/", pfx)
344 if (pfx ~ dst_pat) {
345 if (! shared)
346 uninstall(pfx $4)
347 } else {
348 subdir = pfx
349 if (subdir ~ src_pat)
350 sub (src_pat, "", subdir)
351 else
352 sub (build_pat, "", subdir)
354 dst = dst_pfx subdir $4
355 if (! (dst ~ avoid_pat))
356 install(pfx $4, dst)
358 next
360 END {
361 for (f in rm)
362 print "'"$REMOVE_CMD"' " f
363 for (f in cp)
364 print "'"$LINK_CMD"' " f " " cp[f]
367 done
369 ) | eval $EXEC