because py3k nor js can output fixed floats with full precision
[shellsnippets/shellsnippets.git] / mksh / sortplug.sh
1 #!/usr/bin/env mksh
2 # -*- mode: sh -*-
3 #-
4 # Copyright © 2018
5 #       mirabilos <t.glaser@tarent.de>
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 # Pipe a Maven POM’s <plugins> element’s content without the plugins
23 # element itself through this to sort them.
24
25 LC_ALL=C; export LC_ALL
26 unset LANGUAGE
27
28 set -e
29 cr=$'\r'
30 lf=$'\n'
31 (( ${#cr} == 1 ))
32 set -o pipefail
33 me=$(realpath "$0/..")
34
35 # offsets in element array
36 OgroupId=1
37 OartifactId=0
38 Oversion=5
39 Oextensions=6
40 Oexecutions=7
41 Odependencies=8
42 Ogoals=9
43 Oinherited=2
44 Oconfiguration=10
45 OPRECOMMENT=4
46 OINCOMMENT=3
47
48 exec 4<&0
49 (
50         print '<toplevel>'
51         tr "$cr" "$lf" <&4
52         print '</toplevel>'
53 ) | xmlstarlet fo -e UTF-8 -t - |&
54
55 die() {
56         print -ru2 -- "E: $*"
57         print -ru2 -- "N: line: ${line@Q}"
58         exit 1
59 }
60
61 set -A sortlines
62 IFS= read -pr line
63 [[ $line = '<?xml version="1.0" encoding="UTF-8"?>' ]] || \
64     die unexpected first line not XML declaration
65 IFS= read -pr line
66 [[ $line = '<toplevel>' ]] || die unexpected second line not start tag
67
68 set -A el
69 el[OgroupId]=org.apache.maven.plugins
70 state=0
71 while IFS= read -pr line; do
72         case $state:$line {
73         (0:*(   )'<!--'*'-->')
74                 el[OPRECOMMENT]+=$line ;;
75         (1:*(   )'<!--'*'-->')
76                 el[OINCOMMENT]+=$line ;;
77         (0:*(   )'<!--'*)
78                 el[OPRECOMMENT]+=$line
79                 while IFS= read -pr line; do
80                         el[OPRECOMMENT]+=\ ${line##*([   ])}
81                         [[ $line = *'-->' ]] && break
82                 done
83                 [[ $line = *'-->' ]] || die unclosed comment ;;
84         (1:*(   )'<!--'*)
85                 el[OINCOMMENT]+=$line
86                 while IFS= read -pr line; do
87                         el[OINCOMMENT]+=\ ${line##*([    ])}
88                         [[ $line = *'-->' ]] && break
89                 done
90                 [[ $line = *'-->' ]] || die unclosed comment ;;
91         (0:'</toplevel>')
92                 state=9 ;;
93         (0:'    <plugin>')
94                 state=1 ;;
95         (1:'    </plugin>')
96                 if [[ -n ${el[Odependencies]} ]]; then
97                         line=${el[Odependencies]}
98                         x=$(mksh "$me/sortdeps.sh" <<<"$line") || \
99                             die could not sort dependencies
100                         el[Odependencies]=${x//"$lf"}
101                 fi
102                 sortlines+=("${el[0]}$cr${el[1]}$cr${el[2]}$cr${el[3]}$cr${el[4]}$cr${el[5]}$cr${el[6]}$cr${el[7]}$cr${el[8]}$cr${el[9]}$cr${el[10]}")
103                 set -A el
104                 el[OgroupId]=org.apache.maven.plugins
105                 state=0 ;;
106         (1:'            <'@(artifactId|version|extensions|executions|dependencies|goals|inherited|configuration)'/>')
107                 ;;
108         (1:'            <groupId>'*'</groupId>')
109                 x=${line#'              <groupId>'}
110                 el[OgroupId]=${x%'</groupId>'} ;;
111         (1:'            <groupId>')
112                 x=
113                 while IFS= read -pr line; do
114                         [[ $line = '            </groupId>' ]] && break
115                         x+=$line
116                 done
117                 [[ $line = '            </groupId>' ]] || \
118                     die unterminated tag groupId
119                 [[ -n $x ]] || die empty groupId
120                 el[OgroupId]=$x ;;
121         (1:'            <artifactId>'*'</artifactId>')
122                 x=${line#'              <artifactId>'}
123                 el[OartifactId]=${x%'</artifactId>'} ;;
124         (1:'            <artifactId>')
125                 x=
126                 while IFS= read -pr line; do
127                         [[ $line = '            </artifactId>' ]] && break
128                         x+=$line
129                 done
130                 [[ $line = '            </artifactId>' ]] || \
131                     die unterminated tag artifactId
132                 el[OartifactId]=$x ;;
133         (1:'            <version>'*'</version>')
134                 x=${line#'              <version>'}
135                 el[Oversion]=${x%'</version>'} ;;
136         (1:'            <version>')
137                 x=
138                 while IFS= read -pr line; do
139                         [[ $line = '            </version>' ]] && break
140                         x+=$line
141                 done
142                 [[ $line = '            </version>' ]] || \
143                     die unterminated tag version
144                 el[Oversion]=$x ;;
145         (1:'            <extensions>'*'</extensions>')
146                 x=${line#'              <extensions>'}
147                 el[Oextensions]=${x%'</extensions>'} ;;
148         (1:'            <extensions>')
149                 x=
150                 while IFS= read -pr line; do
151                         [[ $line = '            </extensions>' ]] && break
152                         x+=$line
153                 done
154                 [[ $line = '            </extensions>' ]] || \
155                     die unterminated tag extensions
156                 el[Oextensions]=$x ;;
157         (1:'            <executions>'*'</executions>')
158                 x=${line#'              <executions>'}
159                 el[Oexecutions]=${x%'</executions>'} ;;
160         (1:'            <executions>')
161                 x=
162                 while IFS= read -pr line; do
163                         [[ $line = '            </executions>' ]] && break
164                         x+=$line
165                 done
166                 [[ $line = '            </executions>' ]] || \
167                     die unterminated tag executions
168                 el[Oexecutions]=$x ;;
169         (1:'            <dependencies>'*'</dependencies>')
170                 x=${line#'              <dependencies>'}
171                 el[Odependencies]=${x%'</dependencies>'} ;;
172         (1:'            <dependencies>')
173                 x=
174                 while IFS= read -pr line; do
175                         [[ $line = '            </dependencies>' ]] && break
176                         x+=$line
177                 done
178                 [[ $line = '            </dependencies>' ]] || \
179                     die unterminated tag dependencies
180                 el[Odependencies]=$x ;;
181         (1:'            <goals>'*'</goals>')
182                 x=${line#'              <goals>'}
183                 el[Ogoals]=${x%'</goals>'} ;;
184         (1:'            <goals>')
185                 x=
186                 while IFS= read -pr line; do
187                         [[ $line = '            </goals>' ]] && break
188                         x+=$line
189                 done
190                 [[ $line = '            </goals>' ]] || \
191                     die unterminated tag goals
192                 el[Ogoals]=$x ;;
193         (1:'            <inherited>'*'</inherited>')
194                 x=${line#'              <inherited>'}
195                 el[Oinherited]=${x%'</inherited>'} ;;
196         (1:'            <inherited>')
197                 x=
198                 while IFS= read -pr line; do
199                         [[ $line = '            </inherited>' ]] && break
200                         x+=$line
201                 done
202                 [[ $line = '            </inherited>' ]] || \
203                     die unterminated tag inherited
204                 el[Oinherited]=$x ;;
205         (1:'            <configuration>'*'</configuration>')
206                 x=${line#'              <configuration>'}
207                 el[Oconfiguration]=${x%'</configuration>'} ;;
208         (1:'            <configuration>')
209                 x=
210                 while IFS= read -pr line; do
211                         [[ $line = '            </configuration>' ]] && break
212                         x+=$line
213                 done
214                 [[ $line = '            </configuration>' ]] || \
215                     die unterminated tag configuration
216                 el[Oconfiguration]=$x ;;
217         (*)
218                 die illegal line in state $state ;;
219         }
220 done
221 (( state == 9 )) || die unexpected last line not end tag
222
223 for x in "${sortlines[@]}"; do
224         print -r -- "$x"
225 done | sort -u |&
226
227 while IFS="$cr" read -prA el; do
228         [[ -n ${el[OPRECOMMENT]} ]] && print -r -- "${el[OPRECOMMENT]}"
229         print -r -- '<plugin>'
230         [[ -n ${el[OINCOMMENT]} ]] && print -r -- "${el[OINCOMMENT]}"
231         [[ -n ${el[OgroupId]} ]] && print -r -- "<groupId>${el[OgroupId]}</groupId>"
232         [[ -n ${el[OartifactId]} ]] && print -r -- "<artifactId>${el[OartifactId]}</artifactId>"
233         [[ -n ${el[Oversion]} ]] && print -r -- "<version>${el[Oversion]}</version>"
234         [[ -n ${el[Oextensions]} ]] && print -r -- "<extensions>${el[Oextensions]}</extensions>"
235         [[ -n ${el[Oexecutions]} ]] && print -r -- "<executions>${el[Oexecutions]}</executions>"
236         [[ -n ${el[Odependencies]} ]] && print -r -- "<dependencies>${el[Odependencies]}</dependencies>"
237         [[ -n ${el[Ogoals]} ]] && print -r -- "<goals>${el[Ogoals]}</goals>"
238         [[ -n ${el[Oinherited]} ]] && print -r -- "<inherited>${el[Oinherited]}</inherited>"
239         [[ -n ${el[Oconfiguration]} ]] && print -r -- "<configuration>${el[Oconfiguration]}</configuration>"
240         print -r -- '</plugin>'
241 done
242
243 exit 0