#!/bin/bash
#
# autodist repositories maintainance script
# Copyright (c) 2007-2026 by Silvan Calarco <silvan@openmamba.org>
#
. /etc/autodist/config
[ -r /etc/autodist/config-secret ] && . /etc/autodist/config-secret

if [ "$LOCAL_REPS_BASE_DIR" = "" ]; then
   LOCAL_REPS_BASE_DIR=/var/autodist
   LOCAL_REPS_FETCH=1
fi
[ -r /etc/autodist/secrets ] && . /etc/autodist/secrets

if [ -z "$DISTROQUERY_API_URL" ]; then
   echo "ERROR: DISTROQUERY_API_URL is not defined in configuration; aborting." >&2
   exit 1
fi

basearch=x86_64

me=${0##*/}

function usage() {

   echo "autodist repositories maintainance script"
   echo "Copyright (c) 2007-2026 by Silvan Calarco <silvan@openmamba.org>"
   echo 
   echo "Usage:"
   echo "$me archive REPOSITORY PKGS ..."
   echo "$me diff REPOSITORY [PKGS ...] [-d REPOSITORY]"
   echo "$me distromatic REPOSITORY"
   echo "$me install REPOSITORY [PKGS ...] [-f]"
   echo "$me import REPOSITORY [PKGS ...] [-d REPOSITORY] [-s] [-y]"
   echo "$me inspect REPOSITORY {PKGS ...} [-d REPOSITORY]"
   echo "$me list"
   echo "$me query REPOSITORY PKGS ..."
   echo "$me release REPOSITORY [PKGS ...] [-d REPOSITORY] [-s] [-y]"
   echo "$me restore REPOSITORY PKGS ..."
   echo "$me search [-i] [-r regexp] STRING"
   echo "$me setwarning REPOSITORY {PKG ...} -t \"TEXT\""
   echo "$me verify REPOSITORY [PKGS ...]"
   echo
   echo " -d      use given repository as destination (default: base)"
   echo " -f      force operation"
   echo " -r      match repositories with given regexp"
   echo " -s      simulate operations to see if it would work"
   echo " -t      warning text"
   echo " -y      assume yes to all questions (be careful!)"
}

# get_packages_from_last_build - populate the global $packages array with all
#   source packages in the given repository via the distroquery API, sorted by
#   build time (most recent first).
#
# $1: repository name
function get_packages_from_last_build() {
   local rep=$1 _output _ret
   [ "$rep" ] || return
   _output=$(autodist-distroquery repository "$rep" buildtime desc 2>&1)
   _ret=$?
   if [ $_ret -ne 0 ]; then
      echo "ERROR: autodist-distroquery failed (exit code $_ret): $(echo "$_output" | grep "^ERROR:" | head -1)" >&2
      exit $_ret
   fi
   eval $(echo "$_output" | grep -v "^ERROR:")
   packages=(${pkg_list[*]})
}

# get_pkg_srcinfo - look up a source package via the distroquery REST API.
#   Sets the global variables pkg_name, pkg_version, pkg_release,
#   pkg_repository, pkg_buildtime on success; clears pkg_archs, pkg_arch on
#   every call. Returns without setting pkg_name if the package is not found
#   or belongs to a different repository.
#
# $1: repository name
# $2: package name
get_pkg_srcinfo() {

   local rep pkg

   [ $1 ] && rep=$1 || exit 200
   [ $2 ] && pkg=$2 || exit 200

   get_pkg_buildinfo "$rep" any "$pkg"
}

# get_pkg_buildinfo - retrieve package metadata via the distroquery REST API
#   (GET /package/{rep}/{pkg} for a named package, or GET /repository/{rep}
#   for the full package list). On success sets the global variables pkg_name,
#   pkg_version, pkg_release, pkg_arch, pkg_buildtime, pkg_builds[],
#   pkg_archs[]. pkg_archs[] is always populated with every non-noarch
#   architecture the package is present in (or ["noarch"] for noarch-only
#   packages). When $2 is "any", the function auto-selects the first available
#   architecture. When $3 is omitted the pkg_list[] array is populated with
#   all source package names in the repository.
#
# $1: repository name
# $2: architecture, or "any" to auto-detect
# $3: package name (optional)
function get_pkg_buildinfo() {

   local pkg i a

   [ $1 ] && rep=$1 || exit 200
   [ $2 ] && buildarch=$2 || exit 200
   [ $3 ] && pkg=$3

   pkg_archs=();
   pkg_header=();
   pkg_builds=();
   pkg_obsoletes=();
   pkg_list=();

   unset pkg_name pkg_arch pkg_version pkg_release \
         pkg_group pkg_license pkg_size pkg_buildtime pkg_altrep pkg_repository

   local _distroquery_output _distroquery_ret
   if [ "$pkg" ]; then
      # Per-package API lookup via autodist-distroquery
      if [ "$buildarch" = "any" ]; then
         _distroquery_output=$(autodist-distroquery package-all-archs "$rep" "$pkg" 2>&1)
      else
         _distroquery_output=$(autodist-distroquery package "$rep" "$pkg" "$buildarch" 2>&1)
      fi
   else
      # Full package list via autodist-distroquery
      _distroquery_output=$(autodist-distroquery repository "$rep" 2>&1)
   fi
   _distroquery_ret=$?
   if [ $_distroquery_ret -ne 0 ]; then
      echo "ERROR: autodist-distroquery failed (exit code $_distroquery_ret): $(echo "$_distroquery_output" | grep "^ERROR:" | head -1)" >&2
      return $_distroquery_ret
   fi
   eval $(echo "$_distroquery_output" | grep -v "^ERROR:")
}

# get_pkg_info - look up a binary package via the distroquery REST API. Sets
#   the global variables pkg_name, pkg_version, pkg_release, pkg_size,
#   pkg_repository, pkg_arch. pkg_name is empty when the package is not found.
#
# $1: repository name
# $2: architecture
# $3: binary package name
function get_pkg_info() {

   local pkg buildarch rep _output _ret

   [ $1 ] && rep=$1 || exit 200
   [ $2 ] && buildarch=$2 || exit 200
   [ $3 ] && pkg=$3 || exit 200

   _output=$(autodist-distroquery package-binary "$rep" "$pkg" "$buildarch" 2>&1)
   _ret=$?
   if [ $_ret -ne 0 ]; then
      echo "ERROR: autodist-distroquery failed (exit code $_ret): $(echo "$_output" | grep "^ERROR:" | head -1)" >&2
      exit $_ret
   fi
   eval $(echo "$_output" | grep -v "^ERROR:")
}

# Common curl options for robust remote operations
CURL_OPTS="--connect-timeout 10 --retry 3 --retry-delay 5"

# import_file - transfer a single RPM or SRPM file from the source location
#   (ORIG_URL_ARCH) to the destination location (DEST_URL_ARCH), handling all
#   four combinations of local/remote source and destination:
#     local  -> local : plain cp; in "backup" mode the source file is removed.
#     local  -> remote: curl PUT upload; source file is removed after upload.
#     remote -> local : curl GET download (preferring a local mirror if
#                       available via ORIG_URL_LOCAL_ARCH); in "backup" mode
#                       the remote source file is deleted via curl -Q DELE.
#     remote -> remote: WebDAV MOVE (backup mode) or COPY (release mode),
#                       both server-side operations using ORIG_RW_URL_ARCH and
#                       DEST_RW_URL_ARCH. Credentials are the global
#                       AUTODIST_WEBDAV_USER / AUTODIST_WEBDAV_PASSWD loaded
#                       from /etc/autodist/secrets.
#   Does nothing when $simulate is "1".
#
# $1: filename (basename only; paths are taken from ORIG_URL_ARCH / DEST_URL_ARCH)
# $2: import_mode - "backup" to remove the source file after transfer,
#                   anything else to leave it in place
function import_file() {
 [ $1 ] || exit 200

 local f import_mode
 f=$1
 import_mode=$2
 if [ "$import_mode" = "backup" ]; then
    curl_delete_add="-Q '-DELE $f'"
 else
    curl_delete_add=""
 fi

 [ "$simulate" = "1" ] && return

 if [ "$ORIG_MODE" = "remote" ]; then
     if [ -d $ORIG_URL_LOCAL_ARCH -a ! -f $ORIG_URL_LOCAL_ARCH/$f ]; then
       echo "WARNING: package missing in local mirror; setting copy from remote repository." >&2
     fi
 
     if [ "$DEST_MODE" = "local" ]; then
        # remote -> local
        if [ -d $ORIG_URL_LOCAL_ARCH -a -f $ORIG_URL_LOCAL_ARCH/$f ]; then
           echo -n "(L) "
           # if file exists in a local mirror use it by preference
           cp $ORIG_URL_LOCAL_ARCH/$f $DEST_URL_ARCH/ || {
              echo "ERROR: cannot move file $ORIG_URL_LOCAL_ARCH/$f to $DEST_URL_ARCH/$f; aborting." >&2
              return 1
           }
           #chown ftp$DEST_REPOSITORY:users $DEST_URL_ARCH/$f
           eval curl -s $CURL_OPTS -u${AUTODIST_REPOSITORIES_REMOTE_FTPUSER}:${AUTODIST_REPOSITORIES_REMOTE_FTPPASS} $ORIG_URL_ARCH $curl_delete_add >/dev/null && {
              rm -f $ORIG_URL_LOCAL_ARCH/$f
              touch $ORIG_URL_LOCAL_ARCH
           } || {
              echo
              echo "WARNING: cannot delete remote file $ORIG_URL_ARCH/$f; you'll have to delete it." >&2
           }
        else
           echo -n "(R) "
           curl -s $CURL_OPTS -u${AUTODIST_REPOSITORIES_REMOTE_FTPUSER}:${AUTODIST_REPOSITORIES_REMOTE_FTPPASS} \
              --get $ORIG_URL_ARCH/$f \
              -o $DEST_URL_ARCH/$f $curl_delete_add || {
              echo
              echo "ERROR: cannot get file $ORIG_URL_ARCH/$f; aborting." >&2
              return 1
           }
        fi
     else
        # remote -> remote: server-side WebDAV MOVE (backup) or COPY (release)
        if [ "$import_mode" = "backup" ]; then
           local webdav_method=MOVE
        else
           local webdav_method=COPY
        fi
        curl -s --fail $CURL_OPTS -u${AUTODIST_WEBDAV_USER}:${AUTODIST_WEBDAV_PASSWD} \
           -X $webdav_method \
           -H "Destination: ${DEST_RW_URL_ARCH}${f}" \
           ${ORIG_RW_URL_ARCH}${f} || {
              echo
              echo "ERROR: cannot ${webdav_method} file ${ORIG_RW_URL_ARCH}${f} to ${DEST_RW_URL_ARCH}${f}; aborting." >&2
              return 1
           }
     fi
 else
     if [ "$DEST_MODE" = "local" ]; then
        # local -> local
        cp $ORIG_URL_ARCH/$f $DEST_URL_ARCH/ || {
           echo "ERROR: cannot copy file $ORIG_URL_ARCH/$f to $DEST_URL_ARCH/$f; aborting." >&2
           return 1
        }
        #chown ftp$DEST_REPOSITORY:users $DEST_URL_ARCH/$f
        touch $DEST_URL_ARCH
	if [ "$import_mode" = "backup" ]; then
           rm -f $ORIG_URL_ARCH/$f || {
              echo "ERROR: cannot remove file $ORIG_URL_ARCH/$f; aborting." >&2
              return 1
           }
           touch $ORIG_URL_ARCH
	fi
     else
        # local -> remote
        echo -n "(R) "
        curl -s $CURL_OPTS -u${AUTODIST_REPOSITORIES_REMOTE_FTPUSER}:${AUTODIST_REPOSITORIES_REMOTE_FTPPASS} \
           -T $ORIG_URL_ARCH/$f \
           $DEST_URL_ARCH/ || {
              echo
              echo "ERROR: cannot send file $ORIG_URL_ARCH/$f; aborting." >&2
              return 1
        }
        rm -f $ORIG_URL_ARCH/$f || {
              echo
              echo "WARNING: cannot delete local file $ORIG_URL_ARCH/$f; you'll have to delete it." >&2
        }
        touch $ORIG_URL_ARCH
     fi
 fi

}

# backup_local_file - move one or more local files into the $LOCAL_BACKUP
#   directory, creating it if necessary. Does nothing when $simulate is "1".
#
# $1: space-separated list of absolute file paths to move
function backup_local_file() {
 [ $1 ] || return

 [ -e $LOCAL_BACKUP ] || mkdir -p $LOCAL_BACKUP
 movefiles=$1

 #`find $DEST_URL_ARCH -maxdepth 1 -regex ".*/${pkgname}-[^-]*-[^-]*"`
 for m in $movefiles; do
    echo "  - backing up $m"
    if [ "$simulate" != "1" ]; then
       mv $m $LOCAL_BACKUP/ || {
          echo "ERROR: can't move $m to $LOCAL_BACKUP; aborting." >&2
          return 1
       }
       touch `dirname $m`
    fi
 done

}

# backup_remote_file - archive a single RPM or SRPM file on a remote server
#   using a server-side WebDAV MOVE into the archive directory. The archive
#   directory is created first via MKCOL (a 405 response is ignored since it
#   means the directory already exists). Does nothing when $simulate is "1".
#
# $1: full WebDAV source URL of the file to archive
# $2: full WebDAV URL of the destination archive directory (no trailing slash)
function backup_remote_file() {
   local src=$1
   local archive_dir=$2
   local filename="${src##*/}"
   local archdir="${src%/*}"; archdir="${archdir##*/}"

   [ "$simulate" = "1" ] && return

   echo "  - backing up ${archdir}/${filename}"
   # Ensure the archive directory exists; ignore 405 (already exists)
   curl -s $CURL_OPTS -o /dev/null -u${AUTODIST_WEBDAV_USER}:${AUTODIST_WEBDAV_PASSWD} \
      -X MKCOL "${archive_dir}/"
   curl -s $CURL_OPTS -u${AUTODIST_WEBDAV_USER}:${AUTODIST_WEBDAV_PASSWD} \
      -X MOVE \
      -H "Destination: ${archive_dir}/${filename}" \
      "${src}" || {
         echo "ERROR: cannot archive remote file ${src}; aborting." >&2
         return 1
      }
}

# backup_package - archive all files belonging to a source package (SRPM and
#   per-arch RPMs) into the repository's old/<pkgname>_<date>/ directory.
#   For local repositories uses backup_local_file() (mv); for remote
#   repositories uses backup_remote_file() (WebDAV MOVE). Falls back to
#   get_pkg_srcinfo when the package has no binary builds in distromatic
#   (source-only warning).
#
# $1: source package name
# $2: repository name (default: $destrepository)
# $3: "preloaded" to skip get_pkg_buildinfo and use current pkg_* globals
function backup_package() {
   local rep reg i

   [ "$1" ] || return
   [ "$2" ] && rep=$2 || rep=$destrepository

   archive_pkg=$1

   if [ "$3" != "preloaded" ]; then
      get_pkg_buildinfo $rep any $archive_pkg
      if [ $? -ne 0 ]; then
         echo "ERROR: distroquery query failed for $archive_pkg in $rep; skipping archive." >&2
         return 1
      fi
   fi

   if [ ! "$pkg_name" ]; then
      get_pkg_srcinfo $rep $archive_pkg
      if [ "$pkg_name" ]; then
         echo "WARNING: only source package has been found in repository" >&2
      fi
   fi

   if [ "$pkg_name" ]; then
      LOCAL_BACKUP=$DEST_URL_LOCAL/$rep/old/${pkg_name}_${BACKUP_DATE}
      REMOTE_BACKUP=${REPS_BASE_URL}/$rep/old/${pkg_name}_${BACKUP_DATE}
      PKG_FILENAME="$pkg_name-$pkg_version-$pkg_release.src.rpm"

      if [ "$DEST_MODE" = "remote" ]; then
         backup_remote_file ${REPS_BASE_URL}/$rep/SRPMS.base/$PKG_FILENAME $REMOTE_BACKUP
      elif [ -f $DEST_URL_LOCAL/$rep/SRPMS.base/$PKG_FILENAME ]; then
         backup_local_file $DEST_URL_LOCAL/$rep/SRPMS.base/$PKG_FILENAME
      else
         echo "WARNING: package $PKG_FILENAME does not exist in local repository" >&2
      fi

      for a in ${pkg_archs[*]}; do
          local _builds_ref="pkg_builds_${a}[@]"
          local _arch_ref="pkg_arch_${a}"
          for i in "${!_builds_ref}"; do
             PKG_FILENAME="$i-$pkg_version-$pkg_release.${!_arch_ref}.rpm"
             if [ "$DEST_MODE" = "remote" ]; then
                backup_remote_file ${REPS_BASE_URL}/$rep/RPMS.$a/$PKG_FILENAME $REMOTE_BACKUP
             elif [ -f $DEST_URL_LOCAL/$rep/RPMS.$a/$PKG_FILENAME ]; then
                backup_local_file $DEST_URL_LOCAL/$rep/RPMS.$a/$PKG_FILENAME
             else
                echo "WARNING: package $PKG_FILENAME does not exist in local repository" >&2
             fi
          done
      done
   else
      echo "WARNING: package $archive_pkg does not exist in $rep; skipping." >&2
   fi
}

# restore_local_file - copy one or more files from a backup directory back into
#   the appropriate repository subdirectory (RPMS.<arch>/ for binary packages,
#   SRPMS.base/ when ARCH is empty). Does nothing when $simulate is "1".
#
# $1: space-separated list of filenames to restore (basenames only)
# $2: absolute path to the backup directory containing the files
# $3: architecture string, or empty for SRPM restoration
# $4: destination repository name
function restore_local_file() {
   [ $1 ] || return
   [ $2 ] || return
   [ $4 ] || return

   local restorefiles=$1
   local backupprefix=$2
   local ARCH=$3
   local restorerepository=$4

   #`find $DEST_URL_ARCH -maxdepth 1 -regex ".*/${pkgname}-[^-]*-[^-]*"`
   for r in $restorefiles; do
      [ "$ARCH" ] && restoredest=$DEST_URL_LOCAL/$restorerepository/RPMS.$ARCH/ || restoredest=$DEST_URL_LOCAL/$restorerepository/SRPMS.base/
      echo "restoring $r to $restorerepository"
      if [ "$simulate" != "1" ]; then
         cp ${backupprefix}/$r $restoredest || {
            echo "ERROR: can't copy $p to $restoredest; aborting." >&2
            return 1
         }
         touch $restoredest
      fi
   done
}

# restore_package - interactively restore a previously archived package from the
#   repository's old/<pkgname>_*/ backup directories. Lists all available
#   backups, prompts the user to select one and confirm, then restores all SRPM
#   and per-arch RPM files via restore_local_file.
#   Only works with local repositories.
#
# $1: source package name
# $2: repository name (default: $destrepository)
function restore_package() {
   local rep reg i

   [ "$1" ] || return
   [ "$2" ] && rep=$2 || rep=$destrepository

   restore_pkg=$1

   get_pkg_buildinfo $rep any $restore_pkg
   if [ $? -ne 0 ]; then
      echo "ERROR: distroquery query failed for $restore_pkg in $rep; skipping restore." >&2
      return 1
   fi

   if [ ! "$pkg_name" ]; then
      echo "Info: package $restore_pkg does not exist in $rep"
   fi

   LOCAL_RESTORE_PREFIX=$DEST_URL_LOCAL/$rep/old/${restore_pkg}_

   local cnt=0
   local RESTORE_NAMES=()
   ls ${LOCAL_RESTORE_PREFIX}* &>/dev/null && \
   for f in ${LOCAL_RESTORE_PREFIX}*; do
     [ "$cnt" = 0 ] && echo "Available backups: "
     cnt=`expr $cnt + 1`
     RESTORE_NAMES=(${RESTORE_NAMES[*]} `echo ${f/*_/}`)
     echo "($cnt) ${RESTORE_NAMES[$cnt-1]}"
   done
   [ "$cnt" == "0" ] && {
      echo "Sorry, no backups availables for ${restore_pkg} in $rep"
      return
   }
   local ans=0
   while [ $ans -le 0 2>/dev/null -o $ans -gt $cnt 2>/dev/null ]; do
      echo
      echo -n "Please select the entry to restore or press ENTER to skip (1-$cnt): "
      read ans
      [ "$ans" ] || return
      [ $ans -eq $ans 2>/dev/null ] || ans=0
   done

   echo "Restoring: "
   for f in `ls ${LOCAL_RESTORE_PREFIX}${RESTORE_NAMES[$ans-1]}`; do
      echo -n "${f/*\/} "
   done
   echo
   echo -n "Ok to restore [y/N]? "
   read ans1
   [ "$ans1" != "y" -a "$ans1" != "Y" ] && return

   for a in ${AUTODIST_ARCHS[*]}; do
      for f in `ls ${LOCAL_RESTORE_PREFIX}${RESTORE_NAMES[$ans-1]}/*.${a}.rpm 2>/dev/null`; do
         restore_local_file ${f/*\/} ${LOCAL_RESTORE_PREFIX}${RESTORE_NAMES[$ans-1]}/ $a $rep
      done
   done

   for f in `ls ${LOCAL_RESTORE_PREFIX}${RESTORE_NAMES[$ans-1]}/*.src.rpm 2>/dev/null`; do
         restore_local_file ${f/*\/} ${LOCAL_RESTORE_PREFIX}${RESTORE_NAMES[$ans-1]}/ "" $rep
   done
}

# import_package - transfer a complete source package (SRPM + all per-arch
#   RPMs) from $origrepository to $destrepository. The function:
#   1. Validates arch consistency: if the package is missing for an arch in
#      $origrepository but present in $destrepository with a different version,
#      the import is refused (unless $force=1).
#   2. Verifies the SRPM file actually exists in the source location (HTTP HEAD
#      for remote repos, plain file check for local).
#   3. Prompts for confirmation unless $assume_yes=1.
#   4. Transfers files via import_file and backs up the previous version in
#      $destrepository when it differs.
#   5. Triggers autodist-git syncpkg if $AUTODIST_GIT_SYNC is set.
#   Return codes: 0=success, 253=SRPM not found, 254/255=arch mismatch.
#
# $1: source package name
# $2: import_mode - "backup" (used by import command, removes source files)
#                   or "release" (used by release command, leaves source files)
function import_package() {
   [ $1 ] || exit 200

   local import_pkg import_mode

   import_pkg=$1
   import_mode=$2

   # check for all architectures
   for a in ${AUTODIST_ARCHS[*]}; do
      # check release in dest repository
      get_pkg_buildinfo $destrepository $a $import_pkg
      [ $? -ne 0 ] && {
         echo "ERROR: distroquery query failed for $import_pkg in $destrepository/$a; aborting import." >&2
         return 252
      }
      [ "$pkg_name" ] && {
         dest_ver=$pkg_version
         dest_rel=$pkg_release
         get_pkg_buildinfo $origrepository $a $import_pkg
         [ $? -ne 0 ] && {
            echo "ERROR: distroquery query failed for $import_pkg in $origrepository/$a; aborting import." >&2
            return 252
         }
         [ "$pkg_name" ] || {
            for b in ${AUTODIST_ARCHS[*]}; do
               if [ "$b" != "$a" ]; then
                  # Get upstream version in other architecture, then if same version -> merge
                  get_pkg_buildinfo $origrepository $b $import_pkg
                  [ $? -ne 0 ] && {
                     echo "ERROR: distroquery query failed for $import_pkg in $origrepository/$b; aborting import." >&2
                     return 252
                  }
               fi
               [ "$pkg_name" ] && break
            done
            if [ "$pkg_name" -a "$dest_ver-$dest_rel" != "$pkg_version-$pkg_release" ]; then
               [ "$a" == "$basearch" -a "$force" != "1" ] && {
                  echo "ERROR: package $import_pkg for $a does not exist in $origrepository and can't merge due to different versions; skipping." >&2
                  return 254
               }
               if [ "$force" = "1" ]; then
                  echo "WARNING: package $import_pkg for $a is missing in $origrepository but present in $destrepository." >&2
                  echo "Import forced. You will need to port package to the missing arch." >&2
               else
                  echo "ERROR: package $import_pkg for $a is missing in $origrepository. This would break package in $destrepository($a) repository." >&2
                  return 255
               fi
            fi
         }
      }
   done

   # check release in dest repository
   get_pkg_buildinfo $destrepository any $import_pkg
   [ $? -ne 0 ] && {
      echo "ERROR: distroquery query failed for $import_pkg in $destrepository; aborting import." >&2
      return 252
   }

   [ "$pkg_version" ] && {
      destpkgname="$pkg_name"
      destpkgversion="$pkg_version-$pkg_release"
   } || destpkgversion="none"

   # Save dest package state now, before it gets overwritten by the
   # origrepository query below and then invalidated by the file transfers.
   # backup_package will use this snapshot instead of re-querying distroquery
   # (which would see the already-transferred new version).
   local _saved_dest_pkg_name="$pkg_name"
   local _saved_dest_pkg_version="$pkg_version"
   local _saved_dest_pkg_release="$pkg_release"
   local _saved_dest_pkg_archs=("${pkg_archs[@]}")
   local _sva
   for _sva in "${pkg_archs[@]}"; do
      eval "_saved_dest_pkg_builds_${_sva}=(\"\${pkg_builds_${_sva}[@]}\")"
      eval "_saved_dest_pkg_arch_${_sva}=\"\${pkg_arch_${_sva}}\""
   done

   get_pkg_buildinfo $origrepository any $import_pkg
   [ $? -ne 0 ] && {
      echo "ERROR: distroquery query failed for $import_pkg in $origrepository; aborting import." >&2
      return 252
   }

   [ "$pkg_version" ] && {
      origpkgname="$pkg_name"
      origpkgversion="$pkg_version-$pkg_release"
   } || origpkgversion="none"

   [ $origpkgname ] || {
      echo "ERROR: package $import_pkg does not exist in $origrepository; aborting." >&2
      exit 200
   }

   DEST_URL_ARCH=$DEST_URL/$destrepository/SRPMS.base/
   ORIG_URL_ARCH=$ORIG_URL/$origrepository/SRPMS.base/
   ORIG_URL_LOCAL_ARCH=$ORIG_URL_LOCAL/$origrepository/SRPMS.base/
   ORIG_RW_URL_ARCH=${REPS_BASE_URL}/$origrepository/SRPMS.base/
   DEST_RW_URL_ARCH=${REPS_BASE_URL}/$destrepository/SRPMS.base/

   PKG_FILENAME="$origpkgname-$origpkgversion.src.rpm"

   # Check whether the source SRPM exists
   check_existence=0
   if [ "$ORIG_MODE" = "remote" ]; then
      http_code=$(curl -s $CURL_OPTS -o /dev/null -w "%{http_code}" \
         -u${AUTODIST_WEBDAV_USER}:${AUTODIST_WEBDAV_PASSWD} \
         --head "${ORIG_RW_URL_ARCH}${PKG_FILENAME}")
      [ "${http_code:0:1}" = "2" ] && check_existence=1
   else
      [ -f "$ORIG_URL_ARCH/$PKG_FILENAME" ] && check_existence=1
   fi

   if [ $check_existence = 1 ]; then

      [ "$destpkgversion" = "$origpkgversion" ] && {
         echo "WARNING: same version of $origpkgname exists in destination" >&2
      }

      if [ "$assume_yes" != "1" ]; then
         echo -n "Import $PKG_FILENAME $origpkgversion($origrepository) -> $destpkgversion($destrepository) [y/N]?"
         read ans
      fi

      [ "$assume_yes" = "1" -o "$ans" = "y" -o "$ans" = "Y" ] && {

         echo "  - importing SRPMS.base/$PKG_FILENAME"

         import_file $PKG_FILENAME $import_mode || return 1

         for a in ${pkg_archs[*]}; do
            local _builds_ref="pkg_builds_${a}[@]"
            local _arch_ref="pkg_arch_${a}"
            for i in "${!_builds_ref}"; do
               PKG_FILENAME="$i-$origpkgversion.${!_arch_ref}.rpm"
               DEST_URL_ARCH=$DEST_URL/$destrepository/RPMS.$a/
               ORIG_URL_ARCH=$ORIG_URL/$origrepository/RPMS.$a/
               ORIG_URL_LOCAL_ARCH=$ORIG_URL_LOCAL/$origrepository/RPMS.$a/
               ORIG_RW_URL_ARCH=${REPS_BASE_URL}/$origrepository/RPMS.$a/
               DEST_RW_URL_ARCH=${REPS_BASE_URL}/$destrepository/RPMS.$a/
               echo "  - importing RPMS.$a/$PKG_FILENAME"
               import_file $PKG_FILENAME $import_mode || return 1
            done
         done

      # backup old stuff in destination repository
      [ "$destpkgversion" != "none" -a \
      "$destpkgversion" != "$origpkgversion" ] && {
         # Restore the dest package state captured before file transfers so
         # that backup_package uses the pre-import metadata (the new files
         # are already in place and distroquery would no longer find the old
         # version).
         pkg_name="$_saved_dest_pkg_name"
         pkg_version="$_saved_dest_pkg_version"
         pkg_release="$_saved_dest_pkg_release"
         pkg_archs=("${_saved_dest_pkg_archs[@]}")
         local _rva
         for _rva in "${_saved_dest_pkg_archs[@]}"; do
            eval "pkg_builds_${_rva}=(\"\${_saved_dest_pkg_builds_${_rva}[@]}\")"
            eval "pkg_arch_${_rva}=\"\${_saved_dest_pkg_arch_${_rva}}\""
         done
         backup_package $import_pkg $destrepository preloaded
      }

      # Sync new release with autodist-git
      [ "$AUTODIST_GIT_SYNC" != "" -a "${simulate}" != "1" ] && autodist-git syncpkg ${import_pkg}

   } # ans = y

   else # check_existence != 1
      echo "ERROR: $import_pkg does not exist in '$origrepository' repository" >&2
      return 253
   fi
   return 0
}

# extract_diffinfo - extract comparison data for a package from a local
#   repository into a temporary directory. Writes the following files in $3:
#     <pkgname>.spec  - spec file extracted from the SRPM via autospec
#     buildrequires   - build-time dependencies (from SRPM rpm -qp --requires)
#     requires        - runtime requires aggregated across all binary RPMs
#     provides        - runtime provides aggregated across all binary RPMs
#     files           - file list aggregated across all binary RPMs
#   Returns 1 if the package is not found, if the SRPM is missing or larger
#   than 1 GB, or if spec extraction fails.
#   FIXME: only works with basearch (i586)
#
# $1: source package name
# $2: repository name
# $3: absolute path to an existing temporary directory for output files
function extract_diffinfo() {
   PKG=$1
   REP=$2
   TMP=$3
   local i

   get_pkg_buildinfo $REP $basearch $PKG
   if [ "$pkg_name" ]; then
     PKG_FILENAME="${LOCAL_REPS_BASE_DIR}/$REP/SRPMS.base/$pkg_name-$pkg_version-$pkg_release.src.rpm"
     [ -e "$PKG_FILENAME" ] || {
        echo "ERROR: package $PKG_FILENAME missing in $origrepository; skipping" >&2
        return 1     
     }
     local filesize=`stat -c %s $PKG_FILENAME`
     [ $filesize -gt 1073741824 ] && {
        echo "WARNING: $PKG_FILENAME size of $filesize is more than 1GB; skipping" >&2
        return 1
     }
     rpm -qp $PKG_FILENAME --requires > $TMP/buildrequires

     autospec -q -x $PKG_FILENAME -F \*.spec --destdir $TMP >/dev/null || {
        echo "ERROR: could not extract specfile from $PKG_FILENAME; skipping package" >&2
     return 1
     }
     [ -e "$TMP_SPEC_DIR/$pkg_name.spec" ] || {
        SPEC_FOUND="`ls $TMP_SPEC_DIR/*.spec`"
        mv $SPEC_FOUND $TMP_SPEC_DIR/$pkg_name.spec
        echo "WARNING: specfile name should be $pkg_name.spec instead of ${SPEC_FOUND/*\//} in $REP repository" >&2
     }
     > $TMP/requires
     > $TMP/provides
     for i in ${pkg_builds[*]}; do
         PKG_FILENAME="${LOCAL_REPS_BASE_DIR}/$REP/RPMS.$basearch/$i-$pkg_version-$pkg_release.$pkg_arch.rpm"
        [ -e "$PKG_FILENAME" ] || {
           echo "ERROR: package $PKG_FILENAME missing in $origrepository; skipping" >&2
           return 1
        }
        rpm -qp $PKG_FILENAME --requires >> $TMP/requires
        rpm -qp $PKG_FILENAME --provides >> $TMP/provides
        rpm -qlp $PKG_FILENAME >> $TMP/files
     done
   else
      #echo "WARNING: can't find package $PKG in $REP repository" >&2
      return 1
   fi
   return 0
}

[ $1 ] || { usage; exit 0; }

origrepository=
destrepository=base
packages=
command=
simulate=0

while [ "$1" ]; do
   case $1 in
      -d)
         destrepository=$2; shift ;;
      -r)
         searchrep=$2; shift ;;
      -s)
         simulate=1 ;;
      -t)
         shift
         warningtext="$@"
         break ;;
      -f)
         force=1 ;;
      -i)
         ignorecase=1 ;;
      -y)
         assume_yes=1 ;;
      *)
         if [ "$command" ]; then
            case "$command" in
            "import"|"release"|"query"|"verify"|"archive"|"restore"|"diff"|"inspect"|"install"|"setwarning"|"distromatic")
               if [ "$origrepository" ]; then
                  if [ "$packages" ]; then
                     packages="$packages $1"
                  else
                     packages="$1"
                  fi
               else
                  origrepository=$1
               fi
               ;;
            "search")
               [ "$searchstring" ] && {
                  echo "ERROR: invalid option $1; aborting." >&2
                  exit 1
               }
               searchstring="$1"
               ;;
            *)  usage
               echo "ERROR: invalid option $1; aborting." >&2
               exit 1
               ;;
            esac
         else
            case "$1" in
            "import"|"release"|"query"|"verify"|"archive"|"restore"|"list"|"diff"|"inspect"|"install"|"setwarning"|"distromatic"|"search") command=$1 ;;
            *)
               usage
               echo "Errror: $1 is not a valid command; aborting."
               exit 1
               ;;
            esac
         fi
         ;;
   esac
   shift
done
[ "$command" = "" ] && { usage; exit 0; }

#[ "$command" = "list" ] && echo "Local repositories:"
for a in ${AUTODIST_REPOSITORIES_LOCAL_REPS[*]}; do
  [ "$a" = "$destrepository" ] && DEST_MODE=local;
  [ "$a" = "$origrepository" ] && ORIG_MODE=local;
  [ "$command" = "list" ] && echo "$a"
done
#[ "$command" = "list" ] && echo "Remote repositories:"
for a in ${AUTODIST_REPOSITORIES_REMOTE_REPS[*]}; do
  [ "$a" = "$destrepository" ] && DEST_MODE=remote;
  [ "$a" = "$origrepository" ] && ORIG_MODE=remote;
  [ "$command" = "list" ] && echo "$a"
done
[ "$command" = "list" ] && exit 0;

[ "$command" = "search" ] && {
   [ "$ignorecase" ] && GREP_OPTS="-i"
   for rep in ${AUTODIST_REPOSITORIES_LOCAL_REPS[*]} ${AUTODIST_REPOSITORIES_REMOTE_REPS[*]}; do
      [[ "$rep" =~ "$searchrep" ]] || continue
      [ -r ${LOCAL_REPS_BASE_DIR}/$rep/SRPMS.base ] || continue
      ls --color=none ${LOCAL_REPS_BASE_DIR}/$rep/SRPMS.base | grep $GREP_OPTS "$searchstring" 2>/dev/null | \
      while read PKGLINE; do
        [ "$PKGLINE" ] && {
           echo "$rep(source): ${PKGLINE/ *}"
        }
     done
     for a in ${AUTODIST_ARCHS[*]}; do
        [ -r ${LOCAL_REPS_BASE_DIR}/$rep/RPMS.$a ] || continue
         ls --color=none ${LOCAL_REPS_BASE_DIR}/$rep/RPMS.$a | grep $GREP_OPTS "$searchstring" 2>/dev/null | \
         while read PKGLINE; do
            [ "$PKGLINE" ] && {
               echo "$rep($a): ${PKGLINE/ *}"
            }
         done
      done
   done
   exit 0
}

[ "$origrepository" ] || { usage; exit 200; }

[ "$ORIG_MODE" ] || { echo "ERROR: $origrepository is not a valid repository; aborting." >&2; exit 200; }

[ "$command" = "query" ] && {
   [ "$packages" ] || { usage; exit 1; }
   for i in $packages; do
      get_pkg_buildinfo $origrepository any $i
      if [ ! "$pkg_name" ]; then
         echo "$i: package not found in $origrepository repository"
      else
         for a in ${pkg_archs[*]}; do
            get_pkg_buildinfo $origrepository $a $i
            if [ "$pkg_name" ]; then
               echo "Repository:$origrepository($a)"
               echo "Name:      $pkg_name"
               echo "BuildArch: $pkg_arch"
               echo "Version:   $pkg_version"
               echo "Release:   $pkg_release"
               echo "Group:     $pkg_group"
               echo "License:   $pkg_license"
               echo "Size:      $pkg_size"
               echo "Builds:    ${pkg_builds[*]}"
               echo "Obsoletes: ${pkg_obsoletes[*]}"
               echo
            fi
         done
     fi
   done
   exit 0;
}

[ "$command" = "verify" ] && {
   [ "$packages" ] || {
      get_pkg_buildinfo $origrepository any
      packages=${pkg_list[*]}
   }
   for i in $packages; do
      get_pkg_buildinfo $origrepository any $i
      if [ ! "$pkg_name" ]; then
         echo "$i: package not found in $origrepository repository"
      else
         PKG_FILENAME="$i-$pkg_version-$pkg_release.src.rpm"
         rpm2cpio ${LOCAL_REPS_BASE_DIR}/${origrepository}/SRPMS.base/$PKG_FILENAME &>/dev/null || {
         echo "WARNING: source package $PKG_FILENAME is empty or corrupted." >&2
         }

         for a in ${AUTODIST_ARCHS[*]}; do
            get_pkg_buildinfo $origrepository $a $i
            if [ "$pkg_name" ]; then
               for l in ${pkg_builds[*]}; do
                  PKG_FILENAME="$l-$pkg_version-$pkg_release.$pkg_arch.rpm"
                  rpm2cpio ${LOCAL_REPS_BASE_DIR}/${origrepository}/RPMS.$a/$PKG_FILENAME &>/dev/null || {
                     echo "WARNING: package $PKG_FILENAME($a) is empty or corrupted." >&2
                  }
               done
            fi
         done
      fi
   done
   exit 0;
}

[ "$command" = "diff" ] && {
   [ "$packages" ] || {
      get_pkg_buildinfo $origrepository any
      packages=${pkg_list[*]}
   }
   TMP_SPEC_DIR=`mktemp -d --tmpdir=/dev/shm`
   for i in $packages; do
      echo
      echo "*******************************************************************"
      echo "$i package check:"
      echo "*******************************************************************"

      extract_diffinfo $i $origrepository $TMP_SPEC_DIR || continue
      [ -e $TMP_SPEC_DIR/$i.spec ] || {
         echo "ERROR: could not extract specfile for $i in $origrepository repository; skipping" >&2
         continue
      }
      mv $TMP_SPEC_DIR/$i.spec $TMP_SPEC_DIR/$i.spec.origrep
      mv $TMP_SPEC_DIR/files $TMP_SPEC_DIR/files.origrep
      sort -u $TMP_SPEC_DIR/buildrequires > $TMP_SPEC_DIR/buildrequires.origrep
      sort -u $TMP_SPEC_DIR/requires > $TMP_SPEC_DIR/requires.origrep
      sort -u $TMP_SPEC_DIR/provides > $TMP_SPEC_DIR/provides.origrep
   
      extract_diffinfo $i $destrepository $TMP_SPEC_DIR || {
         echo "Looks like a new package; inspecting data:"
         echo ""
         echo "SPECFILE:"
         echo "========="
         cat $TMP_SPEC_DIR/$i.spec.origrep
         echo ""
         echo "REQUIRES:"
         echo "========="
         cat $TMP_SPEC_DIR/requires.origrep
         echo ""
         echo "PROVIDES:"
         echo "========="
         cat $TMP_SPEC_DIR/provides.origrep
         echo ""
         echo "FILES:"
         echo "======"
         cat $TMP_SPEC_DIR/files.origrep
         continue
      }
      [ -e $TMP_SPEC_DIR/$i.spec ] || {
         echo "ERROR: could not extract specfile for $i in $destrepository repository; skipping" >&2
      }
      mv $TMP_SPEC_DIR/$i.spec $TMP_SPEC_DIR/$i.spec.destrep
      mv $TMP_SPEC_DIR/files $TMP_SPEC_DIR/files.destrep
      sort -u $TMP_SPEC_DIR/buildrequires > $TMP_SPEC_DIR/buildrequires.destrep
      sort -u $TMP_SPEC_DIR/requires > $TMP_SPEC_DIR/requires.destrep
      sort -u $TMP_SPEC_DIR/provides > $TMP_SPEC_DIR/provides.destrep

      echo "Showing differences between package version in $origrepository and $destrepository:"
      echo ""
      echo "SPECFILE:"
      echo "========="
      diff -u $TMP_SPEC_DIR/$i.spec.destrep $TMP_SPEC_DIR/$i.spec.origrep
      echo ""
      echo "BUILDREQUIRES:"
      echo "=============="
      diff -u $TMP_SPEC_DIR/buildrequires.destrep $TMP_SPEC_DIR/buildrequires.origrep
      echo ""
      echo "REQUIRES:"
      echo "========="
      diff -u $TMP_SPEC_DIR/requires.destrep $TMP_SPEC_DIR/requires.origrep
      echo ""
      echo "PROVIDES:"
      echo "========="
      diff -u $TMP_SPEC_DIR/provides.destrep $TMP_SPEC_DIR/provides.origrep
      echo ""
      echo "FILES:"
      echo "======"
      diff -u $TMP_SPEC_DIR/files.destrep $TMP_SPEC_DIR/files.origrep
      echo
   done
   rm -rf $TMP_SPEC_DIR
   exit 0;
}

[ "$command" = "setwarning" ] && {
   [ "$packages" ] || { usage; exit 1; }
   TMP_SPEC_DIR=`mktemp -d`
   for i in $packages; do
      extract_diffinfo $i $origrepository $TMP_SPEC_DIR
      [ -e $TMP_SPEC_DIR/$i.spec ] || {
         echo "ERROR: could not extract specfile for $i in $origrepository repository; aborting." >&2
         exit 1
      }
      echo "$warningtext" > ${LOCAL_REPS_BASE_DIR}/distromatic/$origrepository/warnings/$i.in
   done  
   [ "$TMP_SPEC_DIR" != "/" ] && rm -rf $TMP_SPEC_DIR
   exit 0
}

[ "$command" = "inspect" ] && {
   [ "$packages" ] || { usage; exit 1; }
   TMP_SPEC_DIR=`mktemp -d`
   for i in $packages; do
      extract_diffinfo $i $origrepository $TMP_SPEC_DIR
      [ -e $TMP_SPEC_DIR/$i.spec ] || {
         echo "ERROR: could not extract specfile for $i in $origrepository repository; aborting." >&2
         exit 1
      }
      echo "$i: details of package in $origrepository repository"
      echo ""
      echo "SPECFILE:"
      echo "========="
      cat $TMP_SPEC_DIR/$i.spec
      echo ""
      echo "REQUIRES:"
      echo "========="
      cat $TMP_SPEC_DIR/requires
      echo ""
      echo "PROVIDES:"
      echo "========="
      cat $TMP_SPEC_DIR/provides
   done
   [ "$TMP_SPEC_DIR" != "/" ] && rm -rf $TMP_SPEC_DIR
   exit 0;
}

[ "$command" = "install" ] && {
   [ "$packages" ] || { usage; exit 1; }
   myarch=`uname -p`
   if [ "$myarch" = "*686" -o "$myarch" = "athlon" -o "$myarch" = "pentium*" ]; then
      myarch="i586"
   fi
   for i in $packages; do
      pkg=$i
      pkgarch=
      if [ "${i/.*}" != "${i}" ]; then
         pkg=${i/.*}
         pkgarch=${i/*.}
      fi
      if [ "$pkgarch" -a "$pkgarch" != "$myarch" ]; then
         get_pkg_info $origrepository $pkgarch $pkg
         [ "$pkg_name" ] || {
            echo "WARNING: $pkg not found in $origrepository for arch $pkgarch; skipping."
            continue
         }
      else
         get_pkg_info $origrepository $myarch $pkg
         [ "$pkg_name" ] || {
            echo "WARNING: $pkg not found in $origrepository for arch $myarch; skipping."
            continue
         }
      fi
      pkg_file=${pkg_name}-${pkg_version}-${pkg_release}.$pkg_arch.rpm
      pkg_path=${LOCAL_REPS_BASE_DIR}/$pkg_repository/RPMS.$pkg_arch/${pkg_file}
      [ -r $pkg_path ] || {
         echo "WARNING: file $pkg_path should exist but doesn't; skipping."
         continue
      }
      echo "Installing $pkg_file..."
      if [ "$force" = "1" ]; then
         rpm -i $pkg_path --force
         rpmret=$?
         [ $rpmret -gt 0 ] && echo "WARNING: rpm returned $rpmret"
         if [ "$pkg_arch" != "$myarch" ]; then
            pkg_file=${pkg_name}-${pkg_version}-${pkg_release}.$myarch.rpm
            pkg_path=${LOCAL_REPS_BASE_DIR}/$pkg_repository/RPMS.$myarch/${pkg_file}
            echo "Other arch installation forced; reinstalling native arch package after..."
            rpm -i $pkg_path --force
            rpmret=$?
            [ $rpmret -gt 0 ] && echo "WARNING: rpm returned $rpmret"
         fi
      else
         rpm -i $pkg_path
         rpmret=$?
         [ $rpmret -gt 0 ] && echo "WARNING: rpm returned $rpmret"
      fi
   done
   exit 0;
}

[ "$command" = "distromatic" ] && {
   [ -d ${LOCAL_REPS_BASE_DIR}/$origrepository/specs ] || mkdir ${LOCAL_REPS_BASE_DIR}/$origrepository/specs
   [ -d ${LOCAL_REPS_BASE_DIR}/$origrepository/patches ] || mkdir ${LOCAL_REPS_BASE_DIR}/$origrepository/patches

   while read name repository epoch version release buildtime; do
      [ -e ${LOCAL_REPS_BASE_DIR}/$origrepository/SRPMS.base/$name-$version-$release.src.rpm ] && {
         [ ${LOCAL_REPS_BASE_DIR}/$origrepository/SRPMS.base/$name-$version-$release.src.rpm -nt \
           ${LOCAL_REPS_BASE_DIR}/$origrepository/specs/$name.spec ] && {
            autospec -x ${LOCAL_REPS_BASE_DIR}/$origrepository/SRPMS.base/$name-$version-$release.src.rpm -F '*.spec' \
                     --destdir ${LOCAL_REPS_BASE_DIR}/$origrepository/specs/ -q >/dev/null
            touch ${LOCAL_REPS_BASE_DIR}/$origrepository/specs/$name.spec
            grep -i "^Patch[0-9]*:" ${LOCAL_REPS_BASE_DIR}/$origrepository/specs/$name.spec &>/dev/null && {
               autospec -x ${LOCAL_REPS_BASE_DIR}/$origrepository/SRPMS.base/$name-$version-$release.src.rpm -F '*.patch' \
                        --destdir ${LOCAL_REPS_BASE_DIR}/$origrepository/patches/ -q >/dev/null
            }
         }
      }
   done < <(autodist-distroquery repository-srclist $origrepository)
   exit 0
}

[ "$simulate" = "1" ] && echo "Simulation mode enabled."
#
# import and other active commands
#
if [ "$DEST_MODE" = "remote" ]; then
   DEST_URL=${AUTODIST_REPOSITORIES_REMOTE_FTP}/pub/openmamba
else
   DEST_URL=${LOCAL_REPS_BASE_DIR}
fi
DEST_URL_LOCAL=${LOCAL_REPS_BASE_DIR}

# ORIG_URL_LOCAL is set if a local copy of the repository exists
# and will be preferred for file transfer optimizations
if [ "$ORIG_MODE" = "remote" ]; then
  ORIG_URL=${AUTODIST_REPOSITORIES_REMOTE_FTP}/pub/openmamba
else
  ORIG_URL=${LOCAL_REPS_BASE_DIR}
fi
ORIG_URL_LOCAL=${LOCAL_REPS_BASE_DIR}

BACKUP_DATE=`date +%y%m%d.%H%M%S`
LOCAL_BACKUP=$DEST_URL/$destrepository/old

[ "$command" = "archive" ] && {
   DEST_URL=$ORIG_URL
   DEST_URL_LOCAL=$ORIG_URL_LOCAL
   DEST_MODE=$ORIG_MODE

   [ "$packages" ] || { usage; exit 1; }

   RET=0
   for i in $packages; do
      backup_package $i $origrepository
      [ $? -ne 0 ] && RET=`expr $RET + 1`
   done

   exit $RET
}

[ "$command" = "restore" ] && {
   DEST_URL=$ORIG_URL
   DEST_URL_LOCAL=$ORIG_URL_LOCAL
   DEST_MODE=$ORIG_MODE

   [ "$ORIG_MODE" = "remote" ] && {
      echo "ERROR: restore is only implemented in local repository; exiting." >&2
      exit 1
   }
   [ "$packages" ] || { usage; exit 1; }

   for i in $packages; do
      restore_package $i $origrepository
   done

   exit 0

}

[ "$command" = "import" -o "$command" = "release" ] && {

   [ "$origrepository" = "$destrepository" ] && {
      echo "ERROR: source and destination repository cannot be the same; aborting." >&2; exit 200; }

   if [ "$command" = "import" ]; then
      echo "Importing ${packages}: $origrepository ($ORIG_MODE) => $destrepository ($DEST_MODE)"
      backup_mode=backup
   else
      echo "Releasing ${packages}: $origrepository ($ORIG_MODE) => $destrepository ($DEST_MODE)"
      backup_mode=release
   fi

   if [ ! "$packages" ]; then
      get_packages_from_last_build $origrepository
   fi

   RET=0
   for i in ${packages[*]}; do
      import_package $i $backup_mode
      IMPORT_RET=$?
      if [ $IMPORT_RET -eq 255 -a "${AUTODIST_REPOSITORIES_TRANSITIONAL_REP}" -a \
           "${AUTODIST_REPOSITORIES_TRANSITIONAL_REP}" != "$destrepository" -a \
           "${AUTODIST_REPOSITORIES_TRANSITIONAL_REP}" != "$origrepository" -a \
           "${AUTODIST_REPOSITORIES_TRANSITIONAL_REP/-*}" = "${destrepository/-*}" ]; then
         echo "Use -f to force import to $destrepository; now trying to import to ${AUTODIST_REPOSITORIES_TRANSITIONAL_REP} instead."
         destrepositorysave=$destrepository
         destrepository=${AUTODIST_REPOSITORIES_TRANSITIONAL_REP}
         import_package $i $backup_mode
         IMPORT_RET=$?
         destrepository=$destrepositorysave
      fi
      if [ $IMPORT_RET -ne 0 ]; then
         RET=`expr $RET + 1`
      fi
   done

   exit $RET
}

usage
echo "ERROR: $command is not a valid command; aborting." >&2
exit 1
