Merge branch 'maint'
[platform/upstream/automake.git] / lib / gnupload
1 #!/bin/sh
2 # Sign files and upload them.
3
4 scriptversion=2010-05-23.15; # UTC
5
6 # Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
7 # Foundation, Inc.
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2, or (at your option)
12 # any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 # Originally written by Alexandre Duret-Lutz <adl@gnu.org>.
23
24 set -e
25
26 GPG='gpg --batch --no-tty'
27 conffile=.gnuploadrc
28 to=
29 dry_run=false
30 symlink_files=
31 delete_files=
32 delete_symlinks=
33 collect_var=
34 dbg=
35 nl='
36 '
37
38 usage="Usage: $0 [OPTION]... [CMD] FILE... [[CMD] FILE...]
39
40 Sign all FILES, and process them at selected destinations according to CMD.
41 <http://www.gnu.org/prep/maintain/html_node/Automated-FTP-Uploads.html>
42 explains further.
43
44 Commands:
45   --delete                 delete FILES from destination
46   --symlink                create symbolic links
47   --rmsymlink              remove symbolic links
48   --                       treat the remaining arguments as files to upload
49
50 Options:
51   --help                   print this help text and exit
52   --to DEST                specify one destination for FILES
53                            (multiple --to options are allowed)
54   --user NAME              sign with key NAME
55   --symlink-regex[=EXPR]   use sed script EXPR to compute symbolic link names
56   --dry-run                do nothing, show what would have been done
57   --version                output version information and exit
58
59 If --symlink-regex is given without EXPR, then the link target name
60 is created by replacing the version information with \`-latest', e.g.:
61
62   foo-1.3.4.tar.gz -> foo-latest.tar.gz
63
64 Recognized destinations are:
65   alpha.gnu.org:DIRECTORY
66   savannah.gnu.org:DIRECTORY
67   savannah.nongnu.org:DIRECTORY
68   ftp.gnu.org:DIRECTORY
69                            build directive files and upload files by FTP
70   download.gnu.org.ua:{alpha|ftp}/DIRECTORY
71                            build directive files and upload files by SFTP
72   [user@]host:DIRECTORY    upload files with scp
73
74 Options and commands are applied in order.  If the file $conffile exists
75 in the current working directory, its contents are prepended to the
76 actual command line options.  Use this to keep your defaults.  Comments
77 (#) and empty lines in $conffile are allowed.
78
79 Examples:
80 1. Upload foobar-1.0.tar.gz to ftp.gnu.org:
81   gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz
82
83 2. Upload foobar-1.0.tar.gz and foobar-1.0.tar.xz to ftp.gnu.org:
84   gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz foobar-1.0.tar.xz
85
86 3. Same as above, and also create symbolic links to foobar-latest.tar.*:
87   gnupload --to ftp.gnu.org:foobar \\
88            --symlink-regex \\
89            foobar-1.0.tar.gz foobar-1.0.tar.xz
90
91 4. Upload foobar-0.9.90.tar.gz to two sites:
92   gnupload --to alpha.gnu.org:foobar \\
93            --to sources.redhat.com:~ftp/pub/foobar \\
94            foobar-0.9.90.tar.gz
95
96 5. Delete oopsbar-0.9.91.tar.gz and upload foobar-0.9.91.tar.gz
97    (the -- terminates the list of files to delete):
98   gnupload --to alpha.gnu.org:foobar \\
99            --to sources.redhat.com:~ftp/pub/foobar \\
100            --delete oopsbar-0.9.91.tar.gz \\
101            -- foobar-0.9.91.tar.gz
102
103 gnupload uses the ncftpput program to do the transfers; if you don't
104 happen to have an ncftp package installed, the ncftpput-ftp script in
105 the build-aux/ directory of the gnulib package
106 (http://savannah.gnu.org/projects/gnulib) may serve as a replacement.
107
108 Report bugs to <bug-automake@gnu.org>.
109 Send patches to <automake-patches@gnu.org>."
110
111 # Read local configuration file
112 if test -r "$conffile"; then
113   echo "$0: Reading configuration file $conffile"
114   conf=`sed 's/#.*$//;/^$/d' "$conffile" | tr "\015$nl" '  '`
115   eval set x "$conf \"\$@\""
116   shift
117 fi
118
119 while test -n "$1"; do
120   case $1 in
121   -*)
122     collect_var=
123     case $1 in
124     --help)
125       echo "$usage"
126       exit $?
127       ;;
128     --to)
129       if test -z "$2"; then
130         echo "$0: Missing argument for --to" 1>&2
131         exit 1
132       else
133         to="$to $2"
134         shift
135       fi
136       ;;
137     --user)
138       if test -z "$2"; then
139         echo "$0: Missing argument for --user" 1>&2
140         exit 1
141       else
142         GPG="$GPG --local-user $2"
143         shift
144       fi
145       ;;
146     --delete)
147       collect_var=delete_files
148       ;;
149     --rmsymlink)
150       collect_var=delete_symlinks
151       ;;
152     --symlink-regex=*)
153       symlink_expr=`expr "$1" : '[^=]*=\(.*\)'`
154       ;;
155     --symlink-regex)
156       symlink_expr='s|-[0-9][0-9\.]*\(-[0-9][0-9]*\)\{0,1\}\.|-latest.|'
157       ;;
158     --symlink)
159       collect_var=symlink_files
160       ;;
161     --dry-run|-n)
162       dry_run=:
163       ;;
164     --version)
165       echo "gnupload $scriptversion"
166       exit $?
167       ;;
168     --)
169       shift
170       break
171       ;;
172     -*)
173       echo "$0: Unknown option \`$1', try \`$0 --help'" 1>&2
174       exit 1
175       ;;
176     esac
177     ;;
178   *)
179     if test -z "$collect_var"; then
180       break
181     else
182       eval "$collect_var=\"\$$collect_var $1\""
183     fi
184     ;;
185   esac
186   shift
187 done
188
189 dprint()
190 {
191   echo "Running $* ..."
192 }
193
194 if $dry_run; then
195   dbg=dprint
196 fi
197
198 if test -z "$to"; then
199   echo "$0: Missing destination sites" >&2
200   exit 1
201 fi
202
203 if test -n "$symlink_files"; then
204   x=`echo "$symlink_files" | sed 's/[^ ]//g;s/  //g'`
205   if test -n "$x"; then
206     echo "$0: Odd number of symlink arguments" >&2
207     exit 1
208   fi
209 fi
210
211 if test $# = 0; then
212   if test -z "${symlink_files}${delete_files}${delete_symlinks}"; then
213     echo "$0: No file to upload" 1>&2
214     exit 1
215   fi
216 else
217   # Make sure all files exist.  We don't want to ask
218   # for the passphrase if the script will fail.
219   for file
220   do
221     if test ! -f $file; then
222       echo "$0: Cannot find \`$file'" 1>&2
223       exit 1
224     elif test -n "$symlink_expr"; then
225       linkname=`echo $file | sed "$symlink_expr"`
226       if test -z "$linkname"; then
227         echo "$0: symlink expression produces empty results" >&2
228         exit 1
229       elif test "$linkname" = $file; then
230         echo "$0: symlink expression does not alter file name" >&2
231         exit 1
232       fi
233     fi
234   done
235 fi
236
237 # Make sure passphrase is not exported in the environment.
238 unset passphrase
239
240 # Reset PATH to be sure that echo is a built-in.  We will later use
241 # `echo $passphrase' to output the passphrase, so it is important that
242 # it is a built-in (third-party programs tend to appear in `ps'
243 # listings with their arguments...).
244 # Remember this script runs with `set -e', so if echo is not built-in
245 # it will exit now.
246 PATH=/empty echo -n "Enter GPG passphrase: "
247 stty -echo
248 read -r passphrase
249 stty echo
250 echo
251
252 if test $# -ne 0; then
253   for file
254   do
255     echo "Signing $file ..."
256     rm -f $file.sig
257     echo "$passphrase" | $dbg $GPG --passphrase-fd 0 -ba -o $file.sig $file
258   done
259 fi
260
261
262 # mkdirective DESTDIR BASE FILE STMT
263 # Arguments: See upload, below
264 mkdirective ()
265 {
266   stmt="$4"
267   if test -n "$3"; then
268     stmt="
269 filename: $3$stmt"
270   fi
271
272   cat >${2}.directive<<EOF
273 version: 1.1
274 directory: $1
275 comment: gnupload v. $scriptversion$stmt
276 EOF
277   if $dry_run; then
278     echo "File ${2}.directive:"
279     cat ${2}.directive
280     echo "File ${2}.directive:" | sed 's/./-/g'
281   fi
282 }
283
284 mksymlink ()
285 {
286   while test $# -ne 0
287   do
288     echo "symlink: $1 $2"
289     shift
290     shift
291   done
292 }
293
294 # upload DEST DESTDIR BASE FILE STMT FILES
295 # Arguments:
296 #  DEST     Destination site;
297 #  DESTDIR  Destination directory;
298 #  BASE     Base name for the directive file;
299 #  FILE     Name of the file to distribute (may be empty);
300 #  STMT     Additional statements for the directive file;
301 #  FILES    List of files to upload.
302 upload ()
303 {
304   dest=$1
305   destdir=$2
306   base=$3
307   file=$4
308   stmt=$5
309   files=$6
310
311   rm -f $base.directive $base.directive.asc
312   case $dest in
313     alpha.gnu.org:*)
314       mkdirective "$destdir" "$base" "$file" "$stmt"
315       echo "$passphrase" | $dbg $GPG --passphrase-fd 0 --clearsign $base.directive
316       $dbg ncftpput ftp-upload.gnu.org /incoming/alpha $files $base.directive.asc
317       ;;
318     ftp.gnu.org:*)
319       mkdirective "$destdir" "$base" "$file" "$stmt"
320       echo "$passphrase" | $dbg $GPG --passphrase-fd 0 --clearsign $base.directive
321       $dbg ncftpput ftp-upload.gnu.org /incoming/ftp $files $base.directive.asc
322       ;;
323     savannah.gnu.org:*)
324       if test -z "$files"; then
325         echo "$0: warning: standalone directives not applicable for $dest" >&2
326       fi
327       $dbg ncftpput savannah.gnu.org /incoming/savannah/$destdir $files
328       ;;
329     savannah.nongnu.org:*)
330       if test -z "$files"; then
331         echo "$0: warning: standalone directives not applicable for $dest" >&2
332       fi
333       $dbg ncftpput savannah.nongnu.org /incoming/savannah/$destdir $files
334       ;;
335     download.gnu.org.ua:alpha/*|download.gnu.org.ua:ftp/*)
336       destdir_p1=`echo "$destdir" | sed 's,^[^/]*/,,'`
337       destdir_topdir=`echo "$destdir" | sed 's,/.*,,'`
338       mkdirective "$destdir_p1" "$base" "$file" "$stmt"
339       echo "$passphrase" | $dbg $GPG --passphrase-fd 0 --clearsign $base.directive
340       for f in $files $base.directive.asc
341       do
342         echo put $f
343       done | $dbg sftp -b - puszcza.gnu.org.ua:/incoming/$destdir_topdir
344       ;;
345     /*)
346       dest_host=`echo "$dest" | sed 's,:.*,,'`
347       mkdirective "$destdir" "$base" "$file" "$stmt"
348       echo "$passphrase" | $dbg $GPG --passphrase-fd 0 --clearsign $base.directive
349       $dbg cp $files $base.directive.asc $dest_host
350       ;;
351     *)
352       if test -z "$files"; then
353         echo "$0: warning: standalone directives not applicable for $dest" >&2
354       fi
355       $dbg scp $files $dest
356       ;;
357   esac
358   rm -f $base.directive $base.directive.asc
359 }
360
361 #####
362 # Process any standalone directives
363 stmt=
364 if test -n "$symlink_files"; then
365   stmt="$stmt
366 `mksymlink $symlink_files`"
367 fi
368
369 for file in $delete_files
370 do
371   stmt="$stmt
372 archive: $file"
373 done
374
375 for file in $delete_symlinks
376 do
377   stmt="$stmt
378 rmsymlink: $file"
379 done
380
381 if test -n "$stmt"; then
382   for dest in $to
383   do
384     destdir=`echo $dest | sed 's/[^:]*://'`
385     upload "$dest" "$destdir" "`hostname`-$$" "" "$stmt"
386   done
387 fi
388
389 # Process actual uploads
390 for dest in $to
391 do
392   for file
393   do
394     echo "Uploading $file to $dest ..."
395     stmt=
396     files="$file $file.sig"
397     destdir=`echo $dest | sed 's/[^:]*://'`
398     if test -n "$symlink_expr"; then
399       linkname=`echo $file | sed "$symlink_expr"`
400       stmt="$stmt
401 symlink: $file $linkname
402 symlink: $file.sig $linkname.sig"
403     fi
404     upload "$dest" "$destdir" "$file" "$file" "$stmt" "$files"
405   done
406 done
407
408 exit 0
409
410 # Local variables:
411 # eval: (add-hook 'write-file-hooks 'time-stamp)
412 # time-stamp-start: "scriptversion="
413 # time-stamp-format: "%:y-%02m-%02d.%02H"
414 # time-stamp-time-zone: "UTC"
415 # time-stamp-end: "; # UTC"
416 # End: