bootstrap: uses rsync to download the .po files
[platform/upstream/coreutils.git] / bootstrap
1 #! /bin/sh
2
3 # Bootstrap this package from checked-out sources.
4
5 # Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 # Written by Paul Eggert.
21
22 nl='
23 '
24
25 # Ensure file names are sorted consistently across platforms.
26 # Also, ensure diagnostics are in English, e.g., "wget --help" below.
27 LC_ALL=C
28 export LC_ALL
29
30 local_gl_dir=gl
31
32 # Temporary directory names.
33 bt='._bootmp'
34 bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
35 bt2=${bt}2
36
37 usage() {
38   echo >&2 "\
39 Usage: $0 [OPTION]...
40 Bootstrap this package from the checked-out sources.
41
42 Options:
43  --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
44                           sources reside.  Use this if you already
45                           have gnulib sources on your machine, and
46                           do not want to waste your bandwidth downloading
47                           them again.
48  --copy                   Copy files instead of creating symbolic links.
49  --force                  Attempt to bootstrap even if the sources seem
50                           not to have been checked out.
51  --skip-po                Do not download po files.
52  --cvs-user=USERNAME      Set the username to use when checking out
53                           sources from the gnulib repository.
54
55 If the file bootstrap.conf exists in the current working directory, its
56 contents are read as shell variables to configure the bootstrap.
57
58 Running without arguments will suffice in most cases.
59 "
60 }
61
62 # Configuration.
63
64 # Name of the Makefile.am
65 gnulib_mk=gnulib.mk
66
67 # List of gnulib modules needed.
68 gnulib_modules=
69
70 # Any gnulib files needed that are not in modules.
71 gnulib_files=
72
73 # The command to download all .po files for a specified domain into
74 # a specified directory.  Fill in the first %s is the domain name, and
75 # the second with the destination directory.  Use rsync's -L and -r
76 # options because the latest/%s directory and the .po files within are
77 # all symlinks.
78 po_download_command_format=\
79 "rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
80
81 extract_package_name='
82   /^AC_INIT(/{
83      /.*,.*,.*,/{
84        s///
85        s/[][]//g
86        p
87        q
88      }
89      s/AC_INIT(\[*//
90      s/]*,.*//
91      s/^GNU //
92      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
93      s/[^A-Za-z0-9_]/-/g
94      p
95   }
96 '
97 package=`sed -n "$extract_package_name" configure.ac` || exit
98 gnulib_name=lib$package
99
100 build_aux=build-aux
101 # Extra files from gnulib, which override files from other sources.
102 gnulib_extra_files="
103         $build_aux/install-sh
104         $build_aux/missing
105         $build_aux/mdate-sh
106         $build_aux/texinfo.tex
107         $build_aux/depcomp
108         $build_aux/config.guess
109         $build_aux/config.sub
110         doc/INSTALL
111 "
112
113 # Additional gnulib-tool options to use.  Use "\newline" to break lines.
114 gnulib_tool_option_extras=
115
116 # Other locale categories that need message catalogs.
117 EXTRA_LOCALE_CATEGORIES=
118
119 # Additional xgettext options to use.  Use "\\\newline" to break lines.
120 XGETTEXT_OPTIONS='\\\
121  --flag=_:1:pass-c-format\\\
122  --flag=N_:1:pass-c-format\\\
123  --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
124 '
125
126 # Files we don't want to import.
127 excluded_files=
128
129 # File that should exist in the top directory of a checked out hierarchy,
130 # but not in a distribution tarball.
131 checkout_only_file=README-hacking
132
133 # Whether to use copies instead of symlinks.
134 copy=false
135
136 # Set this to '.cvsignore .gitignore' in bootstrap.conf if you want
137 # those files to be generated in directories like lib/, m4/, and po/.
138 # Or set it to 'auto' to make this script select which to use based
139 # on which version control system (if any) is used in the source directory.
140 vc_ignore=auto
141
142 # Override the default configuration, if necessary.
143 test -r bootstrap.conf && . ./bootstrap.conf
144
145 if test "$vc_ignore" = auto; then
146   vc_ignore=
147   test -d .git && vc_ignore=.gitignore
148   test -d CVS && vc_ignore="$vc_ignore .cvsignore"
149 fi
150
151 # Translate configuration into internal form.
152
153 # Parse options.
154
155 for option
156 do
157   case $option in
158   --help)
159     usage
160     exit;;
161   --gnulib-srcdir=*)
162     GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
163   --cvs-user=*)
164     CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
165   --skip-po)
166     SKIP_PO=t;;
167   --force)
168     checkout_only_file=;;
169   --copy)
170     copy=true;;
171   *)
172     echo >&2 "$0: $option: unknown option"
173     exit 1;;
174   esac
175 done
176
177 if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
178   echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
179   exit 1
180 fi
181
182 # If $STR is not already on a line by itself in $FILE, insert it,
183 # sorting the new contents of the file and replacing $FILE with the result.
184 insert_sorted_if_absent() {
185   file=$1
186   str=$2
187   test -f $file || touch $file
188   echo "$str" | sort -u - $file | cmp -s - $file \
189     || echo "$str" | sort -u - $file -o $file \
190     || exit 1
191 }
192
193 # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
194 found_aux_dir=no
195 grep '^[         ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \
196     >/dev/null && found_aux_dir=yes
197 grep '^[         ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
198     >/dev/null && found_aux_dir=yes
199 if test $found_aux_dir = no; then
200   echo "$0: expected line not found in configure.ac. Add the following:" >&2
201   echo "  AC_CONFIG_AUX_DIR([$build_aux])" >&2
202   exit 1
203 fi
204
205 # If $build_aux doesn't exist, create it now, otherwise some bits
206 # below will malfunction.  If creating it, also mark it as ignored.
207 if test ! -d $build_aux; then
208   mkdir $build_aux
209   for dot_ig in x $vc_ignore; do
210     test $dot_ig = x && continue
211     insert_sorted_if_absent $dot_ig $build_aux
212   done
213 fi
214
215 echo "$0: Bootstrapping from checked-out $package sources..."
216
217 cleanup_gnulib() {
218   status=$?
219   rm -fr gnulib
220   exit $status
221 }
222
223 # Get gnulib files.
224
225 case ${GNULIB_SRCDIR--} in
226 -)
227   if [ ! -d gnulib ]; then
228     echo "$0: getting gnulib files..."
229
230     case ${CVS_AUTH-pserver} in
231     pserver)
232       CVS_PREFIX=':pserver:anonymous@';;
233     ssh)
234       CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
235     *)
236       echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
237       exit 1;;
238     esac
239
240     case $CVS_RSH in
241     '') CVS_RSH=ssh; export CVS_RSH;;
242     esac
243
244     trap cleanup_gnulib 1 2 13 15
245
246     cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/gnulib co gnulib ||
247       cleanup_gnulib
248
249     trap - 1 2 13 15
250   fi
251   GNULIB_SRCDIR=gnulib
252 esac
253
254 gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
255 <$gnulib_tool || exit
256
257 # Get translations.
258
259 download_po_files() {
260   subdir=$1
261   domain=$2
262   echo "$0: getting translations into $subdir for $domain..."
263   cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
264   eval "$cmd"
265 }
266
267 # Download .po files to $po_dir/.reference and copy only the new
268 # or modified ones into $po_dir.  Also update $po_dir/LINGUAS.
269 update_po_files() {
270   # Directory containing primary .po files.
271   # Overwrite them only when we're sure a .po file is new.
272   po_dir=$1
273   domain=$2
274
275   # Download *.po files into this dir.
276   # Usually contains *.s1 checksum files.
277   ref_po_dir="$po_dir/.reference"
278
279   test -d $ref_po_dir || mkdir $ref_po_dir || return
280   download_po_files $ref_po_dir $domain \
281     && ls "$ref_po_dir"/*.po 2>/dev/null |
282       sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
283
284   for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
285      new_po="$ref_po_dir/$po.po"
286      cksum_file="$ref_po_dir/$po.s1"
287      if ! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
288        echo "updated $po_dir/$po.po..."
289        cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
290      fi
291   done
292 }
293
294 case $SKIP_PO in
295 '')
296   case `wget --help` in
297   *'--no-cache'*)
298     WGET_COMMAND='wget -nv --no-cache';;
299   *'--cache=on/off'*)
300     WGET_COMMAND='wget -nv --cache=off';;
301   *'--non-verbose'*)
302     WGET_COMMAND='wget -nv';;
303   *)
304     WGET_COMMAND='';;
305   esac
306
307   if test -d po; then
308     update_po_files po $package || exit
309   fi
310
311   if test -d runtime-po; then
312     update_po_files runtime-po $package-runtime || exit
313   fi;;
314 esac
315
316 symlink_to_dir()
317 {
318   src=$1/$2
319   dst=${3-$2}
320
321   test -f "$src" && {
322
323     # If the destination directory doesn't exist, create it.
324     # This is required at least for "lib/uniwidth/cjk.h".
325     dst_dir=`dirname "$dst"`
326     if ! test -d "$dst_dir"; then
327       mkdir -p "$dst_dir"
328
329       # If we've just created a directory like lib/uniwidth,
330       # tell version control system(s) it's ignorable.
331       # FIXME: for now, this does only one level
332       parent=`dirname "$dst_dir"`
333       for dot_ig in x $vc_ignore; do
334         test $dot_ig = x && continue
335         ig=$parent/$dot_ig
336         insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
337       done
338     fi
339
340     if $copy; then
341       {
342         test ! -h "$dst" || {
343           echo "$0: rm -f $dst" &&
344           rm -f "$dst"
345         }
346       } &&
347       test -f "$dst" &&
348       cmp -s "$src" "$dst" || {
349         echo "$0: cp -fp $src $dst" &&
350         cp -fp "$src" "$dst"
351       }
352     else
353       test -h "$dst" &&
354       src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
355       dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
356       test "$src_i" = "$dst_i" || {
357         dot_dots=
358         case $src in
359         /*) ;;
360         *)
361           case /$dst/ in
362           *//* | */../* | */./* | /*/*/*/*/*/)
363              echo >&2 "$0: invalid symlink calculation: $src -> $dst"
364              exit 1;;
365           /*/*/*/*/)    dot_dots=../../../;;
366           /*/*/*/)      dot_dots=../../;;
367           /*/*/)        dot_dots=../;;
368           esac;;
369         esac
370
371         echo "$0: ln -fs $dot_dots$src $dst" &&
372         ln -fs "$dot_dots$src" "$dst"
373       }
374     fi
375   }
376 }
377
378 cp_mark_as_generated()
379 {
380   cp_src=$1
381   cp_dst=$2
382
383   if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
384     symlink_to_dir "$GNULIB_SRCDIR" "$cp_dst"
385   elif cmp -s "$cp_src" "$local_gl_dir/$cp_dst"; then
386     symlink_to_dir $local_gl_dir "$cp_dst"
387   else
388     case $cp_dst in
389       *.[ch])             c1='/* '; c2=' */';;
390       *.texi)             c1='@c '; c2=     ;;
391       *.m4|*/Make*|Make*) c1='# ' ; c2=     ;;
392       *)                  c1=     ; c2=     ;;
393     esac
394
395     if test -z "$c1"; then
396       cmp -s "$cp_src" "$cp_dst" || {
397         echo "$0: cp -f $cp_src $cp_dst" &&
398         rm -f "$cp_dst" &&
399         sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst"
400       }
401     else
402       # Copy the file first to get proper permissions if it
403       # doesn't already exist.  Then overwrite the copy.
404       cp "$cp_src" "$cp_dst-t" &&
405       (
406         echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
407         echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
408         sed "s!$bt_regex/!!g" "$cp_src"
409       ) > $cp_dst-t &&
410       if cmp -s "$cp_dst-t" "$cp_dst"; then
411         rm -f "$cp_dst-t"
412       else
413         echo "$0: cp $cp_src $cp_dst # with edits" &&
414         mv -f "$cp_dst-t" "$cp_dst"
415       fi
416     fi
417   fi
418 }
419
420 version_controlled_file() {
421   dir=$1
422   file=$2
423   found=no
424   if test -d CVS; then
425     grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
426              grep '^/[^/]*/[0-9]' > /dev/null && found=yes
427   elif test -d .git; then
428     git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
429   else
430     echo "$0: no version control for $dir/$file?" >&2
431   fi
432   test $found = yes
433 }
434
435 slurp() {
436   for dir in . `(cd $1 && find * -type d -print)`; do
437     copied=
438     sep=
439     for file in `ls -a $1/$dir`; do
440       case $file in
441       .|..) continue;;
442       .*) continue;; # FIXME: should all file names starting with "." be ignored?
443       esac
444       test -d $1/$dir/$file && continue
445       for excluded_file in $excluded_files; do
446         test "$dir/$file" = "$excluded_file" && continue 2
447       done
448       if test $file = Makefile.am; then
449         copied=$copied${sep}$gnulib_mk; sep=$nl
450         remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
451         sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
452           echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
453           rm -f $dir/$gnulib_mk &&
454           sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
455         }
456       elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
457            version_controlled_file $dir $file; then
458         echo "$0: $dir/$file overrides $1/$dir/$file"
459       else
460         copied=$copied$sep$file; sep=$nl
461         if test $file = gettext.m4; then
462           echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
463           rm -f $dir/$file
464           sed '
465             /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
466               AC_DEFUN([AM_INTL_SUBDIR], [
467             /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
468               AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
469             $a\
470               AC_DEFUN([gl_LOCK_EARLY], [])
471           ' $1/$dir/$file >$dir/$file
472         else
473           cp_mark_as_generated $1/$dir/$file $dir/$file
474         fi
475       fi || exit
476     done
477
478     for dot_ig in x $vc_ignore; do
479       test $dot_ig = x && continue
480       ig=$dir/$dot_ig
481       if test -n "$copied"; then
482         insert_sorted_if_absent $ig "$copied"
483         # If an ignored file name ends with _.h, then also add
484         # the name with just ".h".  Many gnulib headers are generated,
485         # e.g., stdint_.h -> stdint.h, dirent_.h ->..., etc.
486         # Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
487         f=`echo "$copied"|sed 's/_\.h$/.h/;s/\.sin$/.sed/;s/\.y$/.c/;s/\.gperf$/.h/'`
488         insert_sorted_if_absent $ig "$f"
489
490         # For files like sys_stat_.h and sys_time_.h, record as
491         # ignorable the directory we might eventually create: sys/.
492         f=`echo "$copied"|sed 's/sys_.*_\.h$/sys/'`
493         insert_sorted_if_absent $ig "$f"
494       fi
495     done
496   done
497 }
498
499
500 # Create boot temporary directories to import from gnulib and gettext.
501 rm -fr $bt $bt2 &&
502 mkdir $bt $bt2 || exit
503
504 # Import from gnulib.
505
506 gnulib_tool_options="\
507  --import\
508  --no-changelog\
509  --aux-dir $bt/$build_aux\
510  --doc-base $bt/doc\
511  --lib $gnulib_name\
512  --m4-base $bt/m4/\
513  --source-base $bt/lib/\
514  --tests-base $bt/tests\
515  --local-dir $local_gl_dir\
516 $gnulib_tool_option_extras\
517 "
518 echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
519 $gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
520 slurp $bt || exit
521
522 for file in $gnulib_files; do
523   symlink_to_dir "$GNULIB_SRCDIR" $file || exit
524 done
525
526
527 # Import from gettext.
528 with_gettext=yes
529 grep '^[         ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
530     with_gettext=no
531
532 if test $with_gettext = yes; then
533   echo "$0: (cd $bt2; autopoint) ..."
534   cp configure.ac $bt2 &&
535   (cd $bt2 && autopoint && rm configure.ac) &&
536   slurp $bt2 $bt || exit
537
538   rm -fr $bt $bt2 || exit
539 fi
540
541 # Coreutils is unusual in that it generates some of its test-related
542 # Makefile.am files.  That must be done before invoking automake.
543 mam_template=tests/Makefile.am.in
544 if test -f $mam_template; then
545   PERL=perl
546   for tool in cut head join pr sort tac tail test tr uniq wc; do
547     m=tests/$tool/Makefile.am
548     t=${m}t
549     rm -f $m $t
550     sed -n '1,/^##test-files-begin/p' $mam_template > $t
551     echo "x = $tool" >> $t
552     srcdir=tests/$tool
553     $PERL -I$srcdir -w -- tests/mk-script $srcdir --list >> $t
554     sed -n '/^##test-files-end/,$p' $mam_template >> $t
555     chmod -w $t
556     mv $t $m
557   done
558 fi
559
560 # Reconfigure, getting other files.
561
562 for command in \
563   libtool \
564   'aclocal --force -I m4' \
565   'autoconf --force' \
566   'autoheader --force' \
567   'automake --add-missing --copy --force-missing';
568 do
569   if test "$command" = libtool; then
570     grep '^[     ]*AM_PROG_LIBTOOL\>' configure.ac >/dev/null ||
571       continue
572     command='libtoolize -c -f'
573   fi
574   echo "$0: $command ..."
575   $command || exit
576 done
577
578
579 # Get some extra files from gnulib, overriding existing files.
580 for file in $gnulib_extra_files; do
581   case $file in
582   */INSTALL) dst=INSTALL;;
583   build-aux/*) dst=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;;
584   *) dst=$file;;
585   esac
586   symlink_to_dir "$GNULIB_SRCDIR" $file $dst || exit
587 done
588
589 if test $with_gettext = yes; then
590   # Create gettext configuration.
591   echo "$0: Creating po/Makevars from po/Makevars.template ..."
592   rm -f po/Makevars
593   sed '
594     /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
595     /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
596     /^XGETTEXT_OPTIONS *=/{
597       s/$/ \\/
598       a\
599           '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
600     }
601   ' po/Makevars.template >po/Makevars
602
603   if test -d runtime-po; then
604     # Similarly for runtime-po/Makevars, but not quite the same.
605     rm -f runtime-po/Makevars
606     sed '
607       /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
608       /^subdir *=.*/s/=.*/= runtime-po/
609       /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
610       /^XGETTEXT_OPTIONS *=/{
611         s/$/ \\/
612         a\
613             '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
614       }
615     ' <po/Makevars.template >runtime-po/Makevars
616
617     # Copy identical files from po to runtime-po.
618     (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
619   fi
620 fi
621
622 echo "$0: done.  Now you can run './configure'."