diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/cpt | 63 | ||||
-rwxr-xr-x | src/cpt-build | 7 | ||||
-rw-r--r-- | src/cpt-lib.in | 157 |
3 files changed, 170 insertions, 57 deletions
@@ -1,5 +1,52 @@ #!/bin/sh -ef +bi() { + # Build and install function for cpt. + # + # shellcheck disable=2317 + parser_definition() { + setup REST help:usage -- "usage: ${0##*/} bi [-dfSty] [--root ROOT] [pkg...]" + msg -- '' 'Options:' + flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)" + flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation" + flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \ + "(might want to add '-g' to your '\$CFLAGS')" + global_options + } + + eval "$(getoptions parser_definition parse "$0")" + parse "$@" + eval set -- "$REST" + cpt-build "$@" + + # When building multiple packages, cpt will already ask to install + # the packages, so no need for this here. + [ "$2" ] || cpt-install "$@" +} + +cbi() { + # Checksum, build and install. + # + # shellcheck disable=2317 + parser_definition() { + setup REST help:usage -- "usage: ${0##*/} cbi [-dfSsty] [--root ROOT] [pkg...]" + msg -- '' 'Options:' + flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)" + flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation" + flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \ + "(might want to add '-g' to your '\$CFLAGS')" + flag sha -s -- "Generate checksums using the depracated sha256 algorithm" + global_options + } + + eval "$(getoptions parser_definition parse "$0")" + parse "$@" + eval set -- "$REST" + + cpt-checksum "$@"; cpt-build "$@" + [ "$2" ] || cpt-install "$@" +} + if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi # If none of the tools below are specified, we will reenable glob @@ -35,21 +82,7 @@ case "$arg" in r|remove) arg=remove ;; s|search) arg=search ;; u|update) arg=update ;; - bi) - # Build and install function for cpt. - cpt-build "$@" - - # When building multiple packages, cpt will already ask to install - # the packages, so no need for this here. - [ "$2" ] || cpt-install "$@" - exit - ;; - cbi) - # Checksum, build and install. - cpt-checksum "$@"; cpt-build "$@" - [ "$2" ] || cpt-install "$@" - exit - ;; + bi|cbi) "$arg" "$@"; exit "$?" ;; *) glob=1 ;; esac diff --git a/src/cpt-build b/src/cpt-build index 03a33b7..eaf8849 100755 --- a/src/cpt-build +++ b/src/cpt-build @@ -2,9 +2,12 @@ # Build a package parser_definition() { - setup REST help:usage -- "usage: ${0##*/} [-tfy] [--root ROOT] [pkg...]" + setup REST help:usage -- "usage: ${0##*/} [-dfSty] [--root ROOT] [pkg...]" msg -- '' 'Options:' - flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)" + flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation" + flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)" + flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \ + "(might want to add '-g' to your '\$CFLAGS')" global_options } diff --git a/src/cpt-lib.in b/src/cpt-lib.in index 9b71eab..1896920 100644 --- a/src/cpt-lib.in +++ b/src/cpt-lib.in @@ -88,32 +88,100 @@ _tsort() { # but the specification is quite vague, it doesn't specify cycles as a # reason of error, and implementations differ on how it's handled. coreutils # tsort(1) exits with an error, while openbsd tsort(1) doesn't. Both - # implementations are correct according to the specification. This leaves us - # with the following awk script, because the POSIX shell is not up for the - # job without super ugly hacks. - awk 'function fv(s) { - for (sp in e) { - split (e[sp],t) - for (j in t) if (s == t[j]) return 0 - } return 1 + # implementations are correct according to the specification. + # + # The script below was taken from <https://gist.github.com/apainintheneck/1803fb91dde3ba048ec51d44fa6065a4> + # + # The MIT License (MIT) + # Copyright (c) 2023 Kevin Robell + # + # Permission is hereby granted, free of charge, to any person obtaining a + # copy of this software and associated documentation files (the “Software”), + # to deal in the Software without restriction, including without limitation + # the rights to use, copy, modify, merge, publish, distribute, sublicense, + # and/or sell copies of the Software, and to permit persons to whom the + # Software is furnished to do so, subject to the following conditions: + # + # The above copyright notice and this permission notice shall be included in + # all copies or substantial portions of the Software. + # + # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + # DEALINGS IN THE SOFTWARE. + awk '{ + for (i = 1; i <= NF; ++i) { + # Store each node. + nodes[$i] = 1 + if (is_child) { + child = $i + # Skip nodes that point to themselves. + # This traditionally means that the node + # is disconnected from the rest of the graph. + if (parent != child) { + # Store from parent to child. + idx = ++child_count[parent] + child_graph[parent, idx] = child + # Store count from child to parent. + ++parent_count[child] + } + } else { + parent = $i + } + # Flip switch + is_child = !is_child + } } - function el(_l) {for(i in e){_l=_l" "i;}; return _l;} - function ce(t) {if (!(t in e)) e[t]="";} - function err(s) {print "Dependency cycle deteced between: " s; exit 1;} - {ce($1);$1!=$2&&e[$1]=e[$1]" "$2;} END { - do {p=el() - for (s in e) { - if (fv(s)) { - pr=s" "pr - split(e[s],t) - for(i in t){ce(t[i]);} - delete e[s] + # Print errors to the stderr + stderr = "/dev/stderr" + + # Sanity Check + if (is_child) { + print("Error: odd number of input values: expected pairs of values") > stderr + exit(1) + } + + ##### + # Topological Sort + ##### + + # Remove unconnected nodes first. + for (node in nodes) { + if (parent_count[node] == 0 && child_count[node] == 0) { + delete nodes[node] + print(node) + } + } + + # Remove the rest of the nodes starting with those without parents. + while (length(nodes) > 0) { + removed_node = 0 + for (node in nodes) { + # Delete and print nodes without any remaining parents. + if (parent_count[node] == 0) { + delete nodes[node] + removed_node = 1 + # Decrease child_count for each parent node. + for (i = child_count[node]; i > 0; --i) { + child = child_graph[node, i] + --parent_count[child] + } + print(node) } - } c=el() - } while (p != c) - if (length(p)!=0) err(p); - print pr + } + + # If we havent removed any nodes, it means that there + # are no nodes without any remaining parents so we have + # a cycle. + if (!removed_node) { + print("Error: Cycle found") > stderr + exit(1) + } + } }' } @@ -172,7 +240,7 @@ _stat() ( printf '%s' "$_user" ) -_readlinkf() ( +_readlinkf() { # Public domain POSIX sh readlink function by Koichi Nakashima [ "${1:-}" ] || return 1 max_symlinks=40 @@ -206,7 +274,7 @@ _readlinkf() ( target=${link#*" $target -> "} done return 1 -) +} _get_digest() { # Get digest algorithm from the given file. It looks for a header on the @@ -228,7 +296,7 @@ _get_digest() { # function. # URL: https://github.com/ko1nksm/getoptions (v2.5.0) # License: Creative Commons Zero v1.0 Universal -# shellcheck disable=2016,2086 +# shellcheck disable=2016,2086,2317 getoptions() { _error='' _on=1 _off='' _export='' _plus='' _mode='' _alt='' _rest='' _flags='' _nflags='' _opts='' _help='' _abbr='' _cmds='' _init=@empty IFS=' ' @@ -423,6 +491,7 @@ getoptions() { } # URL: https://github.com/ko1nksm/getoptions (v2.5.0) # License: Creative Commons Zero v1.0 Universal +# shellcheck disable=2317 getoptions_help() { _width='30,12' _plus='' _leading=' ' @@ -512,11 +581,12 @@ regesc() { pkg_download() { # $1: URL # $2: Output (Optional) - set -- "$1" "${2:-${1##*/}}" + set -- "$1" "$(_readlinkf "${2:-${1##*/}}")" case ${dl_prog##*/} in - aria2c|axel) set -- -o "$2" "$1" ;; - curl) set -- -fLo "$2" "$1" ;; - wget|wget2) set -- -O "$2" "$1" ;; + axel) set -- -o "$2" "$1" ;; + aria2c) set -- -d "${2%/*}" -o "${2##*/}" "$1" ;; + curl) set -- -fLo "$2" "$1" ;; + wget|wget2) set -- -O "$2" "$1" ;; esac "$dl_prog" "$@" || { @@ -859,6 +929,9 @@ pkg_extract() { backend=${src%%+*} url=${src##"${backend}"+} com=${url##*[@#]} com=${com#"${url%[@#]*}"} + # Add back @ to com + case $url in *@*) com=@$com; esac + log "$1" "Cloning ${url%[#@]*}" "pkg_vcs_clone_$backend" "${url%[#@]*}" "$com" ;; @@ -900,8 +973,9 @@ pkg_depends() { # Resolve all dependencies and generate an ordered list. # This does a depth-first search. The deepest dependencies are # listed first and then the parents in reverse order. - contains "$pkgs" "$1" || { - pkgs="$pkgs $1 " + # + # shellcheck disable=2015 + contains "$pkgs" "$1" && [ -z "$2" ] || { [ "$2" = raw ] && _dep_append "$1" "$1" while read -r dep type || [ "$dep" ]; do # Skip comments and empty lines. @@ -922,7 +996,7 @@ pkg_depends() { if [ "$2" = explicit ] || [ "$3" ]; then _dep_append "$dep" "$dep" else - _dep_append "$1" "$dep" + _dep_append "$dep" "$1" fi # Recurse through the dependencies of the child packages. Forward @@ -934,6 +1008,7 @@ pkg_depends() { fi done 2>/dev/null < "$(pkg_find "$1")/depends" ||: + pkgs="$pkgs $1 " } } @@ -970,7 +1045,7 @@ pkg_strip() { # system as well as on the tarballs we ship for installation. # Package has stripping disabled, stop here. - [ -f "$mak_dir/$pkg/nostrip" ] && return + [ "$CPT_NOSTRIP" ] || [ -f "$mak_dir/$pkg/nostrip" ] && return log "$1" "Stripping binaries and libraries" @@ -1841,7 +1916,7 @@ pkg_vcs_clone_git() { git init git remote add origin "${1%[#@]*}" case $2 in - @*) git fetch -t --depth=1 origin "${2#@}" || git fetch ;; + @*) git fetch -t --depth=1 origin "${2#@}" || git fetch; set -- "$1" "${2#@}" ;; *) git fetch --depth=1 origin "$2" || git fetch esac git checkout "${2:-FETCH_HEAD}" @@ -2177,6 +2252,7 @@ pkg_gentree() ( esac done pkg_depends "$1" tree "$make_deps" + pkg_depends_commit # Unless 'f' is given, pop the package from the list so that we don't list # the package (for example if it's part of the base package list). Normally @@ -2188,7 +2264,9 @@ pkg_gentree() ( # shellcheck disable=2086 [ -z "${2##*f*}" ] || deps=$(pop "$1" from $deps) - eval set -- "$deps" + # Word splitting is intentional. + # shellcheck disable=2086 + set -- $deps pkg_order "$@" if [ "$reverse" ]; then eval set -- "$redro"; else eval set -- "$order"; fi [ "$1" ] || return 0 @@ -2237,7 +2315,7 @@ _tmp_cp() { # second argument is not given, use the basename of the copied file. _ret=${2:-${1##*/}} _ret=$(_tmp_name "$_ret") - cp "$1" "$_ret" + cp -p "$1" "$_ret" out "$_ret" } @@ -2245,9 +2323,8 @@ _tmp_create() { # Create given file to the temporary directory and return its name create_tmp _ret=$(_tmp_name "$1") - # False positive, we are not reading from the file. - # shellcheck disable=2094 - out "$_ret" 3>> "$_ret" + :> "$_ret" || return 1 + out "$_ret" } create_tmp() { |