From 6a757a93556770f227be9bdd85ce68c44d047777 Mon Sep 17 00:00:00 2001
From: davidovski <david@davidovski.xyz>
Date: Tue, 12 Apr 2022 12:16:47 +0100
Subject: added serial downloads and checking for root

---
 src/get.sh     | 87 ++++++++++++++++++++++++++++++++++++++++++----------------
 src/install.sh | 30 +++++++++-----------
 src/remove.sh  |  7 ++---
 src/util.sh    |  6 +++-
 src/xi.sh      |  7 +++++
 5 files changed, 91 insertions(+), 46 deletions(-)

(limited to 'src')

diff --git a/src/get.sh b/src/get.sh
index b99340f..d4a70a0 100755
--- a/src/get.sh
+++ b/src/get.sh
@@ -1,6 +1,5 @@
 #!/bin/sh
 
-
 # list all direct dependencies of a package
 #
 list_deps() {
@@ -52,14 +51,23 @@ resolve_deps () {
     echo ${deps} > $out
 }
 
+# get the download info for a package ($1)
+#
+# in format:
+#  url checksum size files 
+#
 get_package_download_info() {
     sed 1q ${PACKAGES_DIR}/*/$1
 }
 
+# return if a package is present on the system or not
+#
 is_installed() {
     [ -f "${INSTALLED_DIR}/$1/checksum" ]
 }
 
+# get the installed checksum of a package ($1)
+#
 get_installed_version () {
     local name=$1
     local file="${INSTALLED_DIR}/$name/checksum"
@@ -91,30 +99,37 @@ download_package () {
     ${VERBOSE} && printf "${LIGHT_BLACK}downloading $package from $url\n" $package $checksum
     touch $output
 
-    (curl ${CURL_OPTS} -o "$output_info" "$url.info" 2>> ${LOG_FILE} || printf "${RED}Failed to download info for %s\n" $package) &
-    (curl ${CURL_OPTS} -o "$output" "$url" 2>> ${LOG_FILE} || printf "${RED}Failed to download %s\n" $package) &
+    (curl ${CURL_OPTS} -o "$output_info" "$url.info" 2>> ${LOG_FILE} || printf "${RED}Failed to download info for %s\n" $package) 
+    (curl ${CURL_OPTS} -o "$output" "$url" 2>> ${LOG_FILE} || printf "${RED}Failed to download %s\n" $package) 
 }
 
+# download a list of packages
+# will download, verify and install the packages
+#
+# total_download: total number of bytes to download
+# packages: list of packages by name to download
+#
 download_packages () {
     local total_download=$1; shift
-    local packages=$@
     local outputs=""
 
     local out_dir="${PACKAGE_CACHE}"
     mkdir -p "$out_dir"
 
-    for package in $packages; do 
-        local output="${out_dir}/${checksum}.${package}.xipkg"
-        download_package $package $output
-        outputs="$outputs $output"
+    for package in $@; do 
+        outputs="$outputs ${out_dir}/${checksum}.${package}.xipkg" 
     done
+    fetch_serial $total_download $outputs
 
-    wait_for_download $total_download ${outputs}
-
-    set -- $outputs
+    validate_downloads $outputs
+}
 
+# validate signatures of downloaded packages
+#
+# outputs: list of xipkg files to verify and install
+validate_downloads () {
     local i=0
-    ${UNSAFE} || for pkg_file in ${outputs}; do 
+    ${UNSAFE} || for pkg_file in $@; do 
 
         ${QUIET} || hbar -T "${LARGE_CIRCLE} validating downloads..." $i $#
 
@@ -131,6 +146,8 @@ download_packages () {
     install $@
 }
 
+# get and install requested packages
+#
 get () {
     local requested=$@
     local missing="" already="" install="" update="" urls=""
@@ -194,23 +211,45 @@ get () {
     }
 }
 
+# just fetch the xipkg files of requested packages
+#
 fetch () {
-    local packages=$@
     local outputs=""
-
     local total_download=0
-    for package in $packages; do 
-        if package_exists $package; then
+    for package in $@; do 
+        package_exists $package && {
             set -- $(get_package_download_info $package)
-            size=$3
-            total_download=$((total_download+size))
-
-            local output="${package}.xipkg"
-            download_package $package $output
-            outputs="$outputs $output"
-        fi
+            total_download=$((total_download+$3))
+            outputs="$outputs ${package}.xipkg"
+        }
     done
 
-    wait_for_download $total_download ${outputs}
+    fetch_serial $total_download $outputs
+}
+
+# fetch package files in serial
+#
+# total_download: total number of bytes to download
+# outputs: list of package files to output to
+#
+fetch_serial () {
+    wait_for_download $@ &
+    shift
+    for output in $@; do 
+        download_package $(basename ${output%.*} | cut -d. -f2) $output 
+    done
 }
 
+# fetch package files in parallel
+#
+# total_download: total number of bytes to download
+# outputs: list of package files to output to
+#
+fetch_parallel () {
+    local total_download=$1
+    shift
+    for output in $@; do 
+        download_package $(basename ${output%.*} | cut -d. -f2) $output &
+    done
+    wait_for_download total_download $@ &
+}
diff --git a/src/install.sh b/src/install.sh
index a251820..8631251 100644
--- a/src/install.sh
+++ b/src/install.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 extract () {
-    tar -h -p --no-overwrite-dir -vvxf $1 -C ${SYSROOT} 2>/dev/null | grep ^- | tr -s " " | cut -d" " -f6 | cut -c2- 
+    tar -h --keep-old-files -p -vvxf $1 -C ${SYSROOT} 2>${LOG_FILE} | grep ^- | tr -s " " | cut -d" " -f6 | cut -c2- 
 }
 
 install_package () {
@@ -17,32 +17,28 @@ install_package () {
     set -- $(md5sum $pkg_file)
     local package_checksum=$1
     if [ ! -f $checksum ] || [ "$(cat $checksum)" != "$package_checksum" ]; then
-        mkdir -p "$installed_dir"
-        [ -f $files ] && mv $files $files.old
+        [ ! -d $installed_dir ] && mkdir -p "$installed_dir"
+
+        [ -f "$files" ] && {
+            for file in $(cat $files); do
+                rm -f ${SYSROOT}$file
+            done
+            rm $files
+        }
+
         ${VERBOSE} && printf "${BLACK}Extracting $name...\n"
         extract $pkg_file > $files
 
         [ -f $info_file ] && cp $info_file $info
-
         echo $package_checksum > $checksum
-
-
-        if [ -f "$files.old" ]; then
-            for file in $(diff $files $files.old | grep ^\> | cut -d' ' -f2); do
-                rm -f ${SYSROOT}$file
-            done
-            rm $files.old
-        fi
         return 0
-    else
-        ${VERBOSE} && printf "${BLACK}Skipping $name; already installed...\n"
-        return 1
     fi
+    ${VERBOSE} && printf "${BLACK}Skipping $name; already installed...\n"
+    return 1
 }
 
 get_package_filecount() {
-    local info=$(get_package_download_info $1)
-    set -- $info
+    set -- $(get_package_download_info $1)
     echo $4
 }
 
diff --git a/src/remove.sh b/src/remove.sh
index fcff458..56b6a42 100644
--- a/src/remove.sh
+++ b/src/remove.sh
@@ -49,11 +49,10 @@ remove () {
 
 clean () {
     set -- $(du -sh ${CACHE_DIR})
-    
-    if prompt_question "${LIGHT_RED}Remove ${RED}$1${LIGHT_RED} of cached files?"; then 
+    prompt_question "${LIGHT_RED}Remove ${RED}$1${LIGHT_RED} of cached files?" && {
         rm -rf ${CACHE_DIR}/*
         ${QUIET} || printf "${GREEN}Cleared package cache!\n"
-    else
+    } || {
         ${QUIET} || printf "${LIGHT_BLACK}Action cancled by user\n"
-    fi
+    }
 }
diff --git a/src/util.sh b/src/util.sh
index 501da96..55af05e 100644
--- a/src/util.sh
+++ b/src/util.sh
@@ -37,7 +37,11 @@ wait_for_download () {
         while [ "$downloaded" -lt "$total_download" ]; do
             downloaded=0
             for output in $@; do
-                size=$(stat -t $output | cut -d" " -f2)
+                [ -f $output ] && {
+                    size=$(stat -t $output | cut -d" " -f2)
+                } || {
+                    size=0
+                }
                 downloaded=$((downloaded+size))
             done
 
diff --git a/src/xi.sh b/src/xi.sh
index 9bb6bbf..ae53795 100755
--- a/src/xi.sh
+++ b/src/xi.sh
@@ -64,6 +64,7 @@ Available Commands:
 EOF
 }
 
+
 [ -z "${LIBDIR}" ] && LIBDIR=/usr/lib/xipkg
 
 [ -f ${LIBDIR}/VERSION ] && VERSION=$(cat ${LIBDIR}/VERSION) || VERSION=
@@ -128,6 +129,12 @@ if [ "$#" = "0" ]; then
     . ${LIBDIR}/stats.sh
     show_xipkg_stats
 else 
+    # showing stats doesn't require root, so we can only check when we are here
+    [ ! "$EUID" == 0 ] && {
+        printf "${RED}Please run as root!\n"
+        exit 1
+    }
+    # todo check for permissions when we need them and ask them per request
     case "$1" in
         "sync")
             sync
-- 
cgit v1.2.1