diff options
-rwxr-xr-x | src/cpt-alternatives | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/src/cpt-alternatives b/src/cpt-alternatives index 3c98753..87946f0 100755 --- a/src/cpt-alternatives +++ b/src/cpt-alternatives @@ -2,31 +2,83 @@ # List and swap to alternatives parser_definition() { - setup REST help:usage -- "usage: ${0##*/} [-] [package file]" - global_options silent + setup REST help:usage -- "usage: ${0##*/} package file" + msg -- "or: ${0##*/} [-p]" + msg -- "or: ${0##*/} -" + msg -- '' 'Options:' + flag preferred -p -- "List current owners of alternative files" + global_options } if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi # We don't need to be root in order to list alternatives, so skip privilege # elevation if no arguments are passed to the script. -[ -z "$1" ] || [ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || { +[ -z "$1" ] && [ -t 0 ] || [ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || { as_root "$0" "$@" exit $? } +list_alternatives() { + # Go over each alternative and format the file name for listing. + # (pkg_name>usr>bin>ls) + set +f + for pkg in "$sys_db/../choices/"*; do + printf '%s\n' "${pkg##*/}" + done | sed 's|>|\t/|;s|>|/|g;/\*/d' +} + +stdin_swap() { + # Swap packages by reading the standard input. + while IFS=$(printf '\t') read -r pkg path _; do + pkg_swap "$pkg" "$path" + done + exit +} + case "$1" in - -) - while read -r pkg path; do - pkg_swap "$pkg" "$path" - done - ;; + -) stdin_swap ;; '') - # Go over each alternative and format the file name for listing. - # (pkg_name>usr>bin>ls) - set +f; for pkg in "$sys_db/../choices/"*; do - printf '%s\n' "${pkg##*/}" - done | sed 's|>| /|; s|>|/|g; /\*/d' + # We still want to read the standard input when there are no arguments + # if the standard input is being used. + [ -t 0 ] || stdin_swap + + if [ "$preferred" ]; then + # We are not using the pkg_owner() function here. It's much slower + # when searching items in bulk. + altlist=$(_tmp_create altlist) + pathlist=$(_tmp_create pathlist) + owners=$(_tmp_create owners) + list_alternatives | tee "$altlist" | sed 's,^[^\t]*\t,,' > "$pathlist" + + # Save all matching items in a single file, so we don't ever read + # manifests again. + set +f + grep -Fxf "$pathlist" "$sys_db/"*/manifest > "$owners" + sys_db_esc=$(regesc "$sys_db") + + while read -r pkg path; do + case $path in + # Running regesc() for each file slows us down, don't use + # it unless we detect a regular expression to escape. + *\[*|*\$*|*\\*|*.*|*^*) path_str=$(regesc "$path") ;; + *) path_str=$path + esac + grep_str="$sys_db_esc/[^/]*/manifest:$path_str" + owns=$(grep -x -- "$grep_str" "$owners") || owns=null + owns=${owns%:*} owns=${owns%/*} owns=${owns##*/} + printf '%s\t%s\t(owned by: %s)\n' "$pkg" "$path" "$owns" + done < "$altlist" + + # We read the output of list_alternatives(), because that seems to + # be the faster option. + # list_alternatives | while read -r pkg path; do + # printf '%s %s (owned by: %s)\n' \ + # "$pkg" "$path" "$(pkg_owner -lFx "$path" || out "null")" + # done + else + list_alternatives + fi ;; *) pkg_swap "$@" ;; esac |