Commit 9aa47c6b92ce044b997dc80ab7ac0e33c090725c

Thomas de Grivel 2023-02-06T23:07:07

test

diff --git a/bin/shpkg b/bin/shpkg
index 4f5cdd6..16bb15c 100755
--- a/bin/shpkg
+++ b/bin/shpkg
@@ -28,13 +28,18 @@ Compilation operations :
  clean-build      remove object files
 
 Package operations :
+ clean-fake       remove fake installation directory
+ clean-package    remove built packages
  fake             install compiled sources into fake directory
  package          build package from sources
  install          install package
+ installed        list installed packages
  upgrade          pull sources, build package and install
+ upgrade --all    upgrade all packages
  uninstall        uninstall package
- clean-fake       remove fake installation directory
- clean-package    remove built packages
+
+Miscellaneous operations :
+ list             list local packages
 " >&2
     exit "$1"
 }
diff --git a/share/shpkg/shpkg.subr b/share/shpkg/shpkg.subr
index 73b9941..4c2d143 100644
--- a/share/shpkg/shpkg.subr
+++ b/share/shpkg/shpkg.subr
@@ -4,6 +4,7 @@
 set -e
 
 # Config
+
 SHPKG_DATE="$(date +%F_%T)"
 
 SHPKG_DIR="${SHPKG_DIR:-${HOME}/shpkg}"
@@ -18,6 +19,7 @@ SHPKG_VAR_DB_DIR="${SHPKG_DIR}/var/db/shpkg"
 SHPKG_PREFIX="${SHPKG_DIR}"
 
 # Console output
+
 verbose__puts () {
     {
         if [ "x$1" = "x1" ]; then
@@ -56,6 +58,7 @@ err () {
 }
 
 # C compiler
+
 if [ "x${CC}" = "x" ]; then
     if which cc >/dev/null; then
         CC=cc
@@ -80,6 +83,7 @@ SHPKG_PACKAGE_DIR="${SHPKG_TARGET_DIR}/packages"
 SHPKG_TAG_DIR="${SHPKG_TARGET_DIR}/tag"
 
 # OS detection
+
 SHPKG_OS="$(uname)"
 if [ "x${SHPKG_OS}" = "xLinux" ]; then
     SHPKG_OS="${SHPKG_OS}/$(uname -a | grep -io -e Debian -e gentoo -e Ubuntu)"
@@ -88,6 +92,7 @@ fi
 SHPKG_OS_DIR="${SHPKG_SHARE_DIR}/${SHPKG_OS}"
 
 # SHA256
+
 if which sha256 >/dev/null 2>&1; then
     SHPKG_SHA256=sha256
 elif which sha256sum >/dev/null 2>&1; then
@@ -108,6 +113,7 @@ shpkg_sha256sum () {
 }
 
 # Setup
+
 if ! [ -d "${SHPKG_FAKE_DIR}" ]; then
     verbose 1 mkdir -p "${SHPKG_FAKE_DIR}"
 fi
@@ -122,6 +128,7 @@ if ! [ -d "${SHPKG_VAR_DB_DIR}" ]; then
 fi
 
 # Repo index
+
 SHPKG_REPO_INDEX="${SHPKG_SHARE_DIR}/repo_index"
 if ! [ -f "${SHPKG_REPO_INDEX}" ]; then
     err 1 "${SHPKG_REPO_INDEX}: not found"
@@ -153,11 +160,12 @@ shpkg_src_parent_dir () {
 }
 
 # Source repository
+
 shpkg_clone () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_clone: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_PARENT_DIR="$(shpkg_src_parent_dir "${SHPKG_REPO}")"
         SHPKG_REPO_GIT_BRANCH="$(shpkg_git_branch "${SHPKG_REPO}")"
@@ -179,7 +187,7 @@ shpkg_fetch () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_fetch: unknown repo: $SHPKG_REPO"
         fi
         ( verbose 1 cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
               verbose 1 git fetch
@@ -191,7 +199,7 @@ shpkg_pull () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_pull: unknown repo: $SHPKG_REPO"
         fi
         ( verbose 1 cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
               verbose 1 git pull &&
@@ -213,7 +221,7 @@ shpkg_clean_sources () {
 shpkg_version () {
     SHPKG_REPO_DIR="$(shpkg_dir "$1")"
     if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-        err 1 "unknown repo: $SHPKG_REPO"
+        err 1 "shpkg_version: unknown repo: $SHPKG_REPO"
     fi
     SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
     if [ -d "${SHPKG_REPO_SRC_DIR}/.git" ]; then
@@ -224,6 +232,7 @@ shpkg_version () {
 }
 
 # Building from sources
+
 shpkg_autogen () {
     verbose 2 shpkg_clone "$@"
     for SHPKG_REPO; do
@@ -246,7 +255,7 @@ shpkg_build () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_build: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_OBJ_DIR="${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}"
         SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
@@ -275,7 +284,7 @@ shpkg_clean_build () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_clean_build: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_OBJ_DIR="${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}"
         SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
@@ -295,7 +304,7 @@ shpkg_clean_configure () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_clean_configure: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_VERSION="$(shpkg_version "${SHPKG_REPO}")"
         shpkg__tag_remove configure-done
@@ -306,7 +315,7 @@ shpkg_configure () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_configure: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${SHPKG_REPO}")"
         SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
@@ -358,7 +367,7 @@ shpkg_package () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_package: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_VERSION="$(shpkg_version "${SHPKG_REPO}")"
         SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
@@ -382,9 +391,16 @@ shpkg_package () {
 }
 
 # requires checked-out sources (git clone first)
+
 shpkg__tag_is_absent() {
     SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}/${SHPKG_REPO_VERSION}"
-    ! [ -f "${SHPKG_REPO_TAG_DIR}/$1" ]
+    if [ -f "${SHPKG_REPO_TAG_DIR}/$1" ]; then
+        verbose -n 2 "${SHPKG_REPO_TAG_DIR}/$1: present"
+        false
+    else
+        verbose -n 2 "${SHPKG_REPO_TAG_DIR}/$1: absent"
+        true
+    fi
 }
 
 shpkg__tag_remove() {
@@ -408,20 +424,45 @@ shpkg__tag_write() {
 }
 
 # Packages
+
+shpkg_is_installed () {
+    SHPKG_REPO="$1"
+    SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
+    if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
+        err 1 "shpkg_is_installed: unknown repo: $SHPKG_REPO"
+    fi
+    SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
+    if [ -f "${SHPKG_REPO_INSTALLED}" ]; then
+        verbose -n 2 "shpkg_is_installed ${SHPKG_REPO} -> true"
+        true
+    else
+        verbose -n 2 "shpkg_is_installed ${SHPKG_REPO} -> false"
+        false
+    fi
+}
+
+shpkg_is_system_package () {
+    if grep -Eq "^$1\$" "${SHPKG_OS_DIR}/system_packages"; then
+        verbose -n 2 "shpkg_is_system_package $1 -> true"
+        true
+    else
+        verbose -n 2 "shpkg_is_system_package $1 -> false"
+        false
+    fi
+}
+
 shpkg_install () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_install: unknown repo: $SHPKG_REPO"
         fi
-        if ! grep -Eq "^${SHPKG_REPO_DIR}\$" "${SHPKG_OS_DIR}/system_packages"; then
+        if ! shpkg_is_system_package "${SHPKG_REPO_DIR}"; then
             SHPKG_REPO_VERSION="$(shpkg_version "${SHPKG_REPO}")"
             SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
 	    SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
 	    SHPKG_REPO_INSTALLED_DIR="$(dirname "${SHPKG_REPO_INSTALLED}")"
-	    if ! [ -f "${SHPKG_REPO_INSTALLED}" ] ||
-		    ! head -n 1 < "${SHPKG_REPO_INSTALLED}" |
-		        grep "Version: ${SHPKG_REPO_VERSION}" >/dev/null; then
+	    if ! shpkg_is_installed "${SHPKG_REPO}"; then
 	        ( verbose 2 shpkg_install_dependencies "${SHPKG_REPO}"; )
 	        ( verbose 2 shpkg_build "${SHPKG_REPO}"; )
 	        ( verbose 2 shpkg_package "${SHPKG_REPO}"; )
@@ -448,7 +489,7 @@ shpkg_install_dependencies () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_install_dependencies: unknown repo: $SHPKG_REPO"
         fi
         SHPKG_REPO_DEPENDS_ON="$(shpkg_depends_on "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DEPENDS_ON}" != "x" ]; then
@@ -457,13 +498,35 @@ shpkg_install_dependencies () {
     done
 }
 
-# TODO: remove package files: hash files on install and delete them if not changed
-# TODO: remove metadata about installed packages
+shpkg_installed_version () {
+    SHPKG_REPO="$1"
+    SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
+    SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
+    if [ -f "${SHPKG_REPO_INSTALLED}" ]; then
+        head -n 1 "${SHPKG_REPO_INSTALLED}" | \
+            sed -e 's/^Version: //'
+    fi
+}
+
+shpkg_latest_is_installed () {
+    SHPKG_REPO="$1"
+    SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
+    SHPKG_REPO_INSTALLED_VERSION="$(shpkg_installed_version "${SHPKG_REPO}")"
+    SHPKG_REPO_VERSION="$(shpkg_version "${SHPKG_REPO}")"
+    if [ "x${SHPKG_REPO_INSTALLED_VERSION}" = "x${SHPKG_REPO_VERSION}" ]; then
+        verbose -n 2 "shpkg_latest_is_installed ${SHPKG_REPO} -> true"
+        true
+    else
+        verbose -n 2 "shpkg_latest_is_installed ${SHPKG_REPO} -> false"
+        false
+    fi
+}
+    
 shpkg_uninstall () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
         if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
-            err 1 "unknown repo: $SHPKG_REPO"
+            err 1 "shpkg_uninstall: unknown repo: $SHPKG_REPO"
         fi
 	SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
         if [ -f "${SHPKG_REPO_INSTALLED}" ]; then
@@ -485,14 +548,46 @@ shpkg_uninstall () {
 shpkg_upgrade () {
     verbose 2 shpkg_upgrade_shpkg
     if [ $# -gt 0 ]; then
-        verbose 2 shpkg_pull "$@"
-        verbose 2 shpkg_build "$@"
-        verbose 2 shpkg_package "$@"
-        verbose 2 shpkg_install "$@"
+        verbose 2 shpkg_upgrade_rec "$@"
     fi
 }
 
+shpkg_upgrade_rec () {
+    ( verbose 2 shpkg_upgrade_dependencies "$@"; )
+    for SHPKG_REPO; do
+        SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
+        if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
+            err 1 "shpkg_upgrade_rec: unknown repo: ${SHPKG_REPO}"
+        fi
+        if ! shpkg_is_system_package "${SHPKG_REPO_DIR}"; then
+            verbose 2 shpkg_pull "${SHPKG_REPO}"
+            if ! shpkg_latest_is_installed "${SHPKG_REPO}"; then
+                verbose 2 shpkg_build "${SHPKG_REPO}"
+                verbose 2 shpkg_package "${SHPKG_REPO}"
+                verbose 2 shpkg_uninstall "${SHPKG_REPO}"
+                verbose 2 shpkg_install "${SHPKG_REPO}"
+            fi
+        else
+            true
+        fi
+    done
+}
+
+shpkg_upgrade_dependencies () {
+    for SHPKG_REPO; do
+        SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"
+        if [ "x${SHPKG_REPO_DIR}" = "x" ]; then
+            err 1 "shpkg_upgrade_dependencies: unknown repo: $SHPKG_REPO"
+        fi
+        SHPKG_REPO_DEPENDS_ON="$(shpkg_depends_on "${SHPKG_REPO}")"
+        if [ "x${SHPKG_REPO_DEPENDS_ON}" != "x" ]; then
+            ( verbose 2 shpkg_upgrade_rec ${SHPKG_REPO_DEPENDS_ON}; )
+        fi
+    done
+}
+
 # Misc
+
 shpkg_clean_all () {
     for SHPKG_REPO; do
         SHPKG_REPO_DIR="$(shpkg_dir "${SHPKG_REPO}")"