testpatches.sh - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
testpatches.sh (7546B)
---
1 #!/bin/sh
2 # TODO:
3 # ? build:
4 # - set flags per project? (per version too?).
5 # - add build status (OK, FAIL, unknown), must be secure though.
6
7 projects() {
8 cat <<!__EOF__
9 dmenu tools.suckless.org/dmenu/patches
10 dwm dwm.suckless.org/patches
11 ii tools.suckless.org/ii/patches
12 sent tools.suckless.org/sent/patches
13 sic tools.suckless.org/sic/patches
14 slock tools.suckless.org/slock/patches
15 st st.suckless.org/patches
16 surf surf.suckless.org/patches
17 tabbed tools.suckless.org/tabbed/patches
18 !__EOF__
19 }
20
21 wikidir="$(pwd)/sites"
22 repodir="$(pwd)/repos"
23 revdir="$(pwd)/rev"
24 resultsdir="$(pwd)/results"
25 builddir="$(pwd)/build"
26
27 # dryrun patch command (OpenBSD).
28 # must be unified diff (-u, so no ed script), -t and -C are dryrun (non-POSIX).
29 dryrun="patch -u -p1 -t -C"
30
31 # getdateutc()
32 getdateutc() {
33 # date as UTC+0 time.
34 TZ="UTC+0" date
35 }
36
37 # log(s)
38 log() {
39 s="[$(date)] $1"
40 echo "$s" >&2
41 }
42
43 # getprojects()
44 getprojects() {
45 # allow commenting to disable.
46 projects | grep -v '^#'
47 }
48
49 # clone()
50 clone() {
51 getprojects | while read -r -- project dir; do
52 test -d "$repodir/$project" && continue
53
54 git clone --bare "git://git.suckless.org/$project" "$repodir/$project"
55 done
56 }
57
58 # pull()
59 pull() {
60 getprojects | while read -r -- project dir; do
61 test -d "$repodir/$project" || continue
62
63 GIT_DIR="$repodir/$project" git fetch "git://git.suckless.org/$project"
64 done
65 }
66
67 # listpatches()
68 listpatches() {
69 getprojects | while read -r -- project dir; do
70 find "$wikidir/$dir" -name "*.diff" | while read -r p; do
71 test -f "$p" || continue
72
73 b=$(basename "$p")
74 bb="${b%.diff}"
75 bb="${bb#${project}-}"
76
77 # NOTE: historical patches like "r1506" (mercurial) are ignored.
78 v=$(echo "$bb" | sed -En 's@^([0-9a-f\.]+)-.*$@\1@p')
79 if test -z "$v"; then
80 v=$(echo "$bb" | sed -En 's@^.*-([0-9a-f\.]+)$@\1@p')
81 fi
82
83 # version not found, skip.
84 if test -z "$v"; then
85 continue
86 fi
87
88 name="${p%.diff}"
89 name="${name##*/patches/}"
90 name="${name%%/*}"
91
92 printf '%s\t%s\t%s\t%s\t%s\n' "$project" "$v" "$dir" "$name" "$p"
93 done
94 done
95 }
96
97 # checkoutrev(project, version)
98 checkoutrev() {
99 project="$1"
100 v="$2"
101
102 test -f "$revdir/$project/$v/fail" && return 1
103 test -d "$revdir/$project/$v" && return 0
104
105 cur=$(pwd)
106 d="$revdir/$project/$v"
107 mkdir -p "$d"
108 cd "$d" || return 1
109
110 GIT_DIR="$repodir/$project" \
111 git archive "$v" 2> "$revdir/$project/$v/fail" | \
112 tar xf - 2>/dev/null
113 status=$?
114 if test x"$status" != x"0"; then
115 status=1
116 else
117 rm -f "$revdir/$project/$v/fail"
118 fi
119 cd "$cur"
120
121 return $status
122 }
123
124 # preparebuilds()
125 preparebuilds() {
126 listpatches | while read -r -- project v dir name p; do
127 test -f "$p" || continue
128
129 # version quirks (wrong tagging).
130 if test x"$project" = x"sent"; then
131 if test x"$v" = x"1.0"; then
132 v="1"
133 test -e "$revdir/$project/1.0" || \
134 ln -sf "$v" "$revdir/$project/1.0"
135 fi
136 fi
137 if test x"$project" = x"ii"; then
138 if test x"$v" = x"1.7"; then
139 v="v1.7"
140 test -e "$revdir/$project/1.7" || \
141 ln -sf "$v" "$revdir/$project/1.7"
142 fi
143 fi
144
145 # prepare clean build directory for patch.
146 b=$(basename "$p")
147 b="${b%.diff}"
148
149 # cannot prepare revision for build: skip.
150 if ! checkoutrev "$project" "$v"; then
151 log "CANNOT CHECKOUT REVISION: $project v=$v, name=$name, patch=$b, error=$(cat "$revdir/$project/$v/fail")"
152 continue
153 fi
154
155 # already has clean builddir.
156 test -d "$builddir/$project/$b" && continue
157 cleanbuild "$project" "$v" "$b"
158 done
159 }
160
161 # cleanbuild(project, version, build)
162 cleanbuild() {
163 project="$1"
164 v="$2"
165 b="$3"
166
167 test -d "$builddir/$project/$b" && rm -rf "$builddir/$project/$b"
168
169 mkdir -p "$builddir/$project"
170 cp -r "$revdir/$project/$v" "$builddir/$project/$b"
171 }
172
173 # testpatches()
174 testpatches() {
175 # sort by project, name, version
176 listpatches | sort -k1,1 -k4,4 -k2,2 | \
177 while read -r -- project v dir name p; do
178 test -f "$p" || continue
179
180 # cannot prepare revision for build: skip.
181 checkoutrev "$project" "$v" || continue
182
183 b=$(basename "$p")
184 b="${b%.diff}"
185
186 test -d "$builddir/$project/$b" || continue
187 cd "$builddir/$project/$b" || continue
188
189 # copy patch file for convenience / debugging.
190 cp "$p" "$builddir/$project/$b/p.diff"
191
192 # lenient: copy config.def.h to config.h if config.h doesn't exist.
193 #rm -f "$builddir/$project/$b/config.h" # DEBUG
194 #if test -f "$builddir/$project/$b/config.def.h"; then
195 # if ! test -f "$builddir/$project/$b/config.h"; then
196 # cp "$builddir/$project/$b/config.def.h" "$builddir/$project/$b/config.h"
197 # fi
198 #fi
199
200 # patch (dryrun).
201 $dryrun < "$p" 2> "$builddir/$project/$b/patch.2.log" >"$builddir/$project/$b/patch.1.log"
202 applystatus=$?
203
204 # write results to metadata file (for creating views).
205 printf "%s\t%s\t%s\t%s\t%s\t%s\n" \
206 "$project" "$v" "$dir" "$name" "$applystatus" "$b" > "$builddir/$project/$b/metadata"
207
208 log "$p $applystatus"
209 done
210 }
211
212 # outputhtml()
213 outputhtml() {
214 index="$resultsdir/index.html"
215 title="Last updated on $(getdateutc)"
216
217 cat > "$index" <<!__EOF__
218 <!DOCTYPE html>
219 <html>
220 <head>
221 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
222 <title>$title - Patch applystatus</title>
223 <style type="text/css">
224 table { border-collapse: collapse; }
225 td { padding: 2px; }
226 thead td { background-color: #eee; }
227 .s-0 td { background-color: #ccffcc; }
228 .s-1 td { background-color: #ffcccc; }
229 .s-2 td { background-color: #ff0000; color: #fff; }
230 </style>
231 </head>
232 <body>
233 <h1>$title</h1>
234 <table>
235 <thead>
236 <tr>
237 <td><b>Project</b></td>
238 <td><b>Version/revision</b></td>
239 <td><b>Patch</b></td>
240 <td><b>Patch</b></td>
241 <td><b>Patch file</b></td>
242 <td><b>Patch stdout</b></td>
243 <td><b>Patch stderr</b></td>
244 <td><b>Exitcode</b></td>
245 <td><b>Status</b></td>
246 </tr>
247 </thead>
248 <tbody>
249 !__EOF__
250
251 # sort by project, name, version
252 find "$builddir" -name "metadata" -type f -exec cat {} \; | \
253 sort -k1,1 -k4,4 -k2,2 | \
254 while read -r -- project v dir name applystatus b; do
255 test -d "$builddir/$project/$b" || continue
256
257 # HTML output test
258 mkdir -p "$resultsdir/$b/"
259 cp \
260 "$builddir/$project/$b/p.diff"\
261 "$builddir/$project/$b/patch.2.log"\
262 "$builddir/$project/$b/patch.1.log"\
263 "$resultsdir/$b/"
264
265 statustext="OK"
266 pageurl="https://$dir/$name/"
267
268 case "$applystatus" in
269 0) statustext="OK";;
270 1) statustext="FAIL";;
271 2) statustext="CORRUPT";;
272 *) statustext="UNKNOWN";;
273 esac
274
275 cat >> "$index" <<!__EOF__
276 <tr class="s-$applystatus">
277 <td><a href="https://git.suckless.org/$project/">$project</a></td>
278 <td>$v</td>
279 <td><a href="$pageurl">$name</a></td>
280 <td><a href="$pageurl">$b</a></td>
281 <td><a href="$b/p.diff">[patch]</a></td>
282 <td><a href="$b/patch.1.log">[stdout]</a></td>
283 <td><a href="$b/patch.2.log">[stderr]</a></td>
284 <td>$applystatus</td>
285 <td>$statustext</td>
286 </tr>
287 !__EOF__
288 done
289
290 echo "</tbody></table></body></html>" >> "$index"
291 }
292
293 # outputcsv()
294 outputcsv() {
295 index="$resultsdir/index.csv"
296
297 # sort by project, name, version
298 find "$builddir" -name "metadata" -type f -exec cat {} \; | \
299 sort -k1,1 -k4,4 -k2,2 | \
300 while read -r -- project v dir name applystatus b; do
301 test -d "$builddir/$project/$b" || continue
302
303 printf '%s\n' "$project $v $name $b $applystatus" >> "$index"
304 done
305 }
306
307 case "$1" in
308 clone|pull)
309 mkdir -p "$repodir"
310 $1
311 ;;
312 clean)
313 rm -rf "$revdir" "$builddir"
314 ;;
315 prepare)
316 mkdir -p "$builddir" "$revdir"
317 preparebuilds
318 ;;
319 test)
320 testpatches
321 ;;
322 results)
323 # output results
324 rm -rf "$resultsdir"
325 mkdir -p "$resultsdir"
326 outputhtml
327 outputcsv
328 ;;
329 *)
330 echo "usage: $0 <clone | pull | clean | prepare | test | results>" >&2
331 exit 1
332 ;;
333 esac