Commit | Line | Data |
---|---|---|
c84bdaf6 LC |
1 | #!/bin/sh |
2 | # Sign files and upload them. | |
3 | ||
a927b6c1 | 4 | scriptversion=2010-05-23.15; # UTC |
c84bdaf6 | 5 | |
61cd9dc9 LC |
6 | # Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software |
7 | # Foundation, Inc. | |
c84bdaf6 LC |
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 3, 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= | |
a927b6c1 LC |
35 | nl=' |
36 | ' | |
c84bdaf6 | 37 | |
61cd9dc9 | 38 | usage="Usage: $0 [OPTION]... [CMD] FILE... [[CMD] FILE...] |
c84bdaf6 | 39 | |
61cd9dc9 LC |
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. | |
c84bdaf6 LC |
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: | |
1cd4fffc LC |
80 | 1. Upload foobar-1.0.tar.gz to ftp.gnu.org: |
81 | gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz | |
c84bdaf6 | 82 | |
1cd4fffc LC |
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 | |
c84bdaf6 | 85 | |
1cd4fffc LC |
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 | |
c84bdaf6 | 102 | |
61cd9dc9 LC |
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 | ||
c84bdaf6 LC |
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" | |
a927b6c1 LC |
114 | conf=`sed 's/#.*$//;/^$/d' "$conffile" | tr "\015$nl" ' '` |
115 | eval set x "$conf \"\$@\"" | |
c84bdaf6 LC |
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 | { | |
a927b6c1 | 191 | echo "Running $* ..." |
c84bdaf6 LC |
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 | |
a927b6c1 | 255 | echo "Signing $file ..." |
c84bdaf6 LC |
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 | |
a927b6c1 | 394 | echo "Uploading $file to $dest ..." |
c84bdaf6 LC |
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: |