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