update from MirBSD masters
[shellsnippets/shellsnippets.git] / mksh / debian-dev / quinn-ls.sh
1 #!/bin/mksh
2 rcsid='$MirOS: contrib/hosted/tg/deb/quinn-ls.sh,v 1.6 2011/11/11 20:24:02 tg Exp $'
3 #-
4 # Copyright © 2011
5 #       Thorsten Glaser <tg@debian.org>
6 #
7 # Provided that these terms and disclaimer and all copyright notices
8 # are retained or reproduced in an accompanying document, permission
9 # is granted to deal in this work without restriction, including un‐
10 # limited rights to use, publicly perform, distribute, sell, modify,
11 # merge, give away, or sublicence.
12 #
13 # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
14 # the utmost extent permitted by applicable law, neither express nor
15 # implied; without malicious intent or gross negligence. In no event
16 # may a licensor, author or contributor be held liable for indirect,
17 # direct, other damage, loss, or other issues arising in any way out
18 # of dealing in the work, even if advised of the possibility of such
19 # damage or existence of a defect, except proven that it results out
20 # of said person’s immediate fault when using the work as intended.
21
22 gather=cwd
23 mydir=$(realpath "$(dirname "$0")")
24 PATH="$mydir:$mydir/..:$PATH" . assockit.ksh
25
26 while getopts "l" ch; do
27         case $ch {
28         (l)     gather=installed ;;
29         (*)     exit 1 ;;
30         }
31 done
32 shift $((OPTIND - 1))
33
34 # Debian Policy 3.9.2.0, §5.6.1
35 function isdebpkg {
36         [[ $1 = [a-z0-9]+([a-z0-9+.-]) ]]
37 }
38
39 # Debian Policy 3.9.2.0, §5.6.12
40 function isdebver {
41         local epochglob uvglob dvglob
42
43         # strict (must start with a digit)
44         #uvglob='[0-9]*'
45         # loose (should, but it's ok if not)
46         uvglob='+'
47
48         uvglob=$uvglob'([A-Za-z0-9.+~'
49
50         # colon is allowed if we have an epoch
51         if [[ $1 = +([0-9])':'* ]]; then
52                 epochglob='+([0-9])'\'':'\'
53                 uvglob=$uvglob':'
54         fi
55
56         # hyphen is allowed if we have a debian revision
57         if [[ $1 = *'-'+([A-Za-z0-9+.~]) ]]; then
58                 dvglob=\'-\''+([A-Za-z0-9+.~])'
59                 uvglob=$uvglob'-'
60         fi
61
62         uvglob=$uvglob'])'
63
64         eval [[ \$1 = $epochglob$uvglob$dvglob ]]
65 }
66
67 i=0
68 function do_gather {
69         if ! isdebpkg "$Source"; then
70                 print -ru2 "skipping invalid Source '$Source', file $name"
71                 return 2
72         fi
73         if ! isdebver "$Version"; then
74                 print -ru2 "skipping invalid Version '$Version', file $name"
75                 return 2
76         fi
77         lver=$(asso_getv pkgs "$Source" lver)
78         if [[ -z $lver ]]; then
79                 print -ru2 "local $Source $Version"
80                 asso_sets "$Version" pkgs "$Source" lver
81                 return 0
82         fi
83         lver=$(asso_getv pkgs "$Source" lver)
84         for x in $lver; do
85                 # skip dups (from .changes = .dsc probably) silently
86                 [[ $x = "$Version" ]] && return 1
87         done
88         # put the newest local version leftmost
89         set -A xa -- $lver
90         if dpkg --compare-versions "$Version" gt "${xa[0]}"; then
91                 print -ru2 "newer $Source $Version"
92                 lver="$Version $lver"
93         else
94                 print -ru2 "older $Source $Version"
95                 lver="$lver $Version"
96         fi
97         asso_sets "$lver" pkgs "$Source" lver
98         return 0
99 }
100
101 if [[ $gather = cwd ]]; then
102         find . -name \*.changes -o -name \*.dsc |&
103         while IFS= read -pr name; do
104                 Source=
105                 Version=
106                 eval $(sed -n \
107                     -e '/^\(Source\): \([^ ]*\)\( .*\)*$/s//\1='\''\2'\''/p' \
108                     -e '/^\(Version\): \([^ ]*\)$/s//\1='\''\2'\''/p' \
109                     "$name")
110                 do_gather
111         done
112 elif [[ $gather = installed ]]; then
113         dpkg-query -Wf '${Package} ${Version} ${Source} ${Package}\n' |&
114         while read -p name Version Source x rest; do
115                 if [[ $Source = *'('*')' ]]; then
116                         # this is not customary…
117                         rest=${Source##*'('}
118                         rest=${rest%')'}
119                         isdebver "$rest" && Version=$rest
120                 elif [[ $x = '('*')' ]]; then
121                         # Source:Version ≠ Version
122                         x=${x#'('}
123                         x=${x%')'}
124                         isdebver "$x" && Version=$x
125                 fi
126                 do_gather
127         done
128 else
129         exit 1
130 fi
131
132 print -u2 '\nrunning rmadison…'
133 asso_loadk pkgs
134 rmadison -s sid "${asso_y[@]}" |&
135 while read -pr pkg pipe vsn pipe sid pipe arches; do
136         #print -u2 "D: pkg<$pkg> vsn<$vsn> sid<$sid> arches<$arches>"
137         arches=${arches//,/ }
138         [[ " $arches " = *' source '* ]] || continue
139         if ! asso_isset pkgs "$pkg" lver; then
140                 print -ru2 "bogus $pkg $vsn ignored"
141                 continue
142         fi
143         x=$(asso_getv pkgs "$pkg" uver)
144         if [[ -z $x ]]; then
145                 print -ru2 "found $pkg $vsn"
146                 asso_sets "$vsn" pkgs "$pkg" uver
147         elif [[ $x = "$vsn" ]]; then
148                 print -ru2 "equal $pkg $vsn ignored"
149         elif dpkg --compare-versions "$x" lt "$vsn"; then
150                 print -ru2 "newer $pkg $vsn (dropping $x)"
151                 asso_sets "$vsn" pkgs "$pkg" uver
152         else
153                 print -ru2 "older $pkg $vsn ignored"
154         fi
155 done
156
157 print -u2 '\nreading override files [bad bld ign]…'
158 # bad: mark RIGHT versions lower or equal as "bad"
159 # bld: mark RIGHT version equal as "building"
160 # ign: mark LEFT version equal as "ignored" and ignore not-in-upstream
161 for type in bad bld ign; do
162         [[ -s $mydir/quinn-ls.$type ]] || continue
163         while read pkg vsn; do
164                 [[ $pkg = '#'* ]] && continue
165                 if ! isdebpkg "$pkg"; then
166                         print -ru2 "skipping invalid package '$pkg'," \
167                             override $type
168                         continue
169                 fi
170                 if ! isdebver "$vsn"; then
171                         print -ru2 "skipping invalid version '$vsn'," \
172                              override $type
173                         continue
174                 fi
175                 print -ru2 "o:$type $pkg $vsn"
176                 asso_sets "$vsn" over "$type" "$pkg"
177         done <$mydir/quinn-ls.$type
178 done
179
180 c0=$'\033[0m'
181 c1=$'\033[1;31m'
182 c2=$'\033[1;32m'
183 c3=$'\033[1;33m'
184 c4=$'\033[1;34m'
185 c5=$'\033[1;35m'
186 c6=$'\033[1;36m'
187 print -ru2 "$c0"
188 print -ru2
189
190 asso_loadk pkgs
191 for pkg in "${asso_y[@]}"; do
192         lvs=$(asso_getv pkgs "$pkg" lver)
193         lv=${lvs%% *}
194         uv=$(asso_getv pkgs "$pkg" uver)
195
196         if [[ -z $uv ]]; then
197                 uv=0~RM
198                 lc=$c1
199                 uc=$c1
200         elif [[ $lv = "$uv"?('+b'+([0-9])) ]]; then
201                 lc=$c2
202                 uc=$c2
203         elif dpkg --compare-versions "$lv" lt "$uv"; then
204                 lc=$c1
205                 uc=$c3
206         else
207                 lc=$c3
208                 uc=$c4
209         fi
210
211         over_bad=$(asso_getv over bad "$pkg")
212         over_bld=$(asso_getv over bld "$pkg")
213         over_ign=$(asso_getv over ign "$pkg")
214         if [[ -n $over_ign && $lv = "$over_ign" ]]; then
215                 lc=$c6
216                 [[ $uv = '0~RM' ]] && uc=$c6
217         fi
218         [[ -n $over_bad ]] && dpkg --compare-versions "$uv" le "$over_bad" && \
219             uc=$c5
220         [[ -n $over_bld && $uv = "$over_bld" ]] && uc=$c6
221
222         print -r -- "$c0$pkg $lc$lv$c0 $uc$uv$c0"
223         [[ $lvs = $lv ]] && continue
224         for lv in ${lvs#* }; do
225                 [[ $lv = "$uv"?('+b'+([0-9])) ]] && continue
226                 lc=$c4
227                 [[ -n $over_ign && $lv = "$over_ign" ]] && lc=$c6
228                 print -r -- "$c0$pkg $lc$lv$c0 -"
229         done
230 done | sort | column -t