1#!/bin/sh 2# Sign files and upload them. 3 4scriptversion=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 23set -e 24 25GPG='gpg --batch --no-tty' 26conffile=.gnuploadrc 27to= 28dry_run=false 29symlink_files= 30delete_files= 31delete_symlinks= 32collect_var= 33dbg= 34 35usage="Usage: $0 [OPTIONS]... [COMMAND] FILES... [[COMMAND] FILES...] 36 37Sign all FILES, and upload them to selected destinations, according to 38<http://www.gnu.org/prep/maintain/html_node/Automated-FTP-Uploads.html>. 39 40Commands: 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 46Options: 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 55If --symlink-regex is given without EXPR, then the link target name 56is created by replacing the version information with \`-latest', e.g.: 57 58 foo-1.3.4.tar.gz -> foo-latest.tar.gz 59 60Recognized 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 70Options and commands are applied in order. If the file $conffile exists 71in the current working directory, its contents are prepended to the 72actual command line options. Use this to keep your defaults. Comments 73(#) and empty lines in $conffile are allowed. 74 75Examples: 761. 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 812. 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 873. Symlink automake-1.8.2b.tar.gz to automake-latest.tar.gz and 88automake-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 954. Delete automake-1.8.2a.tar.gz and .bz2, remove symlink 96automake-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 105Report bugs to <bug-automake@gnu.org>. 106Send patches to <automake-patches@gnu.org>." 107 108# Read local configuration file 109if test -r "$conffile"; then 110 echo "$0: Reading configuration file $conffile" 111 eval set x "`sed 's/#.*$//;/^$/d' \"$conffile\" | tr '\012\015' ' '` \"\$@\"" 112 shift 113fi 114 115while 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 183done 184 185dprint() 186{ 187 echo "Running $*..." 188} 189 190if $dry_run; then 191 dbg=dprint 192fi 193 194if test -z "$to"; then 195 echo "$0: Missing destination sites" >&2 196 exit 1 197fi 198 199if 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 205fi 206 207if 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 212else 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 231fi 232 233# Make sure passphrase is not exported in the environment. 234unset 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. 242PATH=/empty echo -n "Enter GPG passphrase: " 243stty -echo 244read -r passphrase 245stty echo 246echo 247 248if 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 255fi 256 257 258# mkdirective DESTDIR BASE FILE STMT 259# Arguments: See upload, below 260mkdirective () 261{ 262 stmt="$4" 263 if test -n "$3"; then 264 stmt=" 265filename: $3$stmt" 266 fi 267 268 cat >${2}.directive<<EOF 269version: 1.1 270directory: $1 271comment: gnupload v. $scriptversion$stmt 272EOF 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 280mksymlink () 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. 298upload () 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 359stmt= 360if test -n "$symlink_files"; then 361 stmt="$stmt 362`mksymlink $symlink_files`" 363fi 364 365for file in $delete_files 366do 367 stmt="$stmt 368archive: $file" 369done 370 371for file in $delete_symlinks 372do 373 stmt="$stmt 374rmsymlink: $file" 375done 376 377if 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 383fi 384 385# Process actual uploads 386for dest in $to 387do 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 397symlink: $file $linkname 398symlink: $file.sig $linkname.sig" 399 fi 400 upload "$dest" "$destdir" "$file" "$file" "$stmt" "$files" 401 done 402done 403 404exit 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: 413