]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/sh | |
2 | ||
3 | usage() { | |
4 | echo "\ | |
5 | apkv: Quickly add and remove packages to/from Alpine virtual packages. | |
6 | ||
7 | Usage: | |
8 | $0 add <packages> <virtual> | |
9 | Add <packages> to virtual package <virtual>. If the virtual package | |
10 | does not exist, it will be created. | |
11 | $0 del <packages> <virtual> | |
12 | Remove <packages> from virtual package <virtual>. Empty virtual | |
13 | packages are removed from world. The shorthand '$0 del * <virtual>' can | |
14 | be used to empty <virtual>. | |
15 | $0 list [packages] | |
16 | List all or specific virtual packages and their contents. | |
17 | $0 help | |
18 | Show this help. | |
19 | ||
20 | Virtual packages must be prefixed with a dot to be managed with apkv. If one is | |
21 | not present, it will be added automatically. | |
22 | ||
23 | Methods can be shortened to their closest unambiguous forms, e.g. a, d, or l. | |
24 | However, due to implementation specifics, any string starting with those forms | |
25 | will work; that functionality is unspecified and is not guaranteed. | |
26 | ||
27 | For example, the following are equivalent: | |
28 | apkv add syslinux .virt | |
29 | apkv a syslinux virt | |
30 | apkv abcdefg syslinux .virt | |
31 | ||
32 | " | |
33 | } | |
34 | ||
35 | prepend_dot() { | |
36 | case $1 in | |
37 | .*) printf "$1";; | |
38 | *) printf ".$1";; | |
39 | esac | |
40 | } | |
41 | ||
42 | show_reqs() { | |
43 | _pkg="$1" | |
44 | shift >/dev/null | |
45 | [ -z "$_pkg" ] && return 1 | |
46 | if [ $# -gt 0 ]; then | |
47 | _list=$(echo "$(for x do echo $x; done)" | sort | uniq) | |
48 | else | |
49 | apk info -e "$_pkg" >/dev/null || return 1 | |
50 | _list=$(apk info -R "$_pkg" | awk 'NR > 1 && NF' | sort) | |
51 | fi | |
52 | echo -e "\e[1m$_pkg\e[0m:" $_list | |
53 | } | |
54 | ||
55 | method="$1" | |
56 | shift >/dev/null | |
57 | case $method in | |
58 | l*) for x in ${*:-$(apk info | grep '^\.')}; do | |
59 | show_reqs "$(prepend_dot "$x")" | |
60 | done | |
61 | exit;; | |
62 | a*) method=add;; | |
63 | d*) method=del;; | |
64 | h*) usage; exit;; | |
65 | -*) usage; exit;; | |
66 | *) [ -n "$method" ] && echo "Invalid method $method" >&2; usage; exit 1;; | |
67 | esac | |
68 | ||
69 | ## add/del | |
70 | # get and validate packages | |
71 | pkgs= | |
72 | virt= | |
73 | for x; do | |
74 | if [ -n "$pkgs" ]; then | |
75 | pkgs="$pkgs $virt" | |
76 | elif [ -n "$virt" ]; then | |
77 | pkgs=$virt | |
78 | fi | |
79 | virt=$x | |
80 | done | |
81 | if [ -z "$pkgs" ]; then | |
82 | echo 'Not enough arguments' >&2 | |
83 | usage | |
84 | exit 1 | |
85 | fi | |
86 | virt=$(prepend_dot $virt) | |
87 | # exit if database locked (99) or no package found to delete from (1) | |
88 | apk info -e "$virt" >/dev/null | |
89 | code=$? | |
90 | if [ $code -eq 99 -o \( $method = del -a $code -ne 0 \) ]; then | |
91 | exit $code | |
92 | fi | |
93 | ||
94 | # we have validated our args, so let's prepare to run apk: get sudo command if | |
95 | # it exists and we are not already root | |
96 | # TODO: support doas | |
97 | if [ "$(id -u)" != 0 ] && command -v sudo >/dev/null 2>&1; then | |
98 | sudo=$(command -v sudo) | |
99 | fi | |
100 | ||
101 | # handle quick delete shorthand mentioned in help | |
102 | if [ $method = del -a '*' = "$pkgs" ]; then | |
103 | $sudo apk del "$virt" | |
104 | exit $? | |
105 | fi | |
106 | ||
107 | currpkgs=$(apk info -R "$virt" | awk 'NR > 1 && NF') | |
108 | case $method in | |
109 | # $(echo) construct is to use word splitting to normalize whitespace | |
110 | add) currpkgs="$(echo $currpkgs) $pkgs";; | |
111 | del) # XXX: there's probably a more efficient way to do this | |
112 | for x in "$pkgs"; do | |
113 | currpkgs=$(echo "$currpkgs" | grep -vFiw $x) | |
114 | done;; | |
115 | esac | |
116 | ||
117 | if [ -z "$currpkgs" ]; then | |
118 | # virtual package is empty | |
119 | $sudo apk del "$virt" | |
120 | else | |
121 | show_reqs "$virt" $currpkgs | |
122 | $sudo apk add -t "$virt" $currpkgs | |
123 | fi | |
124 | # pass along sudo/apk exit code | |
125 | exit $? | |
126 | ||
127 | # vi:sw=4:sts=4:et |