aboutsummaryrefslogtreecommitdiff
path: root/src/cpt-alternatives
blob: 87946f07bf593788c2e53535338ff8349aa98b09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/sh -ef
# List and swap to alternatives

parser_definition() {
    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" ] && [ -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
    -)  stdin_swap ;;
    '')
        # 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