From ce4bf5ea95e9bae6b59cad84679d46e7c223ca60 Mon Sep 17 00:00:00 2001 From: zawz Date: Mon, 2 Mar 2020 16:39:55 +0100 Subject: [PATCH] Major rework: - dependencies - HOME and ROOT filesystems --- README.md | 44 +++- compile.sh | 24 ++ {src => completion}/zpkg.bash | 0 scripts/database_update.sh | 6 - scripts/gen_install.sh | 43 ---- server_deploy.sh | 27 ++- server_scripts/database_update.sh | 15 ++ server_scripts/gen_install.sh | 73 ++++++ src/config.sh | 36 +++ src/deploy.sh | 55 +++++ src/env.sh | 4 + src/fetch.sh | 23 ++ src/install.sh | 58 +++++ src/main.sh | 162 +++++++++++++ src/options.sh | 26 +++ src/print.sh | 30 +++ src/remove.sh | 38 +++ src/util.sh | 35 +++ src/view.sh | 77 +++++++ src/zpkg | 368 ------------------------------ 20 files changed, 708 insertions(+), 436 deletions(-) create mode 100755 compile.sh rename {src => completion}/zpkg.bash (100%) delete mode 100755 scripts/database_update.sh delete mode 100755 scripts/gen_install.sh create mode 100755 server_scripts/database_update.sh create mode 100755 server_scripts/gen_install.sh create mode 100644 src/config.sh create mode 100644 src/deploy.sh create mode 100644 src/env.sh create mode 100644 src/fetch.sh create mode 100644 src/install.sh create mode 100644 src/main.sh create mode 100644 src/options.sh create mode 100644 src/print.sh create mode 100644 src/remove.sh create mode 100644 src/util.sh create mode 100644 src/view.sh delete mode 100755 src/zpkg diff --git a/README.md b/README.md index 9df556d..afe85f0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Official repo: [http://zawz.net/zpkg](http://zawz.net/zpkg) ## As user Requirements: -- curl - sudo - wget - tar @@ -21,12 +20,25 @@ Optional: ### Installing ```shell -curl -SO http://zawz.net/zpkg/install.sh -sudo sh install.sh +wget http://zawz.net/zpkg/install.sh +sh install.sh ``` +> By default the config is installed to /etc/zpkg If you wish to use another repository, substitute `zawz.net/zpkg` for your desired target + +#### Installing to a custom location + +Add the -c option to the install script to specify a custom config path for the install + +### Uninstalling + +```shell +zpkg remove $(zpkg list) +rm -rd /etc/zpkg +``` + ### Using See `zpkg -h` @@ -51,21 +63,35 @@ You need to be able to SSH to the zpkg user. SSH keys are recommended 3. Make available the package directory to the HTTP server +### Package architecture + +``` +. ++-- DEPS ++-- ROOT +| +-- / ++-- HOME + +-- ~ +``` +- The ROOT directory repsesents the root filesystem +- The HOME directory represents the home directory of the user +- The DEPS file contains dependency packages separated by spaces or newlines. Dependencies are package names from the repository + ### Deploying packages -`zpkg deploy ` -Targets are architectured as the linux filesystem +`zpkg deploy ` +> Target directories are structured as described above +> The package name is the name of the directory ## Functionality -- Install packages -- Remove packages -- Update packages +- Install/Remove/Update packages +- Dependency resolution - Config redirection +- User Home capability ### Non-present functionality -- Dependencies - Versions - Multi-repo diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..15b5765 --- /dev/null +++ b/compile.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# config +# no spaces in srcdir or ordered files +SRCDIR=src +ordered='options.sh config.sh main.sh' + +# process +COMMENTSCRIPT="/^\s*#/d;s/\s*#[^\"']*$//" + +# order list +unset namefind list +for I in $ordered +do + namefind="$namefind ! -name $I" + list="$list $SRCDIR/$I" +done + +findlist=$(find "$SRCDIR" -type f $namefind) + +# create file +echo '#!/bin/sh' > zpkg +sed $COMMENTSCRIPT $findlist $list >> zpkg +chmod +x zpkg diff --git a/src/zpkg.bash b/completion/zpkg.bash similarity index 100% rename from src/zpkg.bash rename to completion/zpkg.bash diff --git a/scripts/database_update.sh b/scripts/database_update.sh deleted file mode 100755 index d99de07..0000000 --- a/scripts/database_update.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -. "$(pwd)/.config" - -cd "$HOME/$PKG_PATH" || exit $? -stat -c "%n %Y" ./*.tar.xz | sed 's|\.tar\.xz||g;s|^\./||g' > pkglist diff --git a/scripts/gen_install.sh b/scripts/gen_install.sh deleted file mode 100755 index c2f2f72..0000000 --- a/scripts/gen_install.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -. "$(pwd)/.config" - -# create install file -echo '#!/bin/sh -' > install.sh -cat .config >> install.sh -echo ' - -# Generate conf file -{ - echo "SSH_ADDRESS=$SSH_USER@$SSH_ADDR" - echo "HTTP_ADDRESS=$HTTP_ADDR/$HTTP_PATH" - echo "PKG_PATH=pkg" -} > zpkg.conf -if [ ! -f "/etc/zpkg/zpkg.conf" ] -then - mkdir -p /etc/zpkg || exit $? - mv zpkg.conf /etc/zpkg || exit $? -fi - -# download zpkg -mkdir -p tmp || exit $? -( - cd tmp || exit $? - if ! wget "$HTTP_ADDR/$HTTP_PATH/zpkg.tar.xz" -q -O "zpkg.tar.xz" - then - echo "Cannot reach $HTTP_ADDR/$HTTP_PATH" > /dev/stderr - exit 1 - fi - tar xf zpkg.tar.xz || exit $? - -# install zpkg package - usr/local/bin/zpkg install zpkg || exit $? -) - -# cleanup -rm -rd tmp || exit $? -zpkg update-database >/dev/null || exit $? - -' >> install.sh -mv install.sh "$HOME/$PKG_PATH" diff --git a/server_deploy.sh b/server_deploy.sh index 864e38a..294d1bf 100755 --- a/server_deploy.sh +++ b/server_deploy.sh @@ -4,25 +4,32 @@ ssh="$SSH_USER@$SSH_ADDR" -# add sources to server -ssh "$ssh" mkdir -p "$PKG_PATH" || exit $? -scp .config scripts/* "$ssh":~/ || exit $? - -# make zpkg package DIR=tmp PKG=zpkg DEST=/usr/local/bin BASHDEST=/etc/bash_completion.d -mkdir -p "$DIR/$PKG$DEST" || exit $? -mkdir -p "$DIR/$PKG$BASHDEST" || exit $? -cp src/zpkg.bash "$ZPKG_PKG_PATH/$PKG$BASHDEST" || exit $? -cp src/zpkg "$ZPKG_PKG_PATH/$PKG$DEST" || exit $? + +# build +./compile.sh || exit $? + +# add sources to server +ssh "$ssh" mkdir -p "$PKG_PATH" || exit $? +scp .config server_scripts/* "$ssh":~/ || exit $? + +fullpath="$DIR/$PKG/ROOT" +# setup package sources +mkdir -p "$fullpath$DEST" || exit $? +mkdir -p "$fullpath$BASHDEST" || exit $? +cp completion/zpkg.bash "$fullpath$BASHDEST" || exit $? +mv zpkg "$fullpath$DEST" || exit $? +# create and send package ( - cd pkg/zpkg || exit $? + cd tmp/zpkg || exit $? tar -cvJf zpkg.tar.xz * || exit $? # send package scp zpkg.tar.xz "$ssh":~/"$PKG_PATH" || exit $? ) +# cleanup rm -rd "$DIR" # update database ssh "$ssh" sh database_update.sh || exit $? diff --git a/server_scripts/database_update.sh b/server_scripts/database_update.sh new file mode 100755 index 0000000..f1274d5 --- /dev/null +++ b/server_scripts/database_update.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +. "$(pwd)/.config" + +cd "$HOME/$PKG_PATH" || exit $? +PKGLIST="$(ls ./*.tar.xz)" +{ +for I in $PKGLIST +do + NAME=$(echo "$I" | sed 's|\.tar\.xz||g;s|^\./||g') + TIME=$(stat -c "%Y" "$I") + DEPS=$(tar -xOf "$I" DEPS 2>/dev/null | tr -s '\n\t ' ' ') + echo "$NAME $TIME $DEPS" +done +} > pkglist diff --git a/server_scripts/gen_install.sh b/server_scripts/gen_install.sh new file mode 100755 index 0000000..d301841 --- /dev/null +++ b/server_scripts/gen_install.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +. "$(pwd)/.config" + +# create install file +# header +echo '#!/bin/sh +' > install.sh +# add config +cat .config >> install.sh +# body +echo ' + +config_path=/etc/zpkg + +while getopts ":hc:" opt; +do + case $opt in + h) + usage + exit 0 + ;; + c) + config_path="$OPTARG" + ;; + \?) + echo "Uknown option: $OPTARG" + usage + exit 1 + ;; + esac +done + +shift $((OPTIND-1)) + +if [ "$(id | cut -d"=" -f2 | cut -d"(" -f1)" -eq 0 ] +then + echo "Cannot run as root" > /dev/stderr + exit 10 +fi + +# Generate conf file +sudo sh -c "{ + echo SSH_ADDRESS=$SSH_USER@$SSH_ADDR + echo HTTP_ADDRESS=$HTTP_ADDR/$HTTP_PATH + echo PKG_PATH=pkg +} > zpkg.conf" + +# install config file +sudo mkdir -p "$config_path" || exit $? +sudo mv zpkg.conf "$config_path" || exit $? + +# download zpkg +mkdir -p tmp || exit $? +( + cd tmp || exit $? + if ! wget "$HTTP_ADDR/$HTTP_PATH/zpkg.tar.xz" -q -O "zpkg.tar.xz" + then + echo "Cannot reach $HTTP_ADDR/$HTTP_PATH" > /dev/stderr + exit 1 + fi + tar xf zpkg.tar.xz || exit $? + +# install zpkg package + ROOT/usr/local/bin/zpkg install zpkg || exit $? +) + +# cleanup +rm -rd tmp || exit $? +zpkg update-database >/dev/null || exit $? + +' >> install.sh +mv install.sh "$HOME/$PKG_PATH" diff --git a/src/config.sh b/src/config.sh new file mode 100644 index 0000000..6112ded --- /dev/null +++ b/src/config.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +virtual_config_path() +{ + old_cfg_path="$config_path" + old_pkg_path="$PKG_PATH" + export config_path="$1" + export PKG_PATH="$config_path/pkg" + mkdir -p "$PKG_PATH" + ln -sf "$old_pkg_path/installed" "$PKG_PATH/installed" +} + +# resolve relative config_path +config_path="$(resolve_path "$config_path" "$(pwd)")" + +config_file="$config_path/zpkg.conf" + +if [ ! -d "$config_path" ] +then + sudo mkdir -p "$config_path" 2>/dev/null +fi +if [ ! -f "$config_file" ] +then + echo "Error: no config file '$config_file'" > /dev/stderr + exit 1 +fi + +. "$config_file" + +# resolve relative pkg_path +PKG_PATH="$(resolve_path "$PKG_PATH" "$config_path")" + +if [ ! -d "$PKG_PATH" ] +then + sudo mkdir -p "$PKG_PATH" 2>/dev/null +fi diff --git a/src/deploy.sh b/src/deploy.sh new file mode 100644 index 0000000..9cafa25 --- /dev/null +++ b/src/deploy.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +package() +{ + unset clean_needed + src="$1" + pkg="$2" + echo "Packaging $(getname "$src"): $(du -sh "$src" | awk '{print $1}')iB" + if [ ! -d "$src/ROOT" ] && [ ! -d "$src/HOME" ] && [ ! -f "$src/DEPS" ] + then + tmpdir="/tmp/zpkg$(random_string 5)" + mkdir -p "$tmpdir" + cp -r "$src" "$tmpdir/ROOT" + src="$tmpdir" + clean_needed=true + fi + ( + cd "$src" + if which pv >/dev/null 2>&1 + then + tar -cf - --owner=0 --group=0 -P * | pv -s "$(du -sb . | awk '{print $1}')" | xz > "$pkg" + else + tar -cvJf - --owner=0 --group=0 * > "$pkg" + fi + ) + mv "$src/$pkg" ./ + if [ -n "$clean_needed" ] + then + rm -rd "$tmpdir" + fi +} + +deploy_package() +{ + echo "Deploying $1: $(du -sh "$1" | awk '{print $1}')iB" + scp "$1" $SSH_ADDRESS:~/'$(grep "PKG_PATH=" .config | cut -d"=" -f2-)' +} + +deploy_folder() +{ + archive="$(getname "$1").tar.xz" + if [ -n "$(echo "$1" | grep '\.tar\.xz$' )" ] + then + deploy_package "$1" || return 1 + else + package "$1" "$archive" || return 1 + deploy_package "$archive" || return 1 + rm "$archive" 2> /dev/null + fi +} + +update_remote_database() +{ + ssh $SSH_ADDRESS "~/database_update.sh" +} diff --git a/src/env.sh b/src/env.sh new file mode 100644 index 0000000..8eee23d --- /dev/null +++ b/src/env.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +config_path=/etc/zpkg +fname="$(basename "$0")" diff --git a/src/fetch.sh b/src/fetch.sh new file mode 100644 index 0000000..d4c2930 --- /dev/null +++ b/src/fetch.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +fetch_package() +{ + wget "$HTTP_ADDRESS/$1.tar.xz" -q --show-progress -O "$1.tar.xz" 2>&1 + return $? +} + +# $1 = prefix +fetch_pkglist() +{ + cd "$PKG_PATH" + $1 mv pkglist pkglist_bak 2>/dev/null + if ! $1 wget "$HTTP_ADDRESS/pkglist" -q --show-progress -O pkglist 2>&1 + then + echo "Couldn't fetch server data" > /dev/stderr + $1 mv pkglist_bak pkglist 2>/dev/null + return 1 + else + $1 rm pkglist_bak 2>/dev/null + return 0 + fi +} diff --git a/src/install.sh b/src/install.sh new file mode 100644 index 0000000..32e4660 --- /dev/null +++ b/src/install.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +unpack() +{ + echo "Unpacking $1" + tar -xf "$1" +} + +add_package_entry() +{ + ( + cd "$PKG_PATH" + if grep -q -w "$1" installed 2>/dev/null + then + sudo sed "s|$1 .*\$|$1 $(date +%s)|g" -i installed + else + sudo sh -c "echo '$1 $(date +%s)' >> installed" + fi + ) +} + +# $1 = source_dir, $2 = dest_dir, $3 = prefix for exec +move_files() +{ + # create dirs + FOLDERS=$(find "$1" -mindepth 1 -type d | sed "s|^$1/||g") + echo "$FOLDERS" | while read -r I + do + $3 mkdir -p "$2/$I" + done + + # move files + FILES=$(find "$1" -mindepth 1 ! -type d | sed "s|^$1/||g") + echo "$FILES" | while read -r I + do + $3 mv "$1/$I" "$2/$I" + done +} + +install_package() +{ + tmpdir="/tmp/zpkg$(random_string 5)" + mkdir -p "$tmpdir" + ( + cd "$tmpdir" + if ! fetch_package "$1" + then + echo "Package '$1' not found" > /dev/stderr + return 1 + fi + unpack "$1.tar.xz" + sudo mv "$1.tar.xz" "$PKG_PATH" + move_files ROOT / sudo 2>/dev/null + move_files HOME "$HOME" 2>/dev/null + add_package_entry "$1" + ) || return $? + rm -rd "$tmpdir" 2>/dev/null +} diff --git a/src/main.sh b/src/main.sh new file mode 100644 index 0000000..4895c26 --- /dev/null +++ b/src/main.sh @@ -0,0 +1,162 @@ +#!/bin/sh + +[ -z "$opt_f" ] && root_check || exit 10 + +if [ -n "$1" ] +then + + if [ "$1" = "list" ] + then + awk '{print $1}' "$PKG_PATH/installed" 2>/dev/null + + elif [ "$1" = "list-all" ] + then + awk '{print $1}' "$PKG_PATH/pkglist" 2>/dev/null + + + elif [ "$1" = "fetch" ] + then + + if [ -z "$2" ] + then + echo "No package specified" > /dev/stderr + else + shift 1 + for I in $* + do + fetch_package "$I" + done + fi + + + elif [ "$1" = "show" ] + then + + if [ -z "$2" ] + then + echo "No package specified" > /dev/stderr + else + shift 1 + for I in $* + do + if is_installed "$I" + then + view_package "$I" + else + echo "No package '$I' installed" > /dev/stderr + fi + done + fi + + elif [ "$1" = "deps" ] + then + + if [ -z "$2" ] + then + echo "No package specified" > /dev/stderr + else + shift 1 + resolve_deps $* + fi + + elif [ "$1" = "install" ] + then + + fetch_pkglist sudo || exit $? + if [ -z "$2" ] + then + echo "No package specified" > /dev/stderr + else + shift 1 + pkglist=$(LOG=true resolve_packages $*) || exit $? + pkglist=$(INCLUDE_PACKAGES=true resolve_deps $* | tr '\n' ' ') + echo "Installing packages: $pkglist" + for I in $pkglist + do + if is_installed "$I" + then + remove_package "$I" + fi + install_package "$I" + done + fi + + elif [ "$1" = "remove" ] + then + + if [ -z "$2" ] + then + echo "No package specified" > /dev/stderr + else + root_check + shift 1 + for I in $* + do + remove_package "$I" + done + fi + + elif [ "$1" = "update-database" ] + then + + fetch_pkglist sudo + + elif [ "$1" = "update" ] + then + + fetch_pkglist sudo || exit 1 + r_pkg=$(removed_packages) + o_pkg=$(outdated_packages) + if [ -n "$r_pkg" ] + then + echo "Removing packages: "$r_pkg + for I in $r_pkg + do + remove_package $I + done + fi + if [ -n "$o_pkg" ] + then + echo "Updating packages: "$o_pkg + for I in $o_pkg + do + remove_package $I + install_package $I + done + fi + + elif [ "$1" = "list-outdated" ] + then + + tmpdir="/tmp/zpkg$(random_string 5)" + virtual_config_path "$tmpdir" || exit $? + fetch_pkglist sudo > /dev/null || exit $? + outdated_packages + sudo rm -rd "$tmpdir" + + elif [ "$1" = "list-removed" ] + then + + tmpdir="/tmp/zpkg$(random_string 5)" + virtual_config_path "$tmpdir" || exit $? + fetch_pkglist sudo > /dev/null || exit $? + removed_packages + sudo rm -rd "$tmpdir" + + elif [ "$1" = "deploy" ] + then + + shift 1 + for I in $* + do + deploy_folder "$I" || exit 1 + done + update_remote_database + + else + usage + fi + +else + usage +fi diff --git a/src/options.sh b/src/options.sh new file mode 100644 index 0000000..a9173ed --- /dev/null +++ b/src/options.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +unset opt_f + +while getopts ":hc:f" opt; +do + case $opt in + h) + usage + exit 0 + ;; + c) + config_path="$OPTARG" + ;; + f) + opt_f="y" + ;; + \?) + echo "Uknown option: $OPTARG" + usage + exit 1 + ;; + esac +done + +shift $((OPTIND-1)) diff --git a/src/print.sh b/src/print.sh new file mode 100644 index 0000000..d01a39c --- /dev/null +++ b/src/print.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +usage() +{ + echo "$fname [options] " + echo ' +Operations: + update Update packages + update-database Update only database + install Install packages + remove Remove packages + fetch Fetch packages into current directory + show Show package files + list List currently installed packages + list-all List all packages in repository + list-outdated List outdated packages + list-removed List outdated packages +Admin operations: + deploy Deploy target to package server + +Options: + -h Display this help + -c Custom config path + -f Force run when root +' +} + +error() { + printf "\033[1;31m%s\033[0m\n" "$1" >&2 +} diff --git a/src/remove.sh b/src/remove.sh new file mode 100644 index 0000000..dd7a874 --- /dev/null +++ b/src/remove.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# files from stdin +# $1 = prefix +delete_files() +{ + while read -r in + do + if [ -n "in" ] + then + $1 rm -d "$in" 2>/dev/null + fi + done +} + +remove_package() +{ + cd "$PKG_PATH" + archive="$(pwd)/$1.tar.xz" + if [ ! -f "$archive" ] || ! grep -q -w "^$1" installed + then + echo "Package '$1' not installed" > /dev/stderr + return 1 + fi + echo "Removing $1" + + ( # delete root files + cd / + tar -tf "$archive" ROOT 2>/dev/null | sed 's|^ROOT/||g' | tac | delete_files sudo + ) + ( # delete home files + cd "$HOME" + tar -tf "$archive" HOME 2>/dev/null | sed 's|^HOME/||g' | tac | delete_files + ) + + rm "$archive" 2>/dev/null + sudo sed -i "/^$1 /d" installed +} diff --git a/src/util.sh b/src/util.sh new file mode 100644 index 0000000..05cb939 --- /dev/null +++ b/src/util.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# random alphanumeric string of $1 chars +random_string() +{ + tr -cd '[:alnum:]' < /dev/urandom | head -c$1 +} + +# $1 = input , $2 = prefix absolute path +resolve_path() +{ + if [ "$(echo $1 | cut -c1)" != "/" ] + then + echo "$2/$1" + else + echo "$1" + fi +} + +# get name of the folder +getname() +{ + basename "$(readlink -f "$1")" +} + +# return error if user is root +root_check() +{ + if [ "$(id | cut -d'=' -f2 | cut -d'(' -f1)" -eq 0 ] + then + echo "Cannot run as root" > /dev/stderr + return $1 + fi + return 0 +} diff --git a/src/view.sh b/src/view.sh new file mode 100644 index 0000000..7a06616 --- /dev/null +++ b/src/view.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +deps() +{ + cd "$PKG_PATH" + grep -w "^$1" pkglist | cut -d' ' -f3- +} + +resolve_packages() +{ + RET=0 + cd "$PKG_PATH" + for I in $* + do + if ! grep -wq "^$I" pkglist + then + [ "$LOG" = "true" ] && echo "Package '$I' not found" > /dev/stderr + RET=1 + else + echo "$I" + fi + done + return $RET +} + +# env: INCLUDE_PACKAGES +resolve_deps() +{ + ALLDEPS="" + for I in $* + do + ALLDEPS="$ALLDEPS $(deps $I)" + done + [ "$INCLUDE_PACKAGES" = "true" ] && ALLDEPS="$ALLDEPS $*" + echo "$ALLDEPS" | tr -s ' \n' '\n' | sort | uniq | sed '/^$/d' +} + +is_installed() +{ + cd "$PKG_PATH" + grep -qw "^$1" installed + return $? +} + +view_package() +{ + cd "$PKG_PATH" + tar -tf "$1.tar.xz" | sed "s|^ROOT/|/|g ; /\/$/d ; s|^HOME/|$HOME/|g ; /^DEPS/d" +} + +removed_packages() +{ + cd "$PKG_PATH" + cat installed 2>/dev/null | while read -r in + do + name=$(echo "$in" | awk '{print $1}') + rem=$(grep -w "^$name" pkglist | awk '{print $2}') + if [ -z "$rem" ] ; then + echo $name + fi + done +} + +outdated_packages() +{ + cd "$PKG_PATH" + cat installed 2>/dev/null | while read -r in + do + name=$(echo "$in" | awk '{print $1}') + loc=$(echo "$in" | awk '{print $2}') + rem=$(grep -w "^$name" pkglist | awk '{print $2}') + if [ -n "$rem" ] && [ "$loc" -lt "$rem" ] + then + echo $name + fi + done +} diff --git a/src/zpkg b/src/zpkg deleted file mode 100755 index 5aad327..0000000 --- a/src/zpkg +++ /dev/null @@ -1,368 +0,0 @@ -#!/bin/sh - -config_path=/etc/zpkg - -getname () -{ - basename "$(readlink -f "$1")" -} - -usage () -{ - echo "zpkg [options] " - echo "" - echo "Operations:" - echo " update Update packages" - echo " update-database Update only database" - echo " install Install packages" - echo " remove Remove packages" - echo " fetch Fetch packages into current directory" - echo " show Show package files" - echo " list List currently installed packages" - echo " list-all List all packages in repository" - echo " list-outdated List outdated packages" - echo " list-removed List outdated packages" - echo "Admin operations:" - echo " deploy Deploy target to package server" - echo "" - echo "Options:" - echo " -h Display this help" - echo " -c Custom config path" -} - -error () { - printf "\033[1;31m%s\033[0m\n" "$1" >&2 -} -root_check () { - if [ "$(id | cut -d'=' -f2 | cut -d'(' -f1)" -ne 0 ] - then - echo "Root privileges required" > /dev/stderr - exit 10 - fi -} - -package () -{ - echo "Packaging $(getname "$1"): $(du -sh "$1" | awk '{print $1}')iB" - ( - cd "$1" - if [ -n "$(command -v pv)" ] - then - tar -cf - --owner=0 --group=0 -P * | pv -s "$(du -sb . | awk '{print $1}')" | xz > "$2" - else - tar -cvJf "$2" --owner=0 --group=0 * - fi - ) - mv "$1/$2" ./ -} - -update_remote_database () -{ - ssh $SSH_ADDRESS "~/database_update.sh" -} - -deploy_folder () -{ - archive="$(getname "$1").tar.xz" - if [ -n "$(echo "$1" | grep '\.tar\.xz$' )" ] - then - deploy_package "$1" || return 1 - else - package "$1" "$archive" || return 1 - deploy_package "$archive" || return 1 - rm "$archive" 2> /dev/null - fi -} - -deploy_package () -{ - echo "Deploying $1: $(du -sh "$1" | awk '{print $1}')iB" - scp "$1" $SSH_ADDRESS:~/'$(grep "PKG_PATH=" .config | cut -d"=" -f2-)' -} - -fetch_package () -{ - if ! wget "$HTTP_ADDRESS/$1.tar.xz" -q --show-progress -O "$1.tar.xz" 2>&1 - then - echo "Package '$1' not found" > /dev/stderr - return 1 - else - return 0 - fi -} -add_package_entry () -{ - cd "$config_path" - if grep -q -w "$1" installed 2>/dev/null - then - sed "s|$1 .*|$1 $(date +%s)|g" -i installed - else - echo "$1 $(date +%s)" >> installed - fi -} - -fetch_pkglist () -{ - cd "$config_path" - mv pkglist pkglist_bak 2>/dev/null - if ! wget "$HTTP_ADDRESS/pkglist" -q --show-progress -O pkglist 2>&1 - then - echo "Couldn't fetch server data" > /dev/stderr - mv pkglist_bak pkglist 2>/dev/null - return 1 - else - rm pkglist_bak 2>/dev/null - return 0 - fi -} - -view_package () -{ - cd "$PKG_PATH" - tar tf "$1.tar.xz" -} - -unpack () -{ - echo "Unpacking $1" - tar xf "$1" -} - -install_package () -{ - cd / - if fetch_package "$1" - then - unpack "$1.tar.xz" - mv "$1.tar.xz" "$PKG_PATH" - add_package_entry "$1" - fi -} - -removed_packages () -{ - cd "$config_path" - cat installed | while read -r in - do - name=$(echo "$in" | awk '{print $1}') - rem=$(grep -w "$name" pkglist | awk '{print $2}') - if [ -z "$rem" ] ; then - echo $name - fi - done -} - -outdated_packages () -{ - cd "$config_path" - cat installed | while read -r in - do - name=$(echo "$in" | awk '{print $1}') - loc=$(echo "$in" | awk '{print $2}') - rem=$(grep -w "$name" pkglist | awk '{print $2}') - if [ -n "$rem" ] && [ "$loc" -lt "$rem" ] - then - echo $name - fi - done -} - -remove_package () -{ - cd "$PKG_PATH" - if [ ! -f "$1.tar.xz" ] || ! grep -q -w "$1" "$config_path/installed" - then - echo "Package '$1' not installed" > /dev/stderr - return 1 - fi - echo "Removing $1" - tar tf "$1.tar.xz" | tac | while read -r in - do - rm -d "/$in" 2>/dev/null - done - rm "$1.tar.xz" 2>/dev/null - sed -i "/$1 /d" "$config_path/installed" -} - -while getopts ":hc:" opt; -do - case $opt in - h) - usage - exit 0 - ;; - c) - config_path="$OPTARG" - ;; - \?) - echo "Uknown option: $OPTARG" - usage - exit 1 - ;; - esac -done - -config_file="$config_path/zpkg.conf" - -if [ ! -d "$config_path" ] -then - mkdir -p "$config_path" 2>/dev/null -fi -if [ ! -f "$config_file" ] -then - echo "Error: no config file '$config_file'" > /dev/stderr - exit 1 -fi - -. "$config_file" - -if [ "$(echo $PKG_PATH | cut -c1)" != "/" ] -then - PKG_PATH="$config_path/$PKG_PATH" -fi - -if [ ! -d "$PKG_PATH" ] -then - mkdir -p "$PKG_PATH" 2>/dev/null -fi - -if [ -n "$1" ] -then - - if [ "$1" = "list" ] - then - awk '{print $1}' "$config_path/installed" 2>/dev/null - - elif [ "$1" = "list-all" ] - then - awk '{print $1}' "$config_path/pkglist" 2>/dev/null - - - elif [ "$1" = "fetch" ] - then - - shift $((OPTIND)) - if [ -z "$2" ] - then - echo "No package specified" > /dev/stderr - else - for I in $* - do - fetch_package "$I" - done - fi - - - elif [ "$1" = "show" ] - then - - if [ -z "$2" ] - then - echo "No package specified" > /dev/stderr - else - shift $((OPTIND)) - for I in $* - do - view_package "$I" - done - fi - - elif [ "$1" = "install" ] - then - - if [ -z "$2" ] - then - echo "No package specified" > /dev/stderr - else - root_check - shift $((OPTIND)) - for I in $* - do - install_package "$I" - done - fi - - elif [ "$1" = "remove" ] - then - - if [ -z "$2" ] - then - echo "No package specified" > /dev/stderr - else - root_check - shift $((OPTIND)) - for I in $* - do - remove_package "$I" - done - fi - - elif [ "$1" = "update-database" ] - then - - root_check - fetch_pkglist - - elif [ "$1" = "update" ] - then - - root_check - fetch_pkglist || exit 1 - r_pkg=$(removed_packages) - o_pkg=$(outdated_packages) - if [ -n "$r_pkg" ] - then - echo "Removing packages: "$r_pkg - for I in $r_pkg - do - remove_package $I - done - fi - if [ -n "$o_pkg" ] - then - echo "Updating packages: "$o_pkg - for I in $o_pkg - do - remove_package $I - install_package $I - done - fi - - elif [ "$1" = "list-outdated" ] - then - - old_cfg_path=$config_path - config_path=/tmp/zpkg - mkdir -p $config_path - ln -sf $old_cfg_path/installed $config_path/installed - fetch_pkglist > /dev/null || exit 1 - outdated_packages - - elif [ "$1" = "list-removed" ] - then - - old_cfg_path=$config_path - config_path=/tmp/zpkg - mkdir -p $config_path - ln -sf $old_cfg_path/installed $config_path/installed - fetch_pkglist > /dev/null || exit 1 - removed_packages - - - elif [ "$1" = "deploy" ] - then - - shift $((OPTIND)) - for I in $* - do - deploy_folder "$I" || exit 1 - done - update_remote_database - - else - usage - fi - -else - usage -fi