diff --git a/pkg/de-p1st-repo/PKGBUILD b/pkg/de-p1st-repo/PKGBUILD index 1438825..1ccf1c5 100644 --- a/pkg/de-p1st-repo/PKGBUILD +++ b/pkg/de-p1st-repo/PKGBUILD @@ -2,7 +2,7 @@ _pkgname=repo _reponame=arch-pkg pkgname="de-p1st-$_pkgname" -pkgver=0.1.0 +pkgver=0.1.1 pkgrel=1 pkgdesc="Bash script to manage remote Arch Linux repository" arch=('any') @@ -28,6 +28,7 @@ package() { install -Dm0555 arch-repo-push-new.sh "$pkgdir"/usr/bin/arch-repo-push-new install -Dm0555 arch-repo-receive-new.sh "$pkgdir"/usr/bin/arch-repo-receive-new + install -Dm0555 arch-repo-vercmp.sh "$pkgdir"/usr/bin/arch-repo-vercmp install -Dm0644 arch-repo.cfg "$pkgdir"/etc/de-p1st-repo/arch-repo.cfg chown 0:0 "$pkgdir"/etc/de-p1st-repo/arch-repo.cfg diff --git a/pkg/de-p1st-repo/README.md b/pkg/de-p1st-repo/README.md index d8dd72f..ab85343 100644 --- a/pkg/de-p1st-repo/README.md +++ b/pkg/de-p1st-repo/README.md @@ -34,3 +34,7 @@ Server = https://arch.p1st.de 2. Push new packages to remote repository * `arch-repo-push-new` + +3. Check for AUR updates + +* `arch-repo-vercmp` \ No newline at end of file diff --git a/pkg/de-p1st-repo/arch-repo-push-new.sh b/pkg/de-p1st-repo/arch-repo-push-new.sh index fef2ac8..8332a3e 100644 --- a/pkg/de-p1st-repo/arch-repo-push-new.sh +++ b/pkg/de-p1st-repo/arch-repo-push-new.sh @@ -6,9 +6,19 @@ source /etc/de-p1st-repo/arch-repo.cfg || exit cd "${LOCAL_PKG_DIR}" || exit +# get list of new packages, one package per line +rsync --ignore-existing --out-format="%n" --dry-run \ + ./*.pkg.tar.{xz,zst} "${REMOTE_SSH_HOST}":"${REMOTE_PKG_DIR}" > new-pkg.txt || exit + + # transfer new packages using rsync rsync --ignore-existing --progress --human-readable \ ./*.pkg.tar.{xz,zst} "${REMOTE_SSH_HOST}":"${REMOTE_PKG_DIR}" || exit +# transfer new-pkg.txt +rsync --ignore-times --checksum --progress --human-readable \ + new-pkg.txt "${REMOTE_SSH_HOST}":"${REMOTE_PKG_DIR}" || exit + + # add each new package to database -ssh "${REMOTE_SSH_HOST}" "/usr/bin/arch-repo-receive-new" +ssh "${REMOTE_SSH_HOST}" "/usr/bin/arch-repo-receive-new" || exit diff --git a/pkg/de-p1st-repo/arch-repo-receive-new.sh b/pkg/de-p1st-repo/arch-repo-receive-new.sh index d0a8a28..e07a882 100644 --- a/pkg/de-p1st-repo/arch-repo-receive-new.sh +++ b/pkg/de-p1st-repo/arch-repo-receive-new.sh @@ -4,82 +4,154 @@ source /etc/de-p1st-repo/arch-repo.cfg || exit +function main(){ + cd "${REMOTE_PKG_DIR}" || return $? + add_new_to_db || return $? + generate_index || return $? +} + + +# +# add all packages to database +# +function add_all_to_db(){ + echo "Adding all packages to db ..." + sort_all_pkgname_pkgver || return $? + + echo "For each package name: Add latest version to database ..." + for PKGNAME in db/*; do + PKGNAME=$(basename "${PKGNAME}") || return $? # strip directory and suffix from filename + add_to_db "${PKGNAME}" || return $? + done +} # # add new packages to database # -function add_to_db(){ +function add_new_to_db(){ echo "Adding new packages to db ..." + sort_new_pkgname_pkgver || return $? - sort_pkgname_pkgver || return $? + echo "For each new package name: Add latest version to database ..." + for PKGNAME in "${NEW_PKGNAMES[@]}"; do + add_to_db "${PKGNAME}" || return $? + done +} +# +# add package to database +# +function add_to_db(){ + # $1: package name + local PKGNAME + PKGNAME="$1" - echo "For each package: Add latest version to database ..." - for PKGNAME in db/*; do - PKGNAME=$(basename "${PKGNAME}") # strip directory and suffix from filename + # + # get latest version for $PKGNAME + # - # TODO - # db/* -> results in filenames db/FILE1 - # => remove prefix "db/" to get FILE1 - # e.g. use filename / basename (!) + # pick one random version as starting point for the latest version + local LATEST + for PKGVER in db/"${PKGNAME}"/*; do + PKGVER=$(basename "${PKGVER}") # strip directory and suffix from filename + LATEST="$PKGVER" + break + done - # - # get latest version for $PKGNAME - # + local cmp + for PKGVER in db/"$PKGNAME"/*; do + PKGVER=$(basename "${PKGVER}") # strip directory and suffix from filename - local LATEST - # pick one random version as starting point for the latest version - for PKGVER in db/"${PKGNAME}"/*; do - PKGVER=$(basename "${PKGVER}") # strip directory and suffix from filename + # compare the currently known latest version + # with the next version + cmp=$(vercmp "$LATEST" "$PKGVER") || return $? + # if the new version is larger, save it as LATEST + if [ "$cmp" -lt "0" ]; then LATEST="$PKGVER" - break - done + fi + done - local cmp - for PKGVER in db/"$PKGNAME"/*; do - PKGVER=$(basename "${PKGVER}") # strip directory and suffix from filename + # + # add latest version of PKGNAME to database + # - # compare the currently known latest version - # with the next version - cmp=$(vercmp "$LATEST" "$PKGVER") || return $? - # if the new version is larger, save it as LATEST - if [ "$cmp" -lt "0" ]; then - LATEST="$PKGVER" + PKG=$(cat "db/${PKGNAME}/${LATEST}") || return $? + repo-add --new "${REMOTE_DB_NAME}.db.tar.gz" "${PKG}" || return $? +} + + +# +# create files "db/$pkgname/$pkgver" with content "$PKG" (path to package file) +# +function sort_all_pkgname_pkgver(){ + echo "Cleanup ..." + rm -r db || return $? + + echo "Sorting all packages by package name and package version ..." + + for PKG in *.pkg.tar.{xz,zst}; do + sort_pkgname_pkgver "${PKG}" || return $? + done +} +# +# create files "db/$pkgname/$pkgver" with content "$PKG" (path to package file) +# +function sort_new_pkgname_pkgver(){ + # return: 0 on success; array $NEW_PKGNAMES + + echo "Sorting new packages by package name and package version ..." + + local NEW_PKGNAMES_TMP=() # list the names from new package-files; may contain duplicates + + mapfile -t PKGS < <(cat new-pkg.txt) + for PKG in "${PKGS[@]}"; do + sort_pkgname_pkgver "${PKG}" || return $? + NEW_PKGNAMES_TMP+=("${PKGNAME}") + done + + + # create array $NEW_PKGNAMES without duplicates + NEW_PKGNAMES=() + for NEW_PKGNAME_TMP in "${NEW_PKGNAMES_TMP[@]}"; do + local contains="0" + + # if NEW_PKGNAMES does already contain NEW_PKGNAME_TMP, + # then set contains to "1" + for i in "${NEW_PKGNAMES[@]}"; do + if [ "${NEW_PKGNAME_TMP}" = "${i}" ]; then + contains="1"; + break; fi done - # - # add latest version of PKGNAME to database - # - PKG=$(cat "db/${PKGNAME}/${LATEST}") || return $? - repo-add --new "${REMOTE_DB_NAME}.db.tar.gz" "${PKG}" || return $? - - true + if [ "${contains}" = "0" ]; then + NEW_PKGNAMES+=("${NEW_PKGNAME_TMP}") + fi done } - - # -# create files "./db/$pkgname/$pkgver" with content "$path_to_file" = "$PKG" +# create files "db/$pkgname/$pkgver" with content "$PKG" (path to package file) # function sort_pkgname_pkgver(){ - echo "Sorting packages by package name and package version ..." + # $1: PKG (path to package file) + # return: 0 on success; variables $PKGINFO, $PKGNAME, $PKGVER + local PKG + PKG="$1" - for PKG in *.pkg.tar.{xz,zst}; do - get_pkginfo "$PKG" || { echo "get_pkginfo failed"; return 1; } - get_pkgname "$PKGINFO" || { echo "get_pkgname failed"; echo "Content of PKGINFO: ${PKGINFO}"; return 1; } - get_pkgver "$PKGINFO" || { echo "get_pkgver failed"; echo "Content of PKGINFO: ${PKGINFO}"; return 1; } + get_pkginfo "$PKG" || { echo "get_pkginfo failed"; return 1; } + get_pkgname "$PKGINFO" || { echo "get_pkgname failed"; echo "Content of PKGINFO: ${PKGINFO}"; return 1; } + get_pkgver "$PKGINFO" || { echo "get_pkgver failed"; echo "Content of PKGINFO: ${PKGINFO}"; return 1; } - echo "Creating file ./db/${PKGNAME}/${PKGVER} with content ${PKG} ..." - mkdir -p "db/${PKGNAME}" || return $? - echo "${PKG}" > "db/${PKGNAME}/${PKGVER}" || return $? - done + echo "Creating file ./db/${PKGNAME}/${PKGVER} with content ${PKG} ..." + mkdir -p "db/${PKGNAME}" || return $? + echo "${PKG}" > "db/${PKGNAME}/${PKGVER}" || return $? } + # -# get .PKGINFO +# get content of .PKGINFO from package-file # function get_pkginfo(){ # $1: path to package file - # return: 0 on success + # return: 0 on success; variable $PKGINFO if endswith "$1" ".pkg.tar.xz"; then PKGINFO=$(tar -xf "$1" -O .PKGINFO --force-local) || { echo "tar failed"; return 1; } @@ -96,9 +168,9 @@ function get_pkginfo(){ # get pkgname from $PKGINFO # function get_pkgname(){ - # return: 0 on success; variable $PKGNAME + # return: 0 on success; variable $PKGNAME - # remove "pkgname = " as well as tailing whitespace characters + # remove "pkgname = " as well as tailing whitespace characters local tmp tmp=$(echo "${PKGINFO}" | grep '^pkgname') || { echo "grep failed"; return 1; } PKGNAME=$(echo "${tmp}" | sed 's|^pkgname\s*=\s*||; s|\s*$||') || { echo "sed failed"; return 1; } @@ -156,8 +228,4 @@ function generate_index(){ ' >> index.html } - - -cd "${REMOTE_PKG_DIR}" || exit -add_to_db || exit -generate_index || exit +main "$@" diff --git a/pkg/de-p1st-repo/arch-repo-vercmp.sh b/pkg/de-p1st-repo/arch-repo-vercmp.sh new file mode 100644 index 0000000..1c90c6c --- /dev/null +++ b/pkg/de-p1st-repo/arch-repo-vercmp.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# For all packages in repository $REMOTE_DB_NAME, +# compare package version with AUR and +# print all outdated packages +# + +source /etc/de-p1st-repo/arch-repo.cfg || exit + + + +function main(){ + echo "Running 'pacman -Sy' ..." + sudo pacman -Sy || return $? # update mirrors -> this will also get the latest version of repository-db $REMOTE_DB_NAME + + all_pkg_vers || return $? + check_aur_updates || return $? + + if [ "${#AUR_UPDATES[@]}" -gt "0" ]; then + echo "Repository ${REMOTE_DB_NAME} contains packages with available AUR updates:" + for AUR_PKG in "${AUR_UPDATES[@]}"; do + echo " ${AUR_PKG}" + done + else + echo "There are no pending AUR updates in repository ${REMOTE_DB_NAME}." + fi +} + +# +# Store packages from $PKG_VERS with available AUR updates in $AUR_UPDATES. +# $AUR_UPDATES is an array where each entry describes one outdated package with it's current and new version. +# +function check_aur_updates(){ + mapfile -t AUR_UPDATES < <(echo "$PKG_VERS" | aur vercmp) +} + +# +# Store all installed package names and their versions +# from repository $REMOTE_DB_NAME +# in variable $PKG_VERS. +# $PKG_VERS consists of multiple lines in the format: "" +# +function installed_pkg_vers(){ + # The paclist script is partof the package "pacman-contrib" + PKG_VERS=$(paclist "${REMOTE_DB_NAME}") || return $? +} + +# +# Store all package names and their versions +# from repository $REMOTE_DB_NAME +# in variable $PKG_VERS. +# $PKG_VERS contains of multiple lines in the format: "" +# +function all_pkg_vers(){ + PKG_VERS=$(pacman -S --list "${REMOTE_DB_NAME}" | sed 's|^de-p1st\s*||; s|\s*\[installed.*\]\s*$||') || return $? +} + +main "$@" diff --git a/pkg/de-p1st-repo/bash-unique-array-test.sh b/pkg/de-p1st-repo/bash-unique-array-test.sh new file mode 100644 index 0000000..4f90e6f --- /dev/null +++ b/pkg/de-p1st-repo/bash-unique-array-test.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# +# source: https://stackoverflow.com/a/13649357 +# + +a=(aa ac aa ad "ac ad") +declare -A b +for i in "${a[@]}"; do b["$i"]=1; done + +for i in "${!b[@]}"; do + echo ">> $i" +done