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