autils

Unnamed repository; edit this file 'description' to name the repository.
git clone https://codeberg.org/emmett1/autils
Log | Files | Refs | README | LICENSE

apkg-bin (4938B)


      1 #!/bin/sh
      2 # apkg-bin - a simple binary package manager helper script
      3 
      4 REMOTE="${REMOTE:-https://emmett1.my/files/alice/packages}"
      5 PKGDIR="${PKGDIR:-/var/cache/apkg-bin}"
      6 REPODB="${REPODB:-REPO}"
      7 DBFILE="$PKGDIR/$REPODB"
      8 
      9 usage() {
     10 	echo "Usage: $0 [options]"
     11 	echo "  g <path>     Generate database from package dir"
     12 	echo "  S            Sync database from remote server"
     13 	echo "  l            List packages"
     14 	echo "  s <pattern>  Search packages"
     15 	echo "  a <pkg>      Show package info"
     16 	echo "  d <pkg...>   Download package(s)"
     17 	echo "  i <pkg...>   Install package(s)"
     18 	echo "  u <pkg...>   Upgrade/reinstall package(s)"
     19 	echo "  c            Clean mismatched/unknown packages"
     20 	exit 0
     21 }
     22 
     23 msg() {
     24 	m=${pkg%#*}
     25 	echo "[${m:-...}] $*"
     26 }
     27 
     28 pkg_existence() {
     29 	need_db
     30 	[ "$(cut -d '#' -f1 "$DBFILE" | grep -x "$1" | uniq)" ] || return 1
     31 	return 0
     32 }
     33 
     34 get_pkg() {
     35 	for p in $@; do
     36 		pkg_existence $p && pkg="$pkg $p" || msg "No package found matching: $p"
     37 	done
     38 }
     39 
     40 get_entry() {
     41 	entry=$(grep ^$1# "$DBFILE" | sort -V -t'#' -k2 | tail -n1)
     42 }
     43 
     44 need_db() {
     45 	[ -f "$DBFILE" ] || { msg "Run '$0 S' first to sync database."; exit 1; }
     46 }
     47 
     48 need_root() {
     49 	[ $(id -u) = 0 ] || { msg "This option need root access."; exit 1; }
     50 }
     51 
     52 fetch_pkg() {
     53 	get_entry $1
     54 	expected_sha=$(echo "$entry" | cut -d'|' -f4)
     55 	pkg=$(echo "$entry" | cut -d'|' -f1)
     56 
     57 	mkdir -p "$PKGDIR"
     58 	if [ -f "$PKGDIR/$pkg" ]; then
     59 		msg "$PKGDIR/$pkg found."
     60 	else
     61 		url="$REMOTE/$(echo "$pkg" | sed 's/#/%23/g')"
     62 		msg "Downloading $url..."
     63 		curl -fsSLo "$PKGDIR/$pkg" "$url" || { msg "Download failed: $pkg" >&2; return 1; }
     64 	fi
     65 
     66 	actual_sha=$(sha256sum "$PKGDIR/$pkg" | awk '{print $1}')
     67 	if [ "$expected_sha" = "$actual_sha" ]; then
     68 		msg "Verification PASSED: $pkg"
     69 	else
     70 		msg "Verification FAILED: $pkg" >&2
     71 		rm -f "$pkg"
     72 		return 1
     73 	fi
     74 	
     75 	if [ "$mode" ]; then
     76 		spm $mode "$PKGDIR/$pkg"
     77 	fi
     78 }
     79 
     80 generate_db() {
     81 	[ -d "$1" ] || { msg "Invalid path: $1"; exit 1; }
     82 	> "$1/$REPODB"
     83 	msg "Generating database, please wait..."
     84 	for f in "$1"/*.spm; do
     85 		[ -f "$f" ] || continue
     86 		size=$(stat -c%s "$f")
     87 		mtime=$(stat -c%Y "$f")
     88 		sha=$(sha256sum "$f" | awk '{print $1}')
     89 		name=$(basename "$f")
     90 		echo "$name|$size|$mtime|$sha" >> "$1/$REPODB"
     91 	done
     92 	msg "Database generated at $1/$REPODB"
     93 }
     94 
     95 sync_db() {
     96 	need_root
     97 	mkdir -p "${DBFILE%/*}"
     98 	msg "Downloading database $REMOTE/$REPODB"
     99 	curl -fsSo "$DBFILE" "$REMOTE/$REPODB" || { msg "Failed to sync $REPODB"; exit 1; }
    100 	msg "Database synced to $DBFILE"
    101 }
    102 
    103 list_pkg() {
    104 	need_db
    105 	cut -d'|' -f1 "$DBFILE" | sed 's/#/ /g;s/.spm//g'
    106 }
    107 
    108 search_pkg() {
    109 	need_db
    110 	cut -d '|' -f1 "$DBFILE" | grep -i "$1" | sed 's/#/ /g;s/.spm//g'
    111 	exit 0
    112 }
    113 
    114 info_pkg() {
    115 	need_db
    116 	get_pkg $@	
    117 	for p in $pkg; do
    118 		get_entry $p
    119 		name=$p
    120 		verrel=$(echo "$entry" | cut -d '#' -f2 | sed 's/\.spm.*//')
    121 		size=$(echo "$entry"   | cut -d '|' -f2)
    122 		mtime=$(echo "$entry"  | cut -d '|' -f3)
    123 		sha=$(echo "$entry"	| cut -d '|' -f4)
    124 
    125 		# convert size
    126 		if [ "$size" -lt 1024 ]; then
    127 			hsize="${size} B"
    128 		elif [ "$size" -lt 1048576 ]; then
    129 			hsize="$(awk "BEGIN{printf \"%.1f\", $size/1024}") KB"
    130 		else
    131 			hsize="$(awk "BEGIN{printf \"%.1f\", $size/1048576}") MB"
    132 		fi
    133 
    134 		# convert date
    135 		hdate=$(date -d @"$mtime" '+%Y-%m-%d %H:%M:%S')
    136 
    137 		echo "Package: $name"
    138 		echo "Version: $verrel"
    139 		echo "Size:	$hsize"
    140 		echo "Date:	$hdate"
    141 		echo "SHA256:  $sha"
    142 	done
    143 }
    144 
    145 download_pkg() {
    146 	need_db
    147 	get_pkg $@
    148 	for p in $pkg; do
    149 		fetch_pkg $p
    150 	done
    151 }
    152 
    153 install_pkg() {
    154 	need_root
    155 	need_db
    156 	get_pkg $@
    157 	for p in $pkg; do
    158 		[ "$(spm -a | grep -x $p)" ] && {
    159 			msg "Package '$p' is installed, skipped."
    160 		} || {
    161 			pkg2="$pkg2 $p"
    162 		}
    163 	done
    164 	for p in $pkg2; do
    165 		mode='-i' fetch_pkg $p
    166 	done
    167 }
    168 
    169 upgrade_pkg() {
    170 	need_root
    171 	need_db
    172 	get_pkg $@
    173 	for p in $pkg; do
    174 		[ "$(spm -a | grep -x $p)" ] || {
    175 			msg "Package '$p' not installed, skipped."
    176 		} && {
    177 			pkg2="$pkg2 $p"
    178 		}
    179 	done
    180 	for p in $pkg2; do
    181 		mode='-u' fetch_pkg $p
    182 	done
    183 }
    184 
    185 clean_pkg() {
    186 	need_db
    187 	need_root
    188 	msg "Checking local packages in $PKGDIR..."
    189 	known_pkgs=$(cut -d '|' -f1 "$DBFILE")
    190 	for f in "$PKGDIR"/*.spm; do
    191 		[ -f "$f" ] || continue
    192 		fname=${f##*/}
    193 		if echo "$known_pkgs" | grep -qx "$fname"; then
    194 			entry=$(grep "^$fname|" "$DBFILE")
    195 			expected_size=$(echo "$entry" | cut -d'|' -f2)
    196 			expected_sha=$(echo "$entry" | cut -d'|' -f4)
    197 			actual_size=$(stat -c%s "$f")
    198 			actual_sha=$(sha256sum "$f" | awk '{print $1}')
    199 			if [ "$expected_size" != "$actual_size" ] || [ "$expected_sha" != "$actual_sha" ]; then
    200 				msg "Mismatch: $fname (removed)"
    201 			fi
    202 		else
    203 			msg "Unknown package: $fname (removed)"
    204 			rm -f "$f"
    205 		fi
    206 	done
    207 	msg "Cleanup done."
    208 }
    209 
    210 main() {
    211 	if [ ! "$1" ]; then
    212 		usage
    213 	else
    214 		case $1 in
    215 			g) generate_db $2 ;;
    216 			S) sync_db ;;
    217 			l) list_pkg ;;
    218 			s) search_pkg $2 ;;
    219 			a) shift; info_pkg $@ ;;
    220 			d) shift; download_pkg $@ ;;
    221 			i) shift; install_pkg $@ ;;
    222 			u) shift; upgrade_pkg $@ ;;
    223 			c) clean_pkg ;;
    224 			*) usage ;;
    225 		esac
    226 		exit 0
    227 	fi
    228 }
    229 
    230 main $@
    231 
    232 exit 0