aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordylan.araps@gmail.com <dylan.araps@gmail.com>2019-06-29 20:33:41 +0000
committerdylan.araps@gmail.com <dylan.araps@gmail.com>2019-06-29 20:33:41 +0000
commit387ea855c6c30d128ac8fb1690a6db3dec01c7ca (patch)
tree9ed68813d3abcfc5c6e90f075214c756b81ddefa
parent7cd58b5568d207f7cb3f41d9063652f668887dab (diff)
downloadcpt-387ea855c6c30d128ac8fb1690a6db3dec01c7ca.tar.gz
kiss-new: Done?
FossilOrigin-Name: 697430f3c6cbca33782a8b1e50ef0ae935785ba6f5d5ab6160a6b1e7e3f9a2f5
-rwxr-xr-xkiss-new124
1 files changed, 115 insertions, 9 deletions
diff --git a/kiss-new b/kiss-new
index 9b394a8..2dd5f19 100755
--- a/kiss-new
+++ b/kiss-new
@@ -87,11 +87,18 @@ pkg_list() {
# diectories, this just involves a simple for loop and
# file read.
+ # Change directories to the database. This allows us to
+ # avoid having to basename each path. If this fails,
+ # set '$1' to mimic a failed glob which indicates that
+ # nothing is installed.
+ cd "$KISS_ROOT/var/db/kiss/" 2>/dev/null ||
+ set -- "$KISS_ROOT/var/db/kiss/"\*
+
# Optional arguments can be passed to check for specific
# packages. If no arguments are passed, list all. As we
# loop over '$@', if there aren't any arguments we can
# just set the directory contents to the argument list.
- [ "$1" ] || set -- "$KISS_ROOT/var/db/kiss/"*
+ [ "$1" ] || set -- *
# If the 'glob' above failed, exit early as there are no
# packages installed.
@@ -111,7 +118,7 @@ pkg_list() {
}
read -r version release < "$pkg/version" &&
- printf '%s\n' "${pkg%/*} $version-$release"
+ printf '%s\n' "$pkg $version-$release"
done
}
@@ -310,7 +317,7 @@ pkg_manifest() (
# Find all files and directories in the package. Directories are printed
# with a trailing forward slash '/'. The list is then reversed with
# directories appearing *after* their contents.
- find . -type d -exec printf '%s/\n' {} + -or -print |
+ find . -mindepth 1 -type d -exec printf '%s/\n' {} + -or -print |
sort -r | sed -e ss.ss > "$pkg_dir/$1/var/db/kiss/$1/manifest"
log "[$1]: Generated manifest."
@@ -481,6 +488,7 @@ pkg_checksums() {
pkg_conflicts() {
# Check to see if a package conflicts with another.
# This function takes a path to a KISS tarball as an argument.
+ log "Checking for package conflicts."
# Extract manifest from the tarball and only extract files entries.
tar xf "$1" -O "./var/db/kiss/$pkg_name/manifest" |
@@ -501,6 +509,38 @@ pkg_conflicts() {
rm -f "$cac_dir/manifest-$pid"
}
+pkg_remove() {
+ # Remove a package and all of its files. The '/etc' directory
+ # is handled differently and configuration files are *not*
+ # overwritten.
+
+ # Create a backup of 'rm' and 'rmdir' so they aren't removed
+ # during package removal. This ensures that an upgrade to 'busybox'
+ # or your coreutils of choice doesn't break the package manager.
+ cp "$(command -v rm)" "$cac_dir"
+ cp "$(command -v rmdir)" "$cac_dir"
+
+ for pkg; do
+ # The package is not installed, don't do anything.
+ pkg_list "$pkg" >/dev/null || continue
+
+ while read -r file; do
+ # The file is in '/etc' skip it. This prevents the package
+ # manager from removing user edited config files.
+ [ "${file##/etc/*}" ] || continue
+
+ if [ -d "$KISS_ROOT/$file" ]; then
+ "$cac_dir/rmdir" "$KISS_ROOT/$file" 2>/dev/null || continue
+ else
+ "$cac_dir/rm" -f -- "$KISS_ROOT/$file" ||
+ log "Failed to remove '$file'."
+ fi
+ done < "$KISS_ROOT/var/db/kiss/$pkg/manifest"
+
+ log "Successfully removed '$pkg'."
+ done
+}
+
pkg_install() {
# Install a built package tarball.
@@ -508,7 +548,7 @@ pkg_install() {
# Install can also take the full path to a tarball.
# We don't need to check the repository if this is the case.
if [ -f "$pkg" ]; then
- tar_name=$pkg
+ tar_file=$pkg
else
# Find the package's repository files. This needs to keep
@@ -530,13 +570,19 @@ pkg_install() {
fi
# Figure out which package the tarball installs by checking for
- # a database entry inside the tarball.
- pkg_name=$(tar tf "$tar_file" | grep -x "\./var/db/kiss/.*/version")
- pkg_name=${pkg_name%/*}
- pkg_name=${pkg_name##*/}
+ # a database entry inside the tarball. If no database entry exists,
+ # exit here as the tarball is *most likely* not a KISS package.
+ {
+ pkg_name=$(tar tf "$tar_file" | grep -x "\./var/db/kiss/.*/version")
+ pkg_name=${pkg_name%/*}
+ pkg_name=${pkg_name##*/}
+ } || die "'$tar_file' is not a valid KISS package."
pkg_conflicts "$tar_file"
+ # Extract the tarball early to catch any errors before installation
+ # begins. The package manager uninstalls the previous package during
+ # an upgrade so any errors need to be caught ASAP.
tar pxf "$tar_file" -C "$tar_dir/" ||
die "[$pkg]: Failed to extract tarball."
@@ -548,7 +594,57 @@ pkg_install() {
cp "$(command -v find)" "$cac_dir"
log "Removing previous version of package if it exists."
- pkg_remove
+ pkg_remove "$pkg_name"
+
+ # Installation works by unpacking the tarball to a specified location,
+ # manually running 'mkdir' to create each directory and finally, using
+ # 'mv' to move each file.
+ cd "$tar_dir"
+
+ # Create all of the package's directories.
+ # Optimization: Only find the deepest directories.
+ "$cac_dir/find" . -type d -links -3 -prune | while read -r dir; do
+ "$cac_dir/mkdir" -p "$KISS_ROOT/${dir#./}"
+ done
+
+ # Move all package files to '$KISS_ROOT'.
+ "$cac_dir/find" ./ -mindepth 1 -not -type d | while read -r file; do
+ rpath=${file#.}
+
+ # Don't overwrite existing '/etc' files.
+ [ -z "${rpath##/etc/*}" ] &&
+ [ -f "$KISS_ROOT/${rpath%/*}/${file##*/}" ] &&
+ return
+
+ "$cac_dir/mv" "$file" "$KISS_ROOT/${rpath%/*}"
+ done
+
+ # Run the post install script and suppress errors. If it exists,
+ # it will run, else nothing will happen.
+ "$KISS_ROOT/var/db/kiss/$pkg_name/post-install" 2>/dev/null ||:
+
+ log "Successfully installed '$pkg_name'."
+ done
+}
+
+pkg_updates() {
+ # Check all installed packages for updates. So long as the installed
+ # version and the version in the repositories differ, it's considered
+ # an update.
+ for pkg in "$KISS_ROOT/var/db/kiss/"*; do
+ # Find the package's repository files. This needs to keep
+ # happening as we can't store this data in any kind of data
+ # structure.
+ repo_dir=$(pkg_search "${pkg##*/}")
+
+ # Read version and release information from the installed packages
+ # and repository.
+ read -r db_ver db_rel < "$pkg/version"
+ read -r re_ver re_rel < "$repo_dir/version"
+
+ # Compare installed packages to repository packages.
+ [ "$db_ver-$db_rel" != "$re_ver-$re_rel" ] &&
+ printf '%s\n' "${pkg##*/} $re_ver-$re_rel"
done
}
@@ -588,6 +684,10 @@ pkg_clean() {
# Remove temporary directories.
rm -rf -- "$mak_dir" "$pkg_dir" "$tar_dir"
+
+ # Remove cached commands.
+ rm -f -- "$cac_dir/find" "$cac_dir/mv" "$cac_dir/mkdir" \
+ "$cac_dir/rm" "$cac_dir/rmdir"
}
root_check() {
@@ -640,6 +740,7 @@ args() {
shift
[ "$1" ] || die "'kiss remove' requires an argument."
root_check
+ pkg_remove "$@"
;;
# List installed packages.
@@ -648,6 +749,11 @@ args() {
pkg_list "$@"
;;
+ # Upgrade packages.
+ u*)
+ pkg_updates
+ ;;
+
# Print version and exit.
v*)
log "$kiss 0.1.10"