Sync to HEAD
[bpt/emacs.git] / admin / quick-install-emacs
CommitLineData
d9a88584
MB
1#!/bin/sh
2# quick-install-emacs -- do a halfway-decent job of installing emacs quickly
3# Written by Miles Bader <miles@gnu.org>
4
5# This script is mainly intended for emacs maintainer or pretesters who
6# install emacs very often. See the --help output for more details.
7
8PUBLIC_LIBSRC_BINARIES='b2m emacsclient etags ctags ebrowse'
9PUBLIC_LIBSRC_SCRIPTS='grep-changelog rcs-checkin'
10
6b61353c 11AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile makefile stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile testfile test-distrib"
d9a88584
MB
12
13# Prune old binaries lying around in the source tree
14PRUNE=no
15# Re-install files even if they already exist
16FORCE=no
17# Command verbose flag
18VERBOSE=''
19
20me="`basename $0`"
21
22# Install commands (these commands are also expected to understand the
23# GNU -v (--verbose) option)
24LINK='cp -lf'
25COPY='cp -f'
26REMOVE='rm -r'
27
28# Used to execute commands once once we create them
29EXEC='sh'
30MKDIR='mkdir --verbose -p'
31
32NAWK=/usr/bin/nawk
33
a819ec1a
MB
34# avoid non-standard command output from non-C locales
35unset LANG LC_ALL LC_MESSAGES
36
d9a88584
MB
37# Some messages
38USAGE="Usage: $me [OPTION...] BUILD_TREE [PREFIX]"
39TRY="Try "\`"$me --help' for more information."
40
41# Parse command-line options
42while :; do
43 case "$1" in
44 -n|--dry-run)
45 EXEC=cat; shift;;
46 -p|--prune)
47 PRUNE=yes; shift;;
48 -P|--no-prune)
49 PRUNE=no; shift;;
50 --prune-only)
51 PRUNE=only; shift;;
52 -f|--force)
53 FORCE=yes; shift;;
54 -v|--verbose)
55 VERBOSE="-v"; shift;;
56 --help)
57 cat <<EOF
58$USAGE
59Install emacs quickly
60
61 -n, --dry-run print installation commands instead of
62 executing them
63
64 -f, --force install even files that haven't changed
65 -v, --verbose print messages describing what is done
66
67 -p, --prune prune old generated files
68 -P, --no-prune don't prune old generated files (default)
69 --prune-only prune old generated files, but don't install
70
71 --help display this help and exit
72 --version output version information and exit
73
74$me install emacs \`incrementally,' that is, it will
75install only those files that have changed since the last time it was
76invoked, and remove any obsolete files from the installation
77directories. It also uses hard-links into the source and build trees to
78do the install, so it uses much less space than the default Makefile
79install target; however, this also means that $me can
80not install onto a disk partition other than the one on which the source
81and build directories reside.
82
83Optionally, $me can also remove old versions of
84automatically generated files that are version-specific (such as the
85versioned emacs executables in the \`src' directory, and the DOC-* files
86in the \`etc' directory). The latter action is called \`pruning,' and
87can be enabled using the \`-p' or \`--prune' options.
88EOF
89 exit 0
90 ;;
91 --version)
92 cat <<EOF
ca2135af 93$me 1.6
d9a88584
MB
94
95Written by Miles Bader <miles@gnu.org>
96EOF
97 exit 0
98 ;;
99 -[^-]?*)
100 # split concatenated single-letter options apart
101 FIRST="$1"; shift
102 set -- `echo $FIRST | sed 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
103 ;;
104 -*)
105 echo 1>&2 "$me: unrecognized option "\`"$1'"
106 echo 1>&2 "$TRY"
107 exit 1
108 ;;
109 *)
110 break;
111 esac
112done
113
114LINK_CMD="$LINK $VERBOSE"
115REMOVE_CMD="$REMOVE $VERBOSE"
116
117case $# in
118 1) BUILD="$1";;
119 2) BUILD="$1"; prefix="$2";;
120 *)
121 echo 1>&2 "$USAGE"
122 echo 1>&2 "$TRY"
123 exit 1
124 ;;
125esac
126
127if test ! -d "$BUILD"; then
128 echo 1>&2 "$me: $BUILD: Build tree not found"
129 exit 2
130elif test ! -r "$BUILD/config.status"; then
131 echo 1>&2 "$me: $BUILD: Not a proper build tree, config.status not found"
132 exit 2
133fi
134
135CONFIG_STATUS="$BUILD/config.status"
6b61353c
KH
136get_config_var ()
137{
6461c636 138 if ! sed -n "s/^s\(.\)@$1@\1\(.*\)\1.*$/\2/p" $CONFIG_STATUS | sed q | grep ''
d9a88584
MB
139 then
140 echo 1>&2 "$me: $1: Configuration variable not found in $CONFIG_STATUS"
141 exit 4
142 fi
143}
144
c5915370
MB
145test x"$SRC" = x && { SRC="`get_config_var srcdir`" || exit 4 ; }
146test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; }
c5915370 147test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; }
d9a88584 148
892de428
MB
149VERSION=`grep 'defconst[ ]*emacs-version' $SRC/lisp/version.el \
150 | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
151
d9a88584
MB
152DST_SHARE="$prefix/share/emacs/$VERSION"
153DST_BIN="$prefix/bin"
154DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
155DST_INFO="$prefix/info"
156
6b61353c
KH
157maybe_mkdir ()
158{
d9a88584
MB
159 if ! test -d "$1"; then
160 $MKDIR "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
161 fi
162}
163
164maybe_mkdir "$DST_BIN"
165maybe_mkdir "$DST_SHARE"
166maybe_mkdir "$DST_SHARE/site-lisp"
167maybe_mkdir "$DST_LIBEXEC"
168maybe_mkdir "$DST_INFO"
169
170( # start of command-generating sub-shell
171
172PRUNED=""
173if test x"$PRUNE" != xno; then
6461c636 174 for D in `ls -1t $BUILD/etc/DOC-* | sed 1d`; do
d9a88584
MB
175 echo $REMOVE_CMD $D
176 PRUNED="$PRUNED $D"
177 done
6461c636 178 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
d9a88584
MB
179 echo $REMOVE_CMD $D
180 PRUNED="$PRUNED $D"
181 done
d9a88584
MB
182fi
183
184test x"$PRUNE" = xonly && exit 0
185
6b61353c
KH
186maybe_emit_copy ()
187{
d9a88584
MB
188 if test "$FORCE" = yes || ! cmp -s $1 $2; then
189 echo $LINK_CMD $1 $2
190 fi
191}
192
193maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
194maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
195
196for F in $PUBLIC_LIBSRC_BINARIES; do
197 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
198done
199for F in $PUBLIC_LIBSRC_SCRIPTS; do
200 maybe_emit_copy $SRC/lib-src/$F $DST_BIN/$F
201done
202
203if test x"$SRC" = x"$BUILD"; then
204 PFXS="$BUILD"
205else
206 PFXS="$SRC $BUILD"
207fi
208
209for SUBDIR in lisp leim etc lib-src info; do
210 # defaults
211 SHARED=no
212 FORCED=''
213 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
214
215 # Set subdir-specific values
216 case $SUBDIR in
217 lisp|leim)
218 DST="$DST_SHARE/$SUBDIR"
219 ;;
220 etc)
221 DST="$DST_SHARE/$SUBDIR"
222 # COPYING is in the avoid list, but there should be a copy of it in
223 # the install etc dir, so make that here.
224 FORCED="$DST/COPYING"
225 ;;
226 lib-src)
227 DST="$DST_LIBEXEC"
228 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES $PUBLIC_LIBSRC_SCRIPTS)\$)" | tr ' ' '|'`"
229 ;;
230 info)
231 DST="$DST_INFO"
232 SHARED=yes
233 ;;
234 esac
235
236 for PFX in $PFXS; do
237 if [ -d $PFX/$SUBDIR ]; then
238 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
239 if [ -d $DST/$DIR ]; then
240 echo Directory $DST/$DIR exists
241 else
242 echo Directory $DST/$DIR non-existant
243 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
244 maybe_mkdir $DST/$DIR
245 fi
246 fi
247 done
248 diff -sqr $PFX/$SUBDIR $DST
249 fi
250 done | $NAWK '
251BEGIN {
252 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
253 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
254 dst_pat = "^'"$DST"'/"
255 dst_pfx = "'"$DST"'/"
256 avoid_pat = "'"$AVOID_PAT"'"
257 force = ("'"$FORCE"'" == "yes")
258 shared = ("'"$SHARED"'" == "yes")
259 init_bool_array(pruned, "'"$PRUNED"'")
260 init_bool_array(forced, "'"$FORCED"'")
261}
262function init_bool_array(array, string, a,k)
263{
264 split (string, a)
265 for (k in a)
266 array[a[k]] = 1
267}
268function install(src, dst)
269{
270 if (! (src in pruned)) {
271 cp[src] = dst;
272 from[dst] = src;
273 delete rm[dst];
274 }
275}
276function update(src, dst, copy)
277{
278 if (src in pruned) {
279 rm[dst] = 1;
280 delete from[dst]
281 } else {
282 if (copy)
283 cp[src] = dst;
284 from[dst] = src;
285 delete rm[dst];
286 }
287}
288function uninstall(dst)
289{
290 if (!(dst in from))
291 rm[dst] = 1;
292}
293/^Directory / {
294 if ($2 ~ avoid_pat) {
295 if ($NF == "exists")
296 uninstall($2)
297 } else
298 update(0, $2, 0)
299 next
300}
301/^Files / {
302 if ($4 ~ avoid_pat && !($4 in forced))
303 uninstall($4)
304 else if ($NF == "identical")
305 update($2, $4, force)
306 else
307 update($2, $4, 1)
308 next
309}
310/^Only / {
311 pfx = $3
312 sub (/:$/, "/", pfx)
313
314 if (pfx ~ dst_pat) {
315 if (! shared)
316 uninstall(pfx $4)
317 } else {
318 subdir = pfx
319 if (subdir ~ src_pat)
320 sub (src_pat, "", subdir)
321 else
322 sub (build_pat, "", subdir)
323
324 dst = dst_pfx subdir $4
325 if (! (dst ~ avoid_pat))
326 install(pfx $4, dst)
327 }
328 next
329}
330END {
331 for (f in rm)
332 print "'"$REMOVE_CMD"' " f
333 for (f in cp)
334 print "'"$LINK_CMD"' " f " " cp[f]
335}
336'
337done
338
339) | eval $EXEC
6b61353c
KH
340
341# arch-tag: 9322b572-9755-4cf7-a67a-21e6505f1477