Use the correct database format Instead of getting all the info from the filename, which was a bit ugly, use xdelta3 to get the source and destination files Instead of looking for .delta files in the current directory when adding a package, which was not very flexible, allow .delta files to be added with repo-add just like package files. delta files can also be removed with repo-remove. This is simply done by looking for a .delta extension in the arguments, and calling the appropriate db_write_delta or db_remove_delta functions. Example usage: repo-add repo/test.db.tar.gz repo/libx11-1.1.99.2-2-x86_64.pkg.tar.gz repo-add repo/test.db.tar.gz repo/libx11-1.1.5-2_to_1.1.99.2-2-x86_64.delta repo-remove repo/test.db.tar.gz libx11-1.1.5-2_to_1.1.99.2-2-x86_64.delta Note that db_write_entry had to be modified so that the deltas file is not lost on a package upgrade (remove + add). FS#13414 should be fixed in the same time, by printing a different message when the same package is added. Normal output: ==> Adding package 'repo/libx11-1.1.99.2-2-x86_64.pkg.tar.gz' -> Removing version 'libx11-1.1.5-2'... Warning: ==> Adding package 'repo/libx11-1.1.99.2-2-x86_64.pkg.tar.gz' ==> WARNING: An entry for 'libx11-1.1.99.2-2' already exists, overwriting... Signed-off-by: Xavier Chantry <shiningxc@gmail.com> --- scripts/repo-add.sh.in | 203 ++++++++++++++++++++++++++++-------------------- 1 files changed, 120 insertions(+), 83 deletions(-) diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index c6d25aa..95b7959 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -57,8 +57,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 +93,84 @@ write_list_entry() { fi } -# write a delta entry to the pacman database -# arg1 - path to delta +# Get the package name from the delta filename +getpkgname() { + local tmp + + tmp=${1##*/} + echo ${tmp%-*-*_to*} +} + +find_pkgentry() +{ + local pkgname=$1 + local pkgentry + for pkgentry in $gstmpdir/$pkgname*; do + name=${pkgentry##*/} + if [ "${name%-*-*}" = "$pkgname" ]; then + echo $pkgentry + return 0 + fi + done + return 1 +} + +# 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="$(getpkgname $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 exists, overwriting...")" "$deltafile" + sed -i "/$oldfile.*$newfile/d" $deltas 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="$(getpkgname $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 "/$filename/d" $deltas + return 0 + fi + + return 1 +} # end db_write_delta # write an entry to the pacman database # arg1 - path to package @@ -172,19 +220,34 @@ db_write_entry() return 1 fi - # remove an existing entry if it exists, ignore failures - db_remove_entry "$pkgname" - startdir=$(pwd) pushd "$gstmpdir" 2>&1 >/dev/null - # create package directory - mkdir "$pkgname-$pkgver" + # remove an eventual existing entry but keep the deltas file + if [ -d "$pkgname-$pkgver" ]; then + # special case : same version already exists + # package directory can be kept, just delete depends and desc + warning "$(gettext "An entry for '%s' already exists, overwriting...")" "$pkgname-$pkgver" + rm "$pkgname-$pkgver"/{depends,desc} + else + pkgentry=$(find_pkgentry $pkgname) + # create package directory + mkdir "$pkgname-$pkgver" + if [ -n "$pkgentry" ]; then + # keep the deltas file then delete the existing entry + if [ -f "$pkgentry/deltas" ]; then + cp "$pkgentry/deltas" "$pkgname-$pkgver" + fi + msg2 "$(gettext "Removing version '%s'...")" "${pkgentry##*/}" + rm -rf $pkgentry + fi + fi + cd "$pkgname-$pkgver" # create desc entry msg2 "$(gettext "Creating 'desc' db entry...")" - echo -e "%FILENAME%\n$(basename "$1")\n" >>desc + echo -e "%FILENAME%\n"${1##*/}"\n" >>desc echo -e "%NAME%\n$pkgname\n" >>desc echo -e "%VERSION%\n$pkgver\n" >>desc [ -n "$pkgdesc" ] && echo -e "%DESC%\n$pkgdesc\n" >>desc @@ -211,61 +274,16 @@ db_write_entry() 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" return 0 } # end 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" - fi - done - - popd 2>&1 >/dev/null -} # end db_remove_entry - # PROGRAM START # determine whether we have gettext; make it a no-op if we do not @@ -299,7 +317,7 @@ gstmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\ exit 1) # figure out what program we are -cmd="$(basename $0)" +cmd=${0##*/} if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then error "$(gettext "Invalid command name '%s' specified.")" "$cmd" exit 1 @@ -329,7 +347,14 @@ for arg in "$@"; do else if [ "$cmd" == "repo-add" ]; then if [ -f "$arg" ]; then - if ! bsdtar -tf "$arg" .PKGINFO 2>&1 >/dev/null; then + if [ "${arg##*.}" == "delta" ]; then + msg "$(gettext "Adding delta '%s'")" "$arg" + if db_write_delta "$arg"; then + success=1 + else + error "$(gettext "No package entry for '%s'.")" "$arg" + fi + elif ! 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" @@ -339,15 +364,27 @@ for arg in "$@"; do fi fi else - error "$(gettext "Package '%s' not found.")" "$arg" + error "$(gettext "File '%s' not found.")" "$arg" fi elif [ "$cmd" == "repo-remove" ]; then - msg "$(gettext "Searching for package '%s'...")" "$arg" - - if db_remove_entry "$arg"; then - success=1 + if [ "${arg##*.}" == "delta" ]; then + msg "$(gettext "Searching for delta '%s'...")" "$arg" + if db_remove_delta "$arg"; then + success=1 + else + error "$(gettext "Delta matching '%s' not found.")" "$arg" + fi else - error "$(gettext "Package matching '%s' not found.")" "$arg" + msg "$(gettext "Searching for package '%s'...")" "$arg" + + pkgentry=$(find_pkgentry $arg) + if [ -n "$pkgentry" ]; then + msg2 "$(gettext "Removing existing version '%s'...")" "${pkgentry##*/}" + rm -rf $pkgentry + success=1 + else + error "$(gettext "Package matching '%s' not found.")" "$arg" + fi fi fi fi @@ -364,7 +401,7 @@ if [ $success -eq 1 ]; then "$REPO_DB_FILE" ;; esac - filename=$(basename "$REPO_DB_FILE") + filename=${REPO_DB_FILE##*/} pushd "$gstmpdir" 2>&1 >/dev/null if [ -n "$(ls)" ]; then -- 1.6.1.3