diff options
Diffstat (limited to 'lib/cpt.in')
-rw-r--r-- | lib/cpt.in | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/lib/cpt.in b/lib/cpt.in new file mode 100644 index 0000000..a80a961 --- /dev/null +++ b/lib/cpt.in @@ -0,0 +1,178 @@ +#!/bin/sh -ef +# shellcheck source=/dev/null + +log() { + # Print a message prettily. + # + # All messages are printed to stderr to allow the user to hide build + # output which is the only thing printed to stdout. + # + # '${3:-->}': If the 3rd argument is missing, set prefix to '->'. + # '${2:+colorb}': If the 2nd argument exists, set text style of '$1'. + printf '%b%s %b%b%s%b %s\n' \ + "$colory" "${3:-->}" "$colre" "${2:+$colorb}" "$1" "$colre" "$2" >&2 +} + +version() { + log "Carbs Packaging Tools" @VERSION@ + exit 0 +} + +trap_set() { + # Function to set the trap value. + case ${1:-cleanup} in + cleanup) trap pkg_clean EXIT INT ;; + block) trap '' INT ;; + unset) trap - EXIT INT ;; + esac +} + +_readlinkf() { + # Public domain POSIX sh readlink function by Koichi Nakashima + [ "${1:-}" ] || return 1 + max_symlinks=40 + CDPATH='' # to avoid changing to an unexpected directory + + target=$1 + [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes + [ -d "${target:-/}" ] && target="$target/" + + cd -P . 2>/dev/null || return 1 + while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do + if [ ! "$target" = "${target%/*}" ]; then + case $target in + /*) cd -P "${target%/*}/" 2>/dev/null || break ;; + *) cd -P "./${target%/*}" 2>/dev/null || break ;; + esac + target=${target##*/} + fi + + if [ ! -L "$target" ]; then + target="${PWD%/}${target:+/}${target}" + printf '%s\n' "${target:-/}" + return 0 + fi + + # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n", + # <file mode>, <number of links>, <owner name>, <group name>, + # <size>, <date and time>, <pathname of link>, <contents of link> + # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html + link=$(ls -dl -- "$target" 2>/dev/null) || break + target=${link#*" $target -> "} + done + return 1 +} + +# CPT Library does "lazy loading" of its functions. Meaning that functions are +# defined, but the libraries containing the functions aren't loaded until one of +# those functions are called. This should theoretically decrease the time it +# takes to execute some script that uses only minimal amount of library +# functions. When a function listed below is called, its definition is replaced +# by the one in the loaded library, and executed with the same arguments. +# @AUTOLOADS@ + +# main() +{ + set -ef + + # Set the library directory if unset, assuming that it shares the same + # prefix with the tool. + [ "$CPT_LIBDIR" ] || CPT_LIBDIR=$(_readlinkf "${0%/*}/../lib/cpt/") + + # If a parser definition exists, let's run it ourselves. This makes sure we + # get the variables as soon as possible. + command -v parser_definition >/dev/null && { + eval "$(getoptions parser_definition parse "$0")" + parse "$@" + eval set -- "$REST" + } + + # Create the cache directories for CPT and set the variables which point + # to them. This is seperate from temporary directories created in + # create_cache(). That's because we need these variables set on most + # occasions. + mkdir -p "${cac_dir:=${CPT_CACHE:=${XDG_CACHE_HOME:-$HOME/.cache}/cpt}}" \ + "${src_dir:=$cac_dir/sources}" \ + "${log_dir:=$cac_dir/logs}" \ + "${bin_dir:=$cac_dir/bin}" + + # Set the location to the repository and package database. + pkg_db=var/db/cpt/installed + + # The PID of the current shell process is used to isolate directories + # to each specific CPT instance. This allows multiple package manager + # instances to be run at once. Store the value in another variable so + # that it doesn't change beneath us. + pid=${CPT_PID:-$$} + + # Force the C locale to speed up things like 'grep' which disable unicode + # etc when this is set. We don't need unicode and a speed up is always + # welcome. + export LC_ALL=C LANG=C + + # Catch errors and ensure that build files and directories are cleaned + # up before we die. This occurs on 'Ctrl+C' as well as success and error. + trap_set cleanup + + # Prefer GNU grep if installed as it is much much faster than busybox's + # implementation. Very much worth it if you value performance over + # POSIX correctness (grep quoted to avoid shellcheck false-positive). + grep=$(command -v ggrep) || grep='grep' + + # Prefer libarchive tar or GNU tar if installed as they are much + # much faster than busybox's implementation. Very much worth it if + # you value performance. + tar=$(command -v bsdtar || command -v gtar) || tar=tar + + # Figure out which 'sudo' command to use based on the user's choice or + # what is available on the system. + su=${CPT_SU:-$(command -v sls || + command -v sudo || + command -v doas)} || su=su + + # Store the date and time of script invocation to be used as the name + # of the log files the package manager creates during builds. + time=$(date '+%Y-%m-%d-%H:%M') + + # Use readelf for fixing dependencies if it is available, fallback to + # ldd. readelf shows only the actual dependencies and doesn't include + # the libraries required by the dependencies. + elf_prog=${CPT_ELF:="$( + command -v readelf || + command -v llvm-readelf || + command -v eu-readelf)"} || elf_prog=ldd + + # Make note of the user's current ID to do root checks later on. + # This is used enough to warrant a place here. + uid=$(id -u) + + # Save IFS, so we can restore it back to what it was before. + old_ifs=$IFS + + # Make sure that the CPT_ROOT doesn't end with a '/'. This might + # break some operations. + CPT_ROOT=${CPT_ROOT%"${CPT_ROOT##*[!/]}"} + + # Define an optional sys_arch variable in order to provide + # information to build files with architectural information. + sys_arch=$(uname -m 2>/dev/null) ||: + + # Define this variable but don't create its directory structure from + # the get go. It will be created as needed by package installation. + sys_db=$CPT_ROOT/$pkg_db + + # This allows for automatic setup of a CPT chroot and will + # do nothing on a normal system. + mkdir -p "$CPT_ROOT/" 2>/dev/null ||: + + # Set a value for CPT_COMPRESS if it isn't set. + : "${CPT_COMPRESS:=gz}" + + # Unless being piped or the user specifically doesn't want colors, set + # colors. This can of course be overriden if the user specifically want + # colors during piping. + if { [ "$CPT_COLOR" != 0 ] && [ -t 1 ] ;} || [ "$CPT_COLOR" = 1 ]; then + colory="\033[1;33m" colorb="\033[1;36m" colre="\033[m" + fi + +} |