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