diff options
Diffstat (limited to 'scripts/repo-add.sh.in')
-rw-r--r-- | scripts/repo-add.sh.in | 378 |
1 files changed, 237 insertions, 141 deletions
diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index b12188ce..2390a92c 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -28,7 +28,10 @@ myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' QUIET=0 -REPO_DB_FILE="" +REPO_DB_FILE= +LOCKFILE= +CLEAN_LOCK=0 +startdir="$PWD" # ensure we have a sane umask set umask 0022 @@ -57,8 +60,8 @@ error() { # print usage instructions usage() { printf "repo-add, repo-remove (pacman) %s\n\n" "$myver" - printf "$(gettext "Usage: repo-add [-q] <path-to-db> <package> ...\n")" - printf "$(gettext "Usage: repo-remove [-q] <path-to-db> <packagename> ...\n\n")" + printf "$(gettext "Usage: repo-add [-q] <path-to-db> <package|delta> ...\n")" + printf "$(gettext "Usage: repo-remove [-q] <path-to-db> <packagename|delta> ...\n\n")" printf "$(gettext "\ repo-add will update a package database by reading a package file.\n\ Multiple packages to add can be specified on the command line.\n\n")" @@ -93,36 +96,86 @@ write_list_entry() { fi } -# write a delta entry to the pacman database -# arg1 - path to delta +find_pkgentry() +{ + local pkgname=$1 + local pkgentry + for pkgentry in $tmpdir/$pkgname*; do + name=${pkgentry##*/} + if [ "${name%-*-*}" = "$pkgname" ]; then + echo $pkgentry + return 0 + fi + done + return 1 +} + +# Get the package name from the delta filename +get_delta_pkgname() { + local tmp + + tmp=${1##*/} + echo ${tmp%-*-*_to*} +} + +# write a delta entry +# arg1 - path to delta file db_write_delta() { - # blank out all variables - local deltafile="$1" - local filename=$(basename "$deltafile") - local deltavars pkgname fromver tover arch csize md5sum - - # format of the delta filename: - # (package)-(fromver)_to_(tover)-(arch).delta - deltavars=( $(echo "$filename" | sed -e 's/\(.*\)-\(.*-.*\)_to_\(.*-.*\)-\(.*\).delta/\1 \2 \3 \4/') ) - pkgname=${deltavars[0]} - fromver=${deltavars[1]} - tover=${deltavars[2]} - arch=${deltavars[3]} - - # get md5sum and size of delta + deltafile="$1" + pkgname="$(get_delta_pkgname $deltafile)" + + pkgentry=$(find_pkgentry $pkgname) + if [ -z "$pkgentry" ]; then + return 1 + fi + deltas="$pkgentry/deltas" + # create deltas file if it does not already exist + if [ ! -f "$deltas" ]; then + msg2 "$(gettext "Creating 'deltas' db entry...")" + echo -e "%DELTAS%" >>$deltas + fi + # get md5sum and compressed size of package md5sum="$(openssl dgst -md5 "$deltafile" | awk '{print $NF}')" csize=$(@SIZECMD@ "$deltafile") - # ensure variables were found - if [ -z "$pkgname" -o -z "$fromver" -o -z "$tover" -o -z "$arch" ]; then - return 1 + oldfile=$(xdelta3 printhdr $deltafile | grep "XDELTA filename (source)" | sed 's/.*: *//') + newfile=$(xdelta3 printhdr $deltafile | grep "XDELTA filename (output)" | sed 's/.*: *//') + + if grep -q "$oldfile.*$newfile" $deltas; then + warning "$(gettext "An entry for '%s' already existed")" "$deltafile" + sed -i.backup "/$oldfile.*$newfile/d" $deltas && rm -f $deltas.backup + msg2 "$(gettext "Removing existing entry '%s'...")" "$deltafile" fi + echo ${deltafile##*/} $md5sum $csize $oldfile $newfile >> $deltas - # add the entry for this delta file - echo -e "$fromver $tover $csize $filename $md5sum" >>deltas + return 0 } # end db_write_delta +# remove a delta entry +# arg1 - path to delta file +db_remove_delta() +{ + deltafile="$1" + filename=${deltafile##*/} + pkgname="$(get_delta_pkgname $deltafile)" + + pkgentry=$(find_pkgentry $pkgname) + if [ -z "$pkgentry" ]; then + return 1 + fi + deltas="$pkgentry/deltas" + if [ ! -f "$deltas" ]; then + return 1 + fi + if grep -q "$filename" $deltas; then + sed -i.backup "/$filename/d" $deltas && rm -f $deltas.backup + msg2 "$(gettext "Removing existing entry '%s'...")" "$filename" + return 0 + fi + + return 1 +} # end db_remove_delta # write an entry to the pacman database # arg1 - path to package @@ -130,10 +183,8 @@ db_write_entry() { # blank out all variables local pkgfile="$1" - local pkgname pkgver pkgdesc url builddate packager csize size \ - group depend backup license replaces provides conflict force \ - _groups _depends _backups _licenses _replaces _provides _conflicts \ - startdir optdepend _optdepends md5sum + local pkgname pkgver pkgdesc csize size md5sum url arch builddate packager force \ + _groups _licenses _replaces _depends _conflicts _provides _optdepends local OLDIFS="$IFS" # IFS (field separator) is only the newline character @@ -150,12 +201,11 @@ db_write_entry() declare $var="$val" case "$var" in group) _groups="$_groups$group\n" ;; - depend) _depends="$_depends$depend\n" ;; - backup) _backups="$_backups$backup\n" ;; license) _licenses="$_licenses$license\n" ;; replaces) _replaces="$_replaces$replaces\n" ;; - provides) _provides="$_provides$provides\n" ;; + depend) _depends="$_depends$depend\n" ;; conflict) _conflicts="$_conflicts$conflict\n" ;; + provides) _provides="$_provides$provides\n" ;; optdepend) _optdepends="$_optdepends$optdepend\n" ;; esac done @@ -172,8 +222,7 @@ db_write_entry() return 1 fi - startdir=$(pwd) - pushd "$gstmpdir" 2>&1 >/dev/null + cd "$tmpdir" if [ -d "$pkgname-$pkgver" ]; then warning "$(gettext "An entry for '%s' already existed")" "$pkgname-$pkgver" @@ -186,6 +235,9 @@ db_write_entry() mkdir "$pkgname-$pkgver" cd "$pkgname-$pkgver" + # restore an eventual deltas file + [ -f "../$pkgname.deltas" ] && mv "../$pkgname.deltas" deltas + # create desc entry msg2 "$(gettext "Creating 'desc' db entry...")" echo -e "%FILENAME%\n$(basename "$1")\n" >>desc @@ -210,45 +262,14 @@ db_write_entry() # create depends entry msg2 "$(gettext "Creating 'depends' db entry...")" + # create the file even if it will remain empty + touch "depends" write_list_entry "DEPENDS" "$_depends" "depends" write_list_entry "CONFLICTS" "$_conflicts" "depends" write_list_entry "PROVIDES" "$_provides" "depends" write_list_entry "OPTDEPENDS" "$_optdepends" "depends" - # create deltas entry if there are delta files - # Xav : why should deltas be in $startdir? - for delta in $startdir/$pkgname-*-*_to_*-*-$arch.delta; do - # This for loop also pulls in all files that start with the current package - # name and are followed by a -whatever. For instance, running this loop for - # gcc would also grab gcc-libs. To guard against this, compare the package - # name of the delta to the current package name. - local filename=$(basename "$delta") - local dpkgname="$(echo "$filename" | sed -e 's/\(.*\)-.*-.*_to_.*-.*-.*.delta/\1/')" - if [ "$pkgname" = "$dpkgname" -a -f "$delta" ]; then - # create deltas file if it does not already exist - if [ ! -f "deltas" ]; then - msg2 "$(gettext "Creating 'deltas' db entry...")" - echo -e "%DELTAS%" >>deltas - fi - - # write this delta entry - if db_write_delta "$delta"; then - msg2 "$(gettext "Added delta '%s'")" "$(basename "$delta")" - else - warning "$(gettext "Could not add delta '%s'")" "$(basename "$delta")" - fi - fi - done - # add the final newline - [ -f "deltas" ] && echo -e "" >>deltas - - popd 2>&1 >/dev/null - - # preserve the modification time - # Xav : what for? - pkgdir="$gstmpdir/$pkgname-$pkgver" - touch -r "$pkgfile" "$pkgdir/desc" "$pkgdir/depends" - [ -f "$pkgdir/deltas" ] && touch -r "$pkgfile" "$pkgdir/deltas" + cd "$startdir" return 0 } # end db_write_entry @@ -256,20 +277,122 @@ db_write_entry() # remove existing entries from the DB # arg1 - package name db_remove_entry() { - pushd "$gstmpdir" 2>&1 >/dev/null - - # remove any other package in the DB with same name - local existing - for existing in *; do - if [ "${existing%-*-*}" = "$1" ]; then - msg2 "$(gettext "Removing existing package '%s'...")" "$existing" - rm -rf "$existing" + local pkgname=$1 + local notfound=1 + local pkgentry=$(find_pkgentry $pkgname) + while [ -n "$pkgentry" ]; do + notfound=0 + if [ -f "$pkgentry/deltas" ]; then + mv "$pkgentry/deltas" "$tmpdir/$pkgname.deltas" fi + msg2 "$(gettext "Removing existing entry '%s'...")" \ + "$(basename $pkgentry)" + rm -rf $pkgentry + pkgentry=$(find_pkgentry $pkgname) done - - popd 2>&1 >/dev/null + return $notfound } # end db_remove_entry +check_repo_db() +{ + # check lock file + if ( set -o noclobber; echo "$$" > "$LOCKFILE") 2> /dev/null; then + CLEAN_LOCK=1 + else + error "$(gettext "Failed to acquire lockfile: %s.")" "$LOCKFILE" + [ -f "$LOCKFILE" ] && error "$(gettext "Held by %s")" "$(cat $LOCKFILE)" + exit 1 + fi + + if [ -f "$REPO_DB_FILE" ]; then + if ! (bsdtar -tf "$REPO_DB_FILE" | grep -q "/desc"); then + error "$(gettext "Repository file '%s' is not a proper pacman database.")" "$REPO_DB_FILE" + exit 1 + fi + msg "$(gettext "Extracting database to a temporary location...")" + bsdtar -xf "$REPO_DB_FILE" -C "$tmpdir" + else + if [ "$cmd" == "repo-remove" ]; then + error "$(gettext "Repository file '%s' was not found.")" "$REPO_DB_FILE" + exit 1 + fi + fi +} + +add() +{ + if [ ! -f "$1" ]; then + error "$(gettext "File '%s' not found.")" "$1" + return 1 + fi + + if [ "${1##*.}" == "delta" ]; then + deltafile=$1 + msg "$(gettext "Adding delta '%s'")" "$deltafile" + if [ ! "$(type -p xdelta3)" ]; then + error "$(gettext "Cannot find the xdelta3 binary! Is xdelta3 installed?")" + exit 1 + fi + if db_write_delta "$deltafile"; then + return 0 + else + return 1 + fi + fi + + pkgfile=$1 + if ! bsdtar -tf "$pkgfile" .PKGINFO 2>&1 >/dev/null; then + error "$(gettext "'%s' is not a package file, skipping")" "$pkgfile" + return 1 + fi + + msg "$(gettext "Adding package '%s'")" "$pkgfile" + + db_write_entry "$pkgfile" +} + +remove() +{ + if [ "${1##*.}" == "delta" ]; then + deltafile=$1 + msg "$(gettext "Searching for delta '%s'...")" "$deltafile" + if db_remove_delta "$deltafile"; then + return 0 + else + error "$(gettext "Delta matching '%s' not found.")" "$deltafile" + return 1 + fi + fi + + pkgname=$1 + msg "$(gettext "Searching for package '%s'...")" "$pkgname" + + if db_remove_entry "$pkgname"; then + rm -f "$tmpdir/$pkgname.deltas" + return 0 + else + error "$(gettext "Package matching '%s' not found.")" "$pkgname" + return 1 + fi +} + +trap_exit() +{ + echo + error "$@" + exit 1 +} + +clean_up() { + local exit_code=$? + + cd "$startdir" + [ -d "$tmpdir" ] && rm -rf "$tmpdir" + [ $CLEAN_LOCK -eq 1 -a -f "$LOCKFILE" ] && rm -f "$LOCKFILE" + + exit $exit_code +} + # PROGRAM START # determine whether we have gettext; make it a no-op if we do not @@ -279,17 +402,10 @@ if [ ! $(type -t gettext) ]; then } fi -# check for help flags -if [ "$1" = "-h" -o "$1" = "--help" ]; then - usage - exit 0 -fi - -# check for version flags -if [ "$1" = "-V" -o "$1" = "--version" ]; then - version - exit 0 -fi +case "$1" in + -h|--help) usage; exit 0;; + -V|--version) version; exit 0;; +esac # check for correct number of args if [ $# -lt 2 ]; then @@ -297,11 +413,6 @@ if [ $# -lt 2 ]; then exit 1 fi -# main routine -gstmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\ - error "$(gettext "Cannot create temp directory for database building.")"; \ - exit 1) - # figure out what program we are cmd="$(basename $0)" if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then @@ -309,55 +420,42 @@ if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then exit 1 fi +tmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\ + error "$(gettext "Cannot create temp directory for database building.")"; \ + exit 1) + +trap 'clean_up' EXIT +trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT +trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT +trap 'trap_exit "$(gettext "An unknown error has occured. Exiting...")"' ERR + success=0 # parse arguments for arg in "$@"; do - if [ "$arg" == "--force" -o "$arg" == "-f" ]; then - warning "$(gettext "the -f and --force options are no longer recognized")" - msg2 "$(gettext "use options=(force) in the PKGBUILD instead")" - elif [ "$arg" == "--quiet" -o "$arg" == "-q" ]; then - QUIET=1 - elif [ -z "$REPO_DB_FILE" ]; then - REPO_DB_FILE="$arg" - if [ -f "$REPO_DB_FILE" ]; then - if ! (bsdtar -tf "$REPO_DB_FILE" | grep -q "/desc"); then - error "$(gettext "Repository file '%s' is not a proper pacman database.")" "$REPO_DB_FILE" - exit 1 - fi - msg "$(gettext "Extracting database to a temporary location...")" - bsdtar -xf "$REPO_DB_FILE" -C "$gstmpdir" - elif [ "$cmd" == "repo-remove" ]; then - error "$(gettext "Repository file '%s' was not found.")" "$REPO_DB_FILE" - exit 1 - fi - else - if [ "$cmd" == "repo-add" ]; then - if [ -f "$arg" ]; then - if ! bsdtar -tf "$arg" .PKGINFO 2>&1 >/dev/null; then - error "$(gettext "'%s' is not a package file, skipping")" "$arg" - else - msg "$(gettext "Adding package '%s'")" "$arg" - - if db_write_entry "$arg"; then - success=1 - fi - fi + case "$arg" in + -q|--quiet) QUIET=1;; + + -f|--force) + warning "$(gettext "the -f and --force options are no longer recognized")" + msg2 "$(gettext "use options=(force) in the PKGBUILD instead")" + ;; + + *) + if [ -z "$REPO_DB_FILE" ]; then + REPO_DB_FILE="$arg" + LOCKFILE="$REPO_DB_FILE.lck" + check_repo_db else - error "$(gettext "Package '%s' not found.")" "$arg" + case "$cmd" in + repo-add) add $arg && success=1 ;; + repo-remove) remove $arg && success=1 ;; + esac fi - elif [ "$cmd" == "repo-remove" ]; then - msg "$(gettext "Searching for package '%s'...")" "$arg" - - if db_remove_entry "$arg"; then - success=1 - else - error "$(gettext "Package matching '%s' not found.")" "$arg" - fi - fi - fi + ;; + esac done -# if all operations were a success, re-zip database +# if at least one operation was a success, re-zip database if [ $success -eq 1 ]; then msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE" @@ -370,22 +468,20 @@ if [ $success -eq 1 ]; then filename=$(basename "$REPO_DB_FILE") - pushd "$gstmpdir" 2>&1 >/dev/null + cd "$tmpdir" if [ -n "$(ls)" ]; then bsdtar -c${TAR_OPT}f "$filename" * else # the database will be moved to .old below, and there will be no new one to replace it error "$(gettext "All packages have been removed from the database. Deleting '%s'.")" "$REPO_DB_FILE" fi - popd 2>&1 >/dev/null + cd "$startdir" [ -f "$REPO_DB_FILE" ] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" - [ -f "$gstmpdir/$filename" ] && mv "$gstmpdir/$filename" "$REPO_DB_FILE" + [ -f "$tmpdir/$filename" ] && mv "$tmpdir/$filename" "$REPO_DB_FILE" else msg "$(gettext "No packages modified, nothing to do.")" fi -# remove the temp directory used to unzip -[ -d "$gstmpdir" ] && rm -rf "$gstmpdir" - +exit 0 # vim: set ts=2 sw=2 noet: |