OILS / regtest / aports-html.sh View on Github | oils.pub

897 lines, 393 significant
1#!/usr/bin/env bash
2#
3# Make HTML reports
4#
5# Usage:
6# regtest/aports-html.sh <function name>
7#
8# Examples:
9# $0 sync-results he.oils.pub
10# $0 write-all-reports
11# $0 make-wwz _tmp/aports-report/2025-08-03
12# $0 deploy-wwz-op _tmp/aports-report/2025-08-03.wwz # deploy to op.oils.pub
13
14: ${LIB_OSH=stdlib/osh}
15source $LIB_OSH/bash-strict.sh
16source $LIB_OSH/task-five.sh
17
18source regtest/aports-common.sh
19
20REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
21source test/tsv-lib.sh # tsv2html3
22source web/table/html.sh # table-sort-{begin,end}
23source benchmarks/common.sh # cmark
24source build/dev-shell.sh # python2
25
26sqlite-tabs-headers() {
27 sqlite3 \
28 -cmd '.mode tabs' \
29 -cmd '.headers on' \
30 "$@"
31}
32
33html-head() {
34 # python3 because we're outside containers
35 PYTHONPATH=. python3 doctools/html_head.py "$@"
36}
37
38index-html() {
39 local base_url='../../../../web'
40 html-head --title "aports Build" \
41 "$base_url/base.css"
42
43 # TODO:
44 # - Stats for each config:
45 # - number of non-zero exit codes, total packages
46
47 cmark <<'EOF'
48<body class="width35">
49
50<p id="home-link">
51 <a href="/">Home</a>
52</p>
53
54# aports Build
55
56Configurations:
57
58- [baseline](baseline/packages.html) - [raw tasks](baseline/tasks.html) - [metrics](baseline/metrics.txt)
59- [osh-as-sh](osh-as-sh/packages.html) - [raw tasks](osh-as-sh/tasks.html) - [metrics](osh-as-sh/metrics.txt)
60
61## Baseline versus osh-as-sh
62
63- [diff_baseline](diff_baseline.html)
64
65## osh-as-sh versus osh-as-bash
66
67TODO
68
69</body>
70EOF
71}
72
73diff-summary-html() {
74 local db=${1:-_tmp/aports-report/2025-08-03/diff_merged.db}
75
76 sqlite3 $db < regtest/aports/summary.sql
77
78 echo '
79 <p></p>
80
81 <div class="side-by-side">
82 <section>
83 <h3>Task Summary</h3>
84 '
85 sqlite3 $db < regtest/aports/summary2.sql
86
87 cmark << 'EOF'
88</section>
89
90<section>
91
92### Common Causes of Disagreements
93EOF
94
95 tsv2html3 $base_dir/cause_hist.tsv
96
97 sqlite3 $db << 'EOF'
98select
99 printf(
100 '<p>Unique causes: %d </p>',
101 count(distinct cause)
102 )
103from notable_disagree
104where cause != 'unknown';
105EOF
106
107 cmark <<'EOF'
108Source: [regtest/aports/cause.awk](https://github.com/oils-for-unix/oils/blob/master/regtest/aports/cause.awk)
109EOF
110
111 echo '
112 </section>
113 </div> <!-- side-by-side -->
114 '
115}
116
117table-page-html() {
118 local base_dir=${1:-$REPORT_DIR/$EPOCH}
119 local name=${2:-diff_baseline}
120 local base_url=${3:-'../../../../web'}
121 local title=${4:-'OSH Disagreements - regtest/aports'}
122
123 html-head --title "$title" \
124 "$base_url/ajax.js" \
125 "$base_url/table/table-sort.js" \
126 "$base_url/table/table-sort.css" \
127 "$base_url/base.css"
128
129 table-sort-begin 'width60'
130
131 cmark <<EOF
132<p id="home-link">
133 <a href="../index.html">Up</a> |
134 <a href="/">Home</a>
135</p>
136
137# $title
138
139EOF
140
141 tsv2html3 $base_dir/$name.tsv
142
143 cmark <<EOF
144
145[$name.tsv]($name.tsv)
146EOF
147
148 table-sort-end "$name" # ID for sorting
149}
150
151merge-diff-html() {
152 local base_dir=${1:-$REPORT_DIR/$EPOCH}
153 local base_url=${2:-'../../../../web'}
154 local title=${3:-'OSH Disagreements - regtest/aports'}
155
156 html-head --title "$title" \
157 "$base_url/ajax.js" \
158 "$base_url/table/table-sort.js" \
159 "$base_url/table/table-sort.css" \
160 "$base_url/base.css"
161
162 table-sort-begin 'width60' # <body> <p>
163
164 # Put two parts side-by-side with flexbox
165 echo '
166 <style>
167 .side-by-side {
168 display: flex;
169 gap: 1em;
170
171 padding-left: 1em;
172 padding-right: 1em;
173 background-color: #eee;
174 }
175
176 .side-by-side section {
177 flex: 1;
178 }
179 </style>
180 '
181
182 cmark <<EOF
183<p id="home-link">
184 <a href="../index.html">Up</a> |
185 <a href="/">Home</a>
186</p>
187
188# $title
189
190EOF
191
192 diff-summary-html $base_dir/diff_merged.db
193
194 cmark << 'EOF'
195[tree](tree.html) &nbsp;&nbsp; [metrics](metrics.html) &nbsp;&nbsp; [disagree-packages.txt](disagree-packages.txt)
196
197## Notable OSH Disagreements
198
199<div style="color: #666;">
200
201(Hint: **click** on the cause column header to sort)
202
203</div>
204
205EOF
206
207 local name=notable_disagree
208 tsv2html3 $base_dir/$name.tsv
209
210 cmark <<EOF
211[$name.tsv]($name.tsv)
212
213## All Disagreements with Timeout
214EOF
215
216 local name=timeout_disagree
217 tsv2html3 $base_dir/$name.tsv
218
219 cmark <<EOF
220[$name.tsv]($name.tsv)
221
222## Baseline-Only Failures
223EOF
224
225 name=baseline_only
226 table-sort-begin 'width60'
227 tsv2html3 $base_dir/$name.tsv
228
229 cmark <<EOF
230
231[$name.tsv]($name.tsv)
232
233## Both Timed Out
234EOF
235
236 name=both_timeout
237 table-sort-begin 'width60'
238 tsv2html3 $base_dir/$name.tsv
239
240 cmark <<EOF
241
242[$name.tsv]($name.tsv)
243
244## Both Failed
245EOF
246
247 name=both_fail
248 table-sort-begin 'width60'
249 tsv2html3 $base_dir/$name.tsv
250
251 cmark <<EOF
252[$name.tsv]($name.tsv)
253
254EOF
255
256 # Sort these tables
257 table-sort-end-many \
258 notable_disagree timeout_disagree baseline_only both_fail both_timeout
259}
260
261tasks-html() {
262 local tsv=$1
263 # note: escaping problems with title
264 # it gets interpolated into markdown and html
265 local title=$2
266
267 local base_url='../../../../../web'
268 html-head --title "$title" \
269 "$base_url/ajax.js" \
270 "$base_url/table/table-sort.js" \
271 "$base_url/table/table-sort.css" \
272 "$base_url/base.css"
273
274 table-sort-begin 'width60'
275
276 cmark <<EOF
277<p id="home-link">
278 <a href="../index.html">Up</a> |
279 <a href="/">Home</a>
280</p>
281
282# $title
283EOF
284
285 tsv2html3 $tsv
286
287 local id=$(basename $tsv .tsv)
288 cmark <<EOF
289
290[$id.tsv]($id.tsv)
291EOF
292
293 table-sort-end "$id" # ID for sorting
294}
295
296published-html() {
297 local base_url='../../web'
298
299 local title='regtest/aports'
300
301 html-head --title "$title" \
302 "$base_url/base.css"
303
304 echo '
305 <body class="width35">
306 <style>
307 code { color: green; }
308 </style>
309
310 <p id="home-link">
311 <a href="/">Home</a> |
312 <a href="https://oils.pub/">oils.pub</a>
313 </p>
314 '
315
316 { echo "## $title"
317 echo '
318Testing OSH on decades worth of shell scripts. [Source code](https://github.com/oils-for-unix/oils/tree/master/regtest).
319
320The `aports/main` repo has 1595 `APKBUILD` files, and `aports/community` has
3217168. A disagreement is when the package succeeds normally, but fails when
322`osh` becomes the system shell. Caveats: timeouts and flakiness.
323
324### main
325
326- [2025-08-07-fix](2025-08-07-fix.wwz/_tmp/aports-report/2025-08-07-fix/diff_merged.html) - **131** disagreements
327- [2025-08-14-fix](2025-08-14-fix.wwz/_tmp/aports-report/2025-08-14-fix/diff_merged.html)
328- [2025-08-26-ifs](2025-08-26-ifs.wwz/_tmp/aports-report/2025-08-26-ifs/diff_merged.html) - **62** after `IFS` fix
329 - new causes: [2025-09-06-edit](2025-09-06-edit.wwz/_tmp/aports-report/2025-09-06-edit/diff_merged.html)
330- [2025-09-07](2025-09-07.wwz/_tmp/aports-report/2025-09-07/diff_merged.html)
331- [2025-09-08](2025-09-08.wwz/_tmp/aports-report/2025-09-08/diff_merged.html)
332 - [2025-09-08-edit](2025-09-08-edit.wwz/_tmp/aports-report/2025-09-08-edit/diff_merged.html)
333 - [2025-09-08-notable](2025-09-08-notable.wwz/_tmp/aports-report/2025-09-08-notable/diff_merged.html)
334- [2025-09-10-overlayfs](2025-09-10-overlayfs.wwz/_tmp/aports-report/2025-09-10-overlayfs/diff_merged.html)
335- [2025-09-11-match](2025-09-11-match.wwz/_tmp/aports-report/2025-09-11-match/diff_merged.html)
336- [2025-09-15-order](2025-09-15-order.wwz/_tmp/aports-report/2025-09-15-order/diff_merged.html) - **32** disagreements with `osh` as `/bin/sh`
337
338After this success, we expanded our testing:
339
340- [2025-09-17-ash2](2025-09-17-ash2.wwz/_tmp/aports-report/2025-09-17-ash2/diff_merged.html) - **37**, after adding `osh` as `/bin/ash`
341- [2025-09-18-bash](2025-09-18-bash.wwz/_tmp/aports-report/2025-09-18-bash/diff_merged.html) - **43**, after adding `osh` as `/bin/bash`
342 - only run on packages that disagree: [2025-09-27-disagree](2025-09-27-disagree.wwz/_tmp/aports-report/2025-09-27-disagree/diff_merged.html)
343 - new causes: [2025-10-03-causes](2025-10-03-causes.wwz/_tmp/aports-report/2025-10-03-causes/diff_merged.html)
344- [2025-10-15-main](2025-10-15-main.wwz/_tmp/aports-report/2025-10-15-main/diff_merged.html) - **38** disagreements
345 - [2025-10-16](2025-10-16.wwz/_tmp/aports-report/2025-10-16/diff_merged.html) - down to **35** after `x=1>` and `cd x y` fixes
346 - [2025-10-22](2025-10-22.wwz/_tmp/aports-report/2025-10-22/diff_merged.html) - down to **24** after `((` and `$(false)` fixes
347 - [2025-10-26-cause](2025-10-26-cause.wwz/_tmp/aports-report/2025-10-26-cause/diff_merged.html) - updated causes
348 - [2025-11-01-main-cause](2025-11-01-main-cause.wwz/_tmp/aports-report/2025-11-01-main-cause/diff_merged.html) - updated causes
349 - [2025-11-01-main-again](2025-11-01-main-again.wwz/_tmp/aports-report/2025-11-01-main-again/diff_merged.html) - **18** disagreements
350 - [2025-11-02-main-patch](2025-11-02-main-patch.wwz/_tmp/aports-report/2025-11-02-main-patch/diff_merged.html) - **14** disagreements
351 - [2025-11-09-main-cause](2025-11-09-main-cause.wwz/_tmp/aports-report/2025-11-09-main-cause/diff_merged.html) - updated causes
352- [2025-11-11-main-full](2025-11-11-main-full.wwz/_tmp/aports-report/2025-11-11-main-full/diff_merged.html) - full run with 10 package builds in parallel, 2 cores each
353
354### community
355
356- [2025-10-08-comm](2025-10-08-comm.wwz/_tmp/aports-report/2025-10-08-comm/diff_merged.html) - **86** disagreements
357 - [2025-10-16-comm-disagree](2025-10-16-comm-disagree.wwz/_tmp/aports-report/2025-10-16-comm-disagree/diff_merged.html) - **71** disagreements
358 - [2025-10-22-comm](2025-10-22-comm.wwz/_tmp/aports-report/2025-10-22-comm/diff_merged.html) - down to **65** after `((` and `$(false)` fixes
359 - [2025-10-26-comm-cause](2025-10-26-comm-cause.wwz/_tmp/aports-report/2025-10-26-comm-cause/diff_merged.html) - updated causes
360 - [2025-11-01-comm-cause](2025-11-01-comm-cause.wwz/_tmp/aports-report/2025-11-01-comm-cause/diff_merged.html) - updated causes
361 - [2025-11-02-comm-patch](2025-11-02-comm-patch.wwz/_tmp/aports-report/2025-11-02-comm-patch/diff_merged.html) - **64** disagreements, **45** of unknown cause
362 - [2025-11-09-comm-cause](2025-11-09-comm-cause.wwz/_tmp/aports-report/2025-11-09-comm-cause/diff_merged.html) - updated causes, **20** of unknown cause
363
364';
365 } | cmark
366
367 echo '
368 </body>
369</html>
370'
371}
372
373typed-tsv-to-sql() {
374 local tsv=${1:-$BASE_DIR/big/tasks.tsv}
375 local name
376 name=${2:-$(basename $tsv .tsv)}
377
378 local schema="${tsv%'.tsv'}.schema.tsv"
379 #echo $name $schema
380
381 echo "CREATE TABLE $name ("
382 web/table/schema2sqlite.py $schema
383 echo ');'
384
385 echo "
386-- use this temp import because we already created the table, and
387-- '.headers on' is not expected in that case
388
389.import $tsv temp_import
390insert into $name select * from temp_import;
391drop table temp_import;
392
393-- select * from $name limit 5;
394 "
395}
396
397my-rsync() {
398 #rsync --archive --verbose --dry-run "$@"
399 rsync --archive --verbose "$@"
400}
401
402readonly EPOCH=${EPOCH:-'2025-07-28-100'}
403readonly BUILD_HOST=he.oils.pub
404#readonly BUILD_HOST=lenny.local
405
406sync-results() {
407 local host=${1:-$BUILD_HOST}
408 local prefix=${2:-}
409 mkdir -p $REPORT_DIR
410
411 # Exclude .apk files, because they are large. We only need the metadata
412 my-rsync \
413 --exclude '*.apk' \
414 "$host:~/git/oils-for-unix/oils/_tmp/aports-build/$prefix*" \
415 $REPORT_DIR/
416}
417
418local-sync() {
419 mkdir -p $REPORT_DIR
420
421 #my-rsync --dry-run $BASE_DIR/ $REPORT_DIR/
422 my-rsync $BASE_DIR/ $REPORT_DIR/
423}
424
425make-package-table() {
426 local base_dir=${1:-$REPORT_DIR/$EPOCH}
427 local config=${2:-baseline}
428
429 local db=$PWD/$base_dir/$config/tables.db
430 rm -f $db
431
432 typed-tsv-to-sql $base_dir/$config/tasks.tsv | sqlite-tabs-headers $db
433
434 sqlite3 -cmd '.mode columns' $db < regtest/aports/tasks.sql
435
436 pushd $base_dir/$config > /dev/null
437
438 db-to-tsv $db packages
439
440 # Set precision
441 echo "
442 alter table packages_schema add column precision;
443
444 update packages_schema set precision = 1 where column_name = 'elapsed_secs';
445 update packages_schema set precision = 1 where column_name = 'user_elapsed_ratio';
446 update packages_schema set precision = 1 where column_name = 'user_sys_ratio';
447 update packages_schema set precision = 1 where column_name = 'max_rss_MB';
448 " | sqlite3 $db
449
450 # Count .apk for this config
451 # Note: we could also create an 'apk' table, in addition to 'packages', and diff
452 # But that's a bunch of overhead
453
454 local num_apk
455 num_apk=$(cat apk.txt | wc -l)
456
457 sqlite3 $db >metrics.txt <<EOF
458update metrics
459set num_apk = $num_apk
460where id = 1;
461
462.mode column
463select * from metrics;
464EOF
465
466 popd > /dev/null
467
468 #cat $base_dir/$config/packages.schema.tsv
469}
470
471tasks-schema() {
472 here-schema-tsv-4col <<EOF
473column_name type precision strftime
474status integer 0 -
475elapsed_secs float 1 -
476start_time float 1 %H:%M:%S
477end_time float 1 %H:%M:%S
478user_secs float 1 -
479sys_secs float 1 -
480max_rss_KiB integer 0 -
481xargs_slot integer 0 -
482pkg string 0 -
483pkg_HREF string 0 -
484EOF
485}
486
487write-tables-for-config() {
488 local base_dir=${1:-$REPORT_DIR/$EPOCH}
489 local config=${2:-baseline}
490
491 local tasks_tsv=$base_dir/$config/tasks.tsv
492 mkdir -p $base_dir/$config
493
494 tasks-schema >$base_dir/$config/tasks.schema.tsv
495
496 local out=$base_dir/$config/tasks.html
497 tasks-html $tasks_tsv "tasks: $config" > $out
498 log "Wrote $out"
499
500 make-package-table "$base_dir" "$config"
501
502 local packages_tsv=$base_dir/$config/packages.tsv
503
504 local out=$base_dir/$config/packages.html
505 tasks-html $packages_tsv "packages: $config" > $out
506 log "Wrote $out"
507}
508
509make-diff-db() {
510 local base_dir=$1
511 local name=${2:-diff_baseline}
512
513 local db=$name.db
514
515 local diff_sql=$PWD/regtest/aports/diff.sql
516 local cause_awk=$PWD/regtest/aports/cause.awk
517 local cause_sql=$PWD/regtest/aports/cause.sql
518
519 pushd $base_dir > /dev/null
520
521 rm -f $db
522 sqlite3 $db < $diff_sql
523
524 #
525 # Now make diffs
526 #
527
528 sqlite3 $db >failed-packages.txt <<EOF
529.mode tabs
530-- this is a text file, so headers are OFF
531.headers off
532
533select pkg from diff_baseline;
534EOF
535
536 mkdir -p error
537 cat failed-packages.txt | while read -r pkg; do
538 #local left=baseline/log/$pkg.log.txt
539 local right=osh-as-sh/log/$pkg.log.txt
540
541 # lower case 'error fail' are more noisy, e.g. command line flags
542 egrep 'Error|ERROR|Fail|FAIL|test-suite.log' $right > error/$pkg.txt || true
543 done
544
545 { echo "pkg${TAB}cause${TAB}suite${TAB}suite_HREF"
546 cat failed-packages.txt | while read -r pkg; do
547 local right=osh-as-sh/log/$pkg.log.txt
548
549 local cause
550 cause=$(awk -f $cause_awk $right)
551
552 local suite=''
553 local suite_HREF=''
554 local suite_path="osh-as-sh/test-suite/$pkg/test-suite.log.txt"
555 if test -f "$suite_path"; then
556 suite='suite'
557 suite_HREF=$suite_path # shard added in regtest/aports/merge.sql
558 fi
559
560 echo "${pkg}${TAB}${cause}${TAB}${suite}${TAB}${suite_HREF}"
561 done
562 } > causes.tsv
563
564 # Import causes.tsv and add columns
565 sqlite-tabs-headers \
566 -cmd '.import causes.tsv causes' \
567 $db < $cause_sql
568
569 # The DB is diff_baseline.db, with table diff_baseline
570 db-to-tsv $db diff_baseline
571
572 popd > /dev/null
573}
574
575db-to-tsv() {
576 local db=$1
577 local table_name=$2
578 local order_by=${3:-}
579
580 echo "
581 select * from ${table_name} ${order_by};
582 " | sqlite-tabs-headers $db >$table_name.tsv
583
584 echo "
585 create table ${table_name}_schema as
586 select
587 name as column_name,
588 case
589 when UPPER(type) like '%INT%' then 'integer'
590 when UPPER(type) = 'REAL' then 'float'
591 when UPPER(type) = 'TEXT' then 'string'
592 else LOWER(type)
593 end as type
594 from PRAGMA_TABLE_INFO('${table_name}');
595
596 select * from ${table_name}_schema;
597 " | sqlite-tabs-headers $db >$table_name.schema.tsv
598}
599
600merge-diffs-sql() {
601 local -a SHARDS=( "$@" )
602
603 local is_first_shard=T
604
605 # Now insert data from all the shards
606 for ((i=0; i<${#SHARDS[@]}; i++)); do
607 local shard_dir="${SHARDS[i]}"
608 shard_name=$(basename $shard_dir)
609
610 # Handle incomplete shard
611 if ! test -d $shard_dir/baseline || ! test -d $shard_dir/osh-as-sh; then
612 continue
613 fi
614
615 echo "ATTACH DATABASE '$shard_dir/diff_baseline.db' AS temp_shard;"
616
617 if test -n "$is_first_shard"; then
618 # Create table from first shard
619 echo "
620 CREATE TABLE diff_merged AS
621 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.diff_baseline where 1=0;
622
623 CREATE TABLE metrics AS
624 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.metrics where 1=0;
625 "
626 is_first_shard='' # don't create table next time
627 fi
628
629 # Now insert data
630 echo "
631 INSERT INTO diff_merged
632 SELECT *, '$shard_name' as shard FROM temp_shard.diff_baseline;
633
634 INSERT INTO metrics
635 SELECT *, '$shard_name' as shard FROM temp_shard.metrics;
636
637 DETACH DATABASE temp_shard;
638 "
639 done
640
641 # Does not involve metaprogramming
642 cat regtest/aports/merge.sql
643}
644
645merge-diffs() {
646 local epoch_dir=${1:-_tmp/aports-report/2025-10-15-main}
647 local do_disagree=${2:-}
648
649 local db=$PWD/$epoch_dir/diff_merged.db
650 rm -f $db
651
652 local -a shards
653 if test -n "$do_disagree"; then
654 # Hack: distinguish disagree-2025 from disagree-packages.txt
655 shards=( $epoch_dir/disagree-2* ) # Usually 1 shard
656 else
657 shards=( $epoch_dir/shard* )
658 fi
659
660 echo SHARDS "${shards[@]}"
661
662 merge-diffs-sql "${shards[@]}" | sqlite3 $db
663 #echo $db
664
665 # copied from above
666 pushd $epoch_dir > /dev/null
667
668 db-to-tsv $db diff_merged 'order by pkg'
669 db-to-tsv $db metrics
670
671 db-to-tsv $db notable_disagree 'order by pkg'
672 db-to-tsv $db timeout_disagree 'order by pkg'
673 db-to-tsv $db baseline_only 'order by pkg'
674 db-to-tsv $db both_fail 'order by pkg'
675 db-to-tsv $db both_timeout 'order by pkg'
676
677 db-to-tsv $db cause_hist
678
679 # For re-running failures
680 sqlite3 diff_merged.db >disagree-packages.txt <<EOF
681.headers off
682select pkg from diff_merged where disagree = 1 and timeout = 0;
683EOF
684 #wc -l disagree-packages.txt
685
686 popd > /dev/null
687
688 local title1='OSH Disagreements - regtest/aports'
689 local out=$epoch_dir/diff_merged.html
690 merge-diff-html $epoch_dir '../../../web' "$title1" > $out
691 echo "Wrote $out"
692
693 local name2=metrics
694 local title2='Metrics - regtest/aports'
695 local out=$epoch_dir/$name2.html
696 table-page-html $epoch_dir $name2 '../../../web' "$title2" > $out
697 echo "Wrote $out"
698
699 # After merging, regenerate other stuff too
700
701 html-tree "$epoch_dir"
702
703 update-published # also done in deploy-published
704}
705
706write-shard-reports() {
707 local base_dir=$1 # e.g. _tmp/aports-report/2025-08-02/shard3
708
709 index-html > $base_dir/index.html
710
711 for config in baseline osh-as-sh; do
712 # Incomplete shard
713 if ! test -d "$base_dir/$config"; then
714 return
715 fi
716 write-tables-for-config "$base_dir" "$config"
717 done
718
719 local name=diff_baseline
720 local title="$base_dir differences"
721 make-diff-db $base_dir
722 table-page-html $base_dir $name '' "$title" > $base_dir/$name.html
723 echo "Wrote $base_dir/$name.html"
724}
725
726write-all-reports() {
727 local epoch_dir=${1:-_tmp/aports-report/2025-08-03}
728
729 for shard_dir in $epoch_dir/shard*; do
730 write-shard-reports "$shard_dir"
731 done
732
733 merge-diffs "$epoch_dir"
734}
735
736write-disagree-reports() {
737 local epoch_dir=${1:-_tmp/aports-build/2025-09-27}
738
739 # Hack: distinguish disagree-2025 from disagree-packages.txt
740 for shard_dir in $epoch_dir/disagree-2*; do
741 write-shard-reports "$shard_dir"
742 done
743
744 merge-diffs "$epoch_dir" T
745}
746
747html-tree() {
748 local epoch_dir=${1:-_tmp/aports-report/2025-08-07-fix}
749
750 local epoch
751 epoch=$(basename $epoch_dir)
752
753 pushd $epoch_dir
754 # -L 3 goes 3 levels deeps, omitting logs
755 tree \
756 -H './' \
757 -T "regtest/aports - $epoch" \
758 -L 3 \
759 --charset=ascii \
760 > tree.html
761 popd
762
763 echo "Wrote $epoch_dir/tree.html"
764}
765
766update-published() {
767 local out=$REPORT_DIR/published.html
768 published-html > $out
769 echo "Wrote $out"
770}
771
772remove-apk() {
773 local base_dir=${1:-$REPORT_DIR/2025-09-07}
774 # temporary
775
776 find $base_dir -name '*.apk' -o -name 'APKINDEX*' | xargs -d $'\n' --verbose -- rm -v
777}
778
779make-wwz() {
780 local base_dir=${1:-$REPORT_DIR/2025-08-03}
781
782 # must not end with slash
783 base_dir=${base_dir%'/'}
784
785 local wwz=$base_dir.wwz
786 rm -f -v $wwz
787
788 zip -r $wwz $base_dir web/
789
790 echo "Wrote $wwz"
791}
792
793readonly WEB_HOST=op.oils.pub
794
795deploy-wwz-op() {
796 local wwz=${1:-$REPORT_DIR/2025-08-03.wwz}
797
798 local dest_dir=$WEB_HOST/aports-build
799
800 update-published # slightly redundant
801
802 ssh $WEB_HOST mkdir -p $dest_dir
803
804 scp $wwz $REPORT_DIR/published.html \
805 $WEB_HOST:$dest_dir/
806
807 echo "Visit https://$dest_dir/published.html"
808 echo " https://$dest_dir/$(basename $wwz)/"
809}
810
811deploy-published() {
812 local dest_dir=$WEB_HOST/aports-build
813
814 update-published # slightly redundant
815
816 scp $REPORT_DIR/published.html \
817 $WEB_HOST:$dest_dir/
818
819 echo "Visit https://$dest_dir/published.html"
820}
821
822#
823# For editing
824#
825
826readonly EDIT_DIR=_tmp/aports-edit
827
828readonly EDITING_APORTS_EPOCH='2025-11-02-main-patch.wwz'
829
830sync-old-wwz() {
831 local wwz=${1:-$EDITING_APORTS_EPOCH}
832
833 mkdir -p $EDIT_DIR
834 rm -f -v $EDIT_DIR/$wwz
835
836 wget --directory-prefix $EDIT_DIR \
837 "https://$WEB_HOST/aports-build/$wwz"
838
839 ls -l $EDIT_DIR
840 #echo "Wrote $wwz"
841}
842
843extract-old-wwz() {
844 local new_epoch=$1
845 local wwz=${2:-$EDITING_APORTS_EPOCH}
846
847 # Extract the whole thing into a temp dir
848 local tmp_dir=$EDIT_DIR/$new_epoch
849 rm -r -f $tmp_dir
850 mkdir -p $tmp_dir
851
852 pushd $tmp_dir
853 unzip ../$wwz
854 popd
855
856 # Now re-create the old structure under _tmp/aports-report/2025-09-06-edit
857
858 local dest_dir=$REPORT_DIR/$new_epoch
859 mkdir -p $dest_dir
860
861 local old_epoch
862 old_epoch=$(basename $wwz .wwz)
863 mv -v --no-target-directory $tmp_dir/_tmp/aports-report/$old_epoch $dest_dir
864}
865
866rebuild-both() {
867 for a_repo in main comm; do
868 local old=2025-11-02-${a_repo}-patch.wwz
869 sync-old-wwz $old
870 local new=2025-11-09-${a_repo}-cause
871
872 rm -r -f _tmp/aports-report/$new
873
874 extract-old-wwz $new $old
875
876 write-disagree-reports _tmp/aports-report/$new
877
878 make-wwz _tmp/aports-report/$new
879
880 deploy-wwz-op _tmp/aports-report/$new.wwz
881 done
882}
883
884#
885# Dev tools
886#
887
888out-of-vm() {
889 local dest=~/vm-shared/$EPOCH
890 mkdir -p $dest
891 cp $REPORT_DIR/$EPOCH.wwz $dest
892 pushd ~/vm-shared/$EPOCH
893 unzip $EPOCH.wwz
894 popd
895}
896
897task-five "$@"