diff --git a/README.md b/README.md index 7862081..e6d7085 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,20 @@ portzap is a utility for staying up to date with the The utility stores a transient copy of the ports tree in `/home/_portzap/ports/`. The transient copy can be created, and updated by an unprivileged user account who is a member of the `_portzap` group. The transient copy can then be installed -into the `/usr/ports` directory by root. +into the `/usr/ports/` directory by root. ## Usage * `portzap clone`
- This command clones HardenedBSD's ports tree into `/home/_portzap/ports`. + This command clones HardenedBSD's ports tree into `/home/_portzap/ports/`. * `portzap pull`
- This command pulls updates into `/home/_portzap/ports`. + This command pulls updates into `/home/_portzap/ports/`. * `portzap install`
This command should be run as root.
- The command installs `/home/_portzap/ports` into `/usr/ports`. + The command installs `/home/_portzap/ports/` into `/usr/ports/`.
+ After the first installation, future installations try to save time by being incremental. ## Sources diff --git a/bin/portzap b/bin/portzap index 9531b89..7a8ce29 100755 --- a/bin/portzap +++ b/bin/portzap @@ -6,6 +6,7 @@ # Configuration ports_url="https://git.hardenedbsd.org/hardenedbsd/ports.git" ports_dir="/usr/ports/" +portzap_rev="$ports_dir/.portzap_last_rev" portzap_dir="/home/_portzap/ports" libexec_dir=$(realpath $(dirname $0)/../libexec/portzap/) @@ -17,6 +18,9 @@ pull_mask=007 ## # Utils +. $libexec_dir/functions/perms.sh +. $libexec_dir/functions/fs.sh +. $libexec_dir/functions/git.sh exit_on_missing_deps() { deps=$1 for dep in $deps; do @@ -28,24 +32,6 @@ exit_on_missing_deps() { done } -has_portzap_access() { - groups=$(id -Gn) - in_group=1 - for g in $groups; do - if [ $g = "_portzap" ]; - then - in_group=0 - fi - done - return $in_group -} - -user_is_not_root() { - user_id=$(id -u) - result=$(test $user_id -ne "0") - return $result -} - ## # Commands help() { @@ -98,16 +84,35 @@ install() { exit 1 fi + echo "Please wait..." cd $portzap_dir - find -s . -maxdepth 1 -type f \ - \( -not -name ".gitignore" \) \ - \( -not -name ".arcconfig" \) \ - -exec $libexec_dir/install-file $ports_dir {} + - find -s . -maxdepth 1 -type d \ - \( -not -name "." \) \ - \( -not -name ".git" \) \ - \( -not -name ".hooks" \) \ - -exec $libexec_dir/install-directory $ports_dir $libexec_dir {} + + if [ -e "$portzap_rev" ]; then + rev=$(cat $portzap_rev) + port_dirs=$(modified_ports $rev) + rm_files=$(git diff --name-only --diff-filter=D $rev..HEAD) + for file in $rm_files; do + rm $ports_dir/$file + done + for dir in $port_dirs; do + if [ -f "$dir" ]; then + $libexec_dir/install-file $ports_dir $dir + else + $libexec_dir/install-directory $ports_dir $libexec_dir $dir + fi + done + else + find -s . -maxdepth 1 -type f \ + \( -not -name ".gitignore" \) \ + \( -not -name ".arcconfig" \) \ + -exec $libexec_dir/install-file $ports_dir {} + + find -s . -maxdepth 1 -type d \ + \( -not -name "." \) \ + \( -not -name ".git" \) \ + \( -not -name ".hooks" \) \ + -exec $libexec_dir/install-directory $ports_dir $libexec_dir {} + + fi + echo $(git rev-parse HEAD) > $portzap_rev + echo "Done." } case $1 in diff --git a/libexec/portzap/functions/fs.sh b/libexec/portzap/functions/fs.sh new file mode 100755 index 0000000..db4d188 --- /dev/null +++ b/libexec/portzap/functions/fs.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +## +# Returns the depth of a path +port_depth() { + p=$1 + result=$(echo $p | tr '/' '\n' | grep . | wc -l) + return $result +} + +## +# Returns the entry point for a port relative to /usr/ports +# (eg: ./ftp/curl/) +port_dirname() { + p=$1 + port_depth "$p" + depth=$? + if [ $depth -gt 2 ]; then + p=$(dirname $p) + port_dirname "$p" + else + echo $p + fi +} diff --git a/libexec/portzap/functions/git.sh b/libexec/portzap/functions/git.sh new file mode 100644 index 0000000..79715f1 --- /dev/null +++ b/libexec/portzap/functions/git.sh @@ -0,0 +1,11 @@ +## +# Returns a list of new, and modified files between two points / commits. +modified_ports() { + rev=$1 + files=$(git diff --name-only --diff-filter=AM $rev..HEAD) + for file in $files; do + dirs="$dirs $(port_dirname $file)" + done + dirs=$(echo $dirs | tr ' ' '\n' | uniq) + echo $dirs +} diff --git a/libexec/portzap/functions/perms.sh b/libexec/portzap/functions/perms.sh new file mode 100644 index 0000000..2ba718e --- /dev/null +++ b/libexec/portzap/functions/perms.sh @@ -0,0 +1,21 @@ +## +# Returns true when current user is in _portzap group +has_portzap_access() { + groups=$(id -Gn) + in_group=1 + for g in $groups; do + if [ $g = "_portzap" ]; + then + in_group=0 + fi + done + return $in_group +} + +## +# Returns true when current user is root +user_is_not_root() { + user_id=$(id -u) + result=$(test $user_id -ne "0") + return $result +}