update from their respective sources
[shellsnippets/shellsnippets.git] / mksh / debian-dev / quinn-ls.sh
1 #!/bin/mksh
2 rcsid='$MirOS: contrib/hosted/tg/deb/quinn-ls.sh,v 1.3 2011/05/25 17:40:51 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
25 while getopts "l" ch; do
26         case $ch {
27         (l)     gather=installed ;;
28         (*)     exit 1 ;;
29         }
30 done
31 shift $((OPTIND - 1))
32
33 # Debian Policy 3.9.2.0, §5.6.1
34 function isdebpkg {
35         [[ $1 = [a-z0-9]+([a-z0-9+.-]) ]]
36 }
37
38 # Debian Policy 3.9.2.0, §5.6.12
39 function isdebver {
40         local epochglob uvglob dvglob
41
42         # strict (must start with a digit)
43         #uvglob='[0-9]*'
44         # loose (should, but it's ok if not)
45         uvglob='+'
46
47         uvglob=$uvglob'([A-Za-z0-9.+~'
48
49         # colon is allowed if we have an epoch
50         if [[ $1 = +([0-9])':'* ]]; then
51                 epochglob='+([0-9])'\'':'\'
52                 uvglob=$uvglob':'
53         fi
54
55         # hyphen is allowed if we have a debian revision
56         if [[ $1 = *'-'+([A-Za-z0-9+.~]) ]]; then
57                 dvglob=\'-\''+([A-Za-z0-9+.~])'
58                 uvglob=$uvglob'-'
59         fi
60
61         uvglob=$uvglob'])'
62
63         eval [[ \$1 = $epochglob$uvglob$dvglob ]]
64 }
65
66 set -A pkgs
67 set -A lver
68 set -A uver
69 i=0
70 function do_gather {
71         if ! isdebpkg "$Source"; then
72                 print -ru2 "skipping invalid Source '$Source', file $name"
73                 return 2
74         fi
75         if ! isdebver "$Version"; then
76                 print -ru2 "skipping invalid Version '$Version', file $name"
77                 return 2
78         fi
79         j=-1
80         while (( ++j < i )); do
81                 [[ ${pkgs[j]} = "$Source" ]] && break
82         done
83         if (( j == i )); then
84                 print -ru2 "local $Source $Version"
85                 pkgs[i]=$Source
86                 lver[i++]=$Version
87                 return 0
88         fi
89         for x in ${lver[j]}; do
90                 # skip dups (from .changes = .dsc probably) silently
91                 [[ $x = "$Version" ]] && return 1
92         done
93         # put the newest local version leftmost
94         set -A xa -- ${lver[j]}
95         if dpkg --compare-versions "$Version" gt "${xa[0]}"; then
96                 print -ru2 "newer $Source $Version"
97                 lver[j]="$Version ${lver[j]}"
98         else
99                 print -ru2 "older $Source $Version"
100                 lver[j]="${lver[j]} $Version"
101         fi
102         return 0
103 }
104
105 if [[ $gather = cwd ]]; then
106         find . -name \*.changes -o -name \*.dsc |&
107         while IFS= read -pr name; do
108                 Source=
109                 Version=
110                 eval $(sed -n \
111                     -e '/^\(Source\): \([^ ]*\)\( .*\)*$/s//\1='\''\2'\''/p' \
112                     -e '/^\(Version\): \([^ ]*\)$/s//\1='\''\2'\''/p' \
113                     "$name")
114                 do_gather
115         done
116 elif [[ $gather = installed ]]; then
117         dpkg-query -Wf '${Package} ${Version} ${Source} ${Package}\n' |&
118         while read -p name Version Source x rest; do
119                 if [[ $Source = *'('*')' ]]; then
120                         # this is not customary…
121                         rest=${Source##*'('}
122                         rest=${rest%')'}
123                         isdebver "$rest" && Version=$rest
124                 elif [[ $x = '('*')' ]]; then
125                         # Source:Version ≠ Version
126                         x=${x#'('}
127                         x=${x%')'}
128                         isdebver "$x" && Version=$x
129                 fi
130                 do_gather
131         done
132 else
133         exit 1
134 fi
135
136 print -u2 '\nrunning rmadison…'
137 rmadison -s sid "${pkgs[@]}" |&
138 while read -pr pkg pipe vsn pipe sid pipe arches; do
139         #print -u2 "D: pkg<$pkg> vsn<$vsn> sid<$sid> arches<$arches>"
140         arches=${arches//,/ }
141         [[ " $arches " = *' source '* ]] || continue
142         j=-1
143         while (( ++j < i )); do
144                 [[ ${pkgs[j]} = "$pkg" ]] && break
145         done
146         if (( j == i )); then
147                 print -ru2 "bogus $pkg $vsn ignored"
148                 continue
149         fi
150         x=${uver[j]}
151         if [[ -z $x ]]; then
152                 print -ru2 "found $pkg $vsn"
153                 uver[j]=$vsn
154         elif [[ $x = "$vsn" ]]; then
155                 print -ru2 "equal $pkg $vsn ignored"
156         elif dpkg --compare-versions "$x" lt "$vsn"; then
157                 print -ru2 "newer $pkg $vsn (dropping $x)"
158                 uver[j]=$vsn
159         else
160                 print -ru2 "older $pkg $vsn ignored"
161         fi
162 done
163
164 print -u2 '\nreading override files [bad bld ign]…'
165 # bad: mark RIGHT versions lower or equal as "bad"
166 # bld: mark RIGHT version equal as "building"
167 # ign: mark LEFT version equal as "ignored" and ignore not-in-upstream
168 for type in bad bld ign; do
169         [[ -s $mydir/quinn-ls.$type ]] || continue
170         while read pkg vsn; do
171                 if ! isdebpkg "$pkg"; then
172                         print -ru2 "skipping invalid package '$pkg'," \
173                             override $type
174                         continue
175                 fi
176                 if ! isdebver "$vsn"; then
177                         print -ru2 "skipping invalid version '$vsn'," \
178                              override $type
179                         continue
180                 fi
181                 print -ru2 "o:$type $pkg $vsn"
182                 epkg=${pkg//'+'/_p}
183                 epkg=${epkg//'.'/_d}
184                 epkg=${epkg//'-'/_u}
185                 eval over_${type}_${epkg}=\$vsn
186         done <$mydir/quinn-ls.$type
187 done
188
189 c0=$'\033[0m'
190 c1=$'\033[1;31m'
191 c2=$'\033[1;32m'
192 c3=$'\033[1;33m'
193 c4=$'\033[1;34m'
194 c5=$'\033[1;35m'
195 c6=$'\033[1;36m'
196 print -ru2 "$c0"
197 print -ru2
198
199 j=-1
200 while (( ++j < i )); do
201         pkg=${pkgs[j]}
202         lvs=${lver[j]}
203         lv=${lvs%% *}
204         uv=${uver[j]}
205
206         if [[ -z $uv ]]; then
207                 uv=0~RM
208                 lc=$c1
209                 uc=$c1
210         elif [[ $lv = "$uv"?('+b'+([0-9])) ]]; then
211                 lc=$c2
212                 uc=$c2
213         elif dpkg --compare-versions "$lv" lt "$uv"; then
214                 lc=$c1
215                 uc=$c3
216         else
217                 lc=$c3
218                 uc=$c4
219         fi
220
221         epkg=${pkg//'+'/_p}
222         epkg=${epkg//'.'/_d}
223         epkg=${epkg//'-'/_u}
224         for type in bad bld ign; do
225                 eval over_$type=\$over_${type}_${epkg}
226         done
227         if [[ -n $over_ign && $lv = "$over_ign" ]]; then
228                 lc=$c6
229                 [[ $uv = '0~RM' ]] && uc=$c6
230         fi
231         [[ -n $over_bad ]] && dpkg --compare-versions "$uv" le "$over_bad" && \
232             uc=$c5
233         [[ -n $over_bld && $uv = "$over_bld" ]] && uc=$c6
234
235         print -r -- "$c0$pkg $lc$lv$c0 $uc$uv$c0"
236         [[ $lvs = $lv ]] && continue
237         for lv in ${lvs#* }; do
238                 [[ $lv = "$uv"?('+b'+([0-9])) ]] && continue
239                 print -r -- "$c0$pkg $c4$lv$c0 -"
240         done
241 done | sort | column -t