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

885 lines, 388 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## All Notable 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
212[$name.tsv]($name.tsv)
213
214## Baseline-Only Failures
215EOF
216
217 name=baseline_only
218 table-sort-begin 'width60'
219 tsv2html3 $base_dir/$name.tsv
220
221 cmark <<EOF
222[$name.tsv]($name.tsv)
223
224## Other Failures
225EOF
226
227 name=other_fail
228 table-sort-begin 'width60'
229 tsv2html3 $base_dir/$name.tsv
230
231 cmark <<EOF
232
233[$name.tsv]($name.tsv)
234
235## Timeouts
236EOF
237
238 name=timeout
239 table-sort-begin 'width60'
240 tsv2html3 $base_dir/$name.tsv
241
242 cmark <<EOF
243
244[$name.tsv]($name.tsv)
245EOF
246
247 # Sort these 3 tables
248 table-sort-end-many notable_disagree baseline_only other_fail timeout
249}
250
251tasks-html() {
252 local tsv=$1
253 # note: escaping problems with title
254 # it gets interpolated into markdown and html
255 local title=$2
256
257 local base_url='../../../../../web'
258 html-head --title "$title" \
259 "$base_url/ajax.js" \
260 "$base_url/table/table-sort.js" \
261 "$base_url/table/table-sort.css" \
262 "$base_url/base.css"
263
264 table-sort-begin 'width60'
265
266 cmark <<EOF
267<p id="home-link">
268 <a href="../index.html">Up</a> |
269 <a href="/">Home</a>
270</p>
271
272# $title
273EOF
274
275 tsv2html3 $tsv
276
277 local id=$(basename $tsv .tsv)
278 cmark <<EOF
279
280[$id.tsv]($id.tsv)
281EOF
282
283 table-sort-end "$id" # ID for sorting
284}
285
286published-html() {
287 local base_url='../../web'
288
289 local title='regtest/aports'
290
291 html-head --title "$title" \
292 "$base_url/base.css"
293
294 echo '
295 <body class="width35">
296 <style>
297 code { color: green; }
298 </style>
299
300 <p id="home-link">
301 <a href="/">Home</a> |
302 <a href="https://oils.pub/">oils.pub</a>
303 </p>
304 '
305
306 { echo "## $title"
307 echo '
308Testing OSH on decades worth of shell scripts. [Source code](https://github.com/oils-for-unix/oils/tree/master/regtest).
309
310The `aports/main` repo has 1595 `APKBUILD` files, and `aports/community` has
3117168. A disagreement is when the package succeeds normally, but fails when
312`osh` becomes the system shell. Caveats: timeouts and flakiness.
313
314### main
315
316- [2025-08-07-fix](2025-08-07-fix.wwz/_tmp/aports-report/2025-08-07-fix/diff_merged.html) - **131** disagreements
317- [2025-08-14-fix](2025-08-14-fix.wwz/_tmp/aports-report/2025-08-14-fix/diff_merged.html)
318- [2025-08-26-ifs](2025-08-26-ifs.wwz/_tmp/aports-report/2025-08-26-ifs/diff_merged.html) - **62** after `IFS` fix
319 - new causes: [2025-09-06-edit](2025-09-06-edit.wwz/_tmp/aports-report/2025-09-06-edit/diff_merged.html)
320- [2025-09-07](2025-09-07.wwz/_tmp/aports-report/2025-09-07/diff_merged.html)
321- [2025-09-08](2025-09-08.wwz/_tmp/aports-report/2025-09-08/diff_merged.html)
322 - [2025-09-08-edit](2025-09-08-edit.wwz/_tmp/aports-report/2025-09-08-edit/diff_merged.html)
323 - [2025-09-08-notable](2025-09-08-notable.wwz/_tmp/aports-report/2025-09-08-notable/diff_merged.html)
324- [2025-09-10-overlayfs](2025-09-10-overlayfs.wwz/_tmp/aports-report/2025-09-10-overlayfs/diff_merged.html)
325- [2025-09-11-match](2025-09-11-match.wwz/_tmp/aports-report/2025-09-11-match/diff_merged.html)
326- [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`
327
328After this success, we expanded our testing:
329
330- [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`
331- [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`
332 - 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)
333 - new causes: [2025-10-03-causes](2025-10-03-causes.wwz/_tmp/aports-report/2025-10-03-causes/diff_merged.html)
334- [2025-10-15-main](2025-10-15-main.wwz/_tmp/aports-report/2025-10-15-main/diff_merged.html) - **38** disagreements
335 - [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
336 - [2025-10-22](2025-10-22.wwz/_tmp/aports-report/2025-10-22/diff_merged.html) - down to **24** after `((` and `$(false)` fixes
337 - [2025-10-26-cause](2025-10-26-cause.wwz/_tmp/aports-report/2025-10-26-cause/diff_merged.html) - updated causes
338 - [2025-11-01-main-cause](2025-11-01-main-cause.wwz/_tmp/aports-report/2025-11-01-main-cause/diff_merged.html) - updated causes
339 - [2025-11-01-main-again](2025-11-01-main-again.wwz/_tmp/aports-report/2025-11-01-main-again/diff_merged.html) - **18** disagreements
340 - [2025-11-02-main-patch](2025-11-02-main-patch.wwz/_tmp/aports-report/2025-11-02-main-patch/diff_merged.html) - **14** disagreements
341 - [2025-11-09-main-cause](2025-11-09-main-cause.wwz/_tmp/aports-report/2025-11-09-main-cause/diff_merged.html) - updated causes
342
343### community
344
345- [2025-10-08-comm](2025-10-08-comm.wwz/_tmp/aports-report/2025-10-08-comm/diff_merged.html) - **86** disagreements
346 - [2025-10-16-comm-disagree](2025-10-16-comm-disagree.wwz/_tmp/aports-report/2025-10-16-comm-disagree/diff_merged.html) - **71** disagreements
347 - [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
348 - [2025-10-26-comm-cause](2025-10-26-comm-cause.wwz/_tmp/aports-report/2025-10-26-comm-cause/diff_merged.html) - updated causes
349 - [2025-11-01-comm-cause](2025-11-01-comm-cause.wwz/_tmp/aports-report/2025-11-01-comm-cause/diff_merged.html) - updated causes
350 - [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
351 - [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
352
353';
354 } | cmark
355
356 echo '
357 </body>
358</html>
359'
360}
361
362typed-tsv-to-sql() {
363 local tsv=${1:-$BASE_DIR/big/tasks.tsv}
364 local name
365 name=${2:-$(basename $tsv .tsv)}
366
367 local schema="${tsv%'.tsv'}.schema.tsv"
368 #echo $name $schema
369
370 echo "CREATE TABLE $name ("
371 web/table/schema2sqlite.py $schema
372 echo ');'
373
374 echo "
375-- use this temp import because we already created the table, and
376-- '.headers on' is not expected in that case
377
378.import $tsv temp_import
379insert into $name select * from temp_import;
380drop table temp_import;
381
382-- select * from $name limit 5;
383 "
384}
385
386my-rsync() {
387 #rsync --archive --verbose --dry-run "$@"
388 rsync --archive --verbose "$@"
389}
390
391readonly EPOCH=${EPOCH:-'2025-07-28-100'}
392readonly BUILD_HOST=he.oils.pub
393#readonly BUILD_HOST=lenny.local
394
395sync-results() {
396 local host=${1:-$BUILD_HOST}
397 local prefix=${2:-}
398 mkdir -p $REPORT_DIR
399
400 # Exclude .apk files, because they are large. We only need the metadata
401 my-rsync \
402 --exclude '*.apk' \
403 "$host:~/git/oils-for-unix/oils/_tmp/aports-build/$prefix*" \
404 $REPORT_DIR/
405}
406
407local-sync() {
408 mkdir -p $REPORT_DIR
409
410 #my-rsync --dry-run $BASE_DIR/ $REPORT_DIR/
411 my-rsync $BASE_DIR/ $REPORT_DIR/
412}
413
414make-package-table() {
415 local base_dir=${1:-$REPORT_DIR/$EPOCH}
416 local config=${2:-baseline}
417
418 local db=$PWD/$base_dir/$config/tables.db
419 rm -f $db
420
421 typed-tsv-to-sql $base_dir/$config/tasks.tsv | sqlite-tabs-headers $db
422
423 sqlite3 -cmd '.mode columns' $db < regtest/aports/tasks.sql
424
425 pushd $base_dir/$config > /dev/null
426
427 db-to-tsv $db packages
428
429 # Set precision
430 echo "
431 alter table packages_schema add column precision;
432
433 update packages_schema set precision = 1 where column_name = 'elapsed_secs';
434 update packages_schema set precision = 1 where column_name = 'user_elapsed_ratio';
435 update packages_schema set precision = 1 where column_name = 'user_sys_ratio';
436 update packages_schema set precision = 1 where column_name = 'max_rss_MB';
437 " | sqlite3 $db
438
439 # Count .apk for this config
440 # Note: we could also create an 'apk' table, in addition to 'packages', and diff
441 # But that's a bunch of overhead
442
443 local num_apk
444 num_apk=$(cat apk.txt | wc -l)
445
446 sqlite3 $db >metrics.txt <<EOF
447update metrics
448set num_apk = $num_apk
449where id = 1;
450
451.mode column
452select * from metrics;
453EOF
454
455 popd > /dev/null
456
457 #cat $base_dir/$config/packages.schema.tsv
458}
459
460tasks-schema() {
461 here-schema-tsv-4col <<EOF
462column_name type precision strftime
463status integer 0 -
464elapsed_secs float 1 -
465start_time float 1 %H:%M:%S
466end_time float 1 %H:%M:%S
467user_secs float 1 -
468sys_secs float 1 -
469max_rss_KiB integer 0 -
470xargs_slot integer 0 -
471pkg string 0 -
472pkg_HREF string 0 -
473EOF
474}
475
476write-tables-for-config() {
477 local base_dir=${1:-$REPORT_DIR/$EPOCH}
478 local config=${2:-baseline}
479
480 local tasks_tsv=$base_dir/$config/tasks.tsv
481 mkdir -p $base_dir/$config
482
483 tasks-schema >$base_dir/$config/tasks.schema.tsv
484
485 local out=$base_dir/$config/tasks.html
486 tasks-html $tasks_tsv "tasks: $config" > $out
487 log "Wrote $out"
488
489 make-package-table "$base_dir" "$config"
490
491 local packages_tsv=$base_dir/$config/packages.tsv
492
493 local out=$base_dir/$config/packages.html
494 tasks-html $packages_tsv "packages: $config" > $out
495 log "Wrote $out"
496}
497
498make-diff-db() {
499 local base_dir=$1
500 local name=${2:-diff_baseline}
501
502 local db=$name.db
503
504 local diff_sql=$PWD/regtest/aports/diff.sql
505 local cause_awk=$PWD/regtest/aports/cause.awk
506 local cause_sql=$PWD/regtest/aports/cause.sql
507
508 pushd $base_dir > /dev/null
509
510 rm -f $db
511 sqlite3 $db < $diff_sql
512
513 #
514 # Now make diffs
515 #
516
517 sqlite3 $db >failed-packages.txt <<EOF
518.mode tabs
519-- this is a text file, so headers are OFF
520.headers off
521
522select pkg from diff_baseline;
523EOF
524
525 mkdir -p error
526 cat failed-packages.txt | while read -r pkg; do
527 #local left=baseline/log/$pkg.log.txt
528 local right=osh-as-sh/log/$pkg.log.txt
529
530 # lower case 'error fail' are more noisy, e.g. command line flags
531 egrep 'Error|ERROR|Fail|FAIL|test-suite.log' $right > error/$pkg.txt || true
532 done
533
534 { echo "pkg${TAB}cause${TAB}suite${TAB}suite_HREF"
535 cat failed-packages.txt | while read -r pkg; do
536 local right=osh-as-sh/log/$pkg.log.txt
537
538 local cause
539 cause=$(awk -f $cause_awk $right)
540
541 local suite=''
542 local suite_HREF=''
543 local suite_path="osh-as-sh/test-suite/$pkg/test-suite.log.txt"
544 if test -f "$suite_path"; then
545 suite='suite'
546 suite_HREF=$suite_path # shard added in regtest/aports/merge.sql
547 fi
548
549 echo "${pkg}${TAB}${cause}${TAB}${suite}${TAB}${suite_HREF}"
550 done
551 } > causes.tsv
552
553 # Import causes.tsv and add columns
554 sqlite-tabs-headers \
555 -cmd '.import causes.tsv causes' \
556 $db < $cause_sql
557
558 # The DB is diff_baseline.db, with table diff_baseline
559 db-to-tsv $db diff_baseline
560
561 popd > /dev/null
562}
563
564db-to-tsv() {
565 local db=$1
566 local table_name=$2
567 local order_by=${3:-}
568
569 echo "
570 select * from ${table_name} ${order_by};
571 " | sqlite-tabs-headers $db >$table_name.tsv
572
573 echo "
574 create table ${table_name}_schema as
575 select
576 name as column_name,
577 case
578 when UPPER(type) like '%INT%' then 'integer'
579 when UPPER(type) = 'REAL' then 'float'
580 when UPPER(type) = 'TEXT' then 'string'
581 else LOWER(type)
582 end as type
583 from PRAGMA_TABLE_INFO('${table_name}');
584
585 select * from ${table_name}_schema;
586 " | sqlite-tabs-headers $db >$table_name.schema.tsv
587}
588
589merge-diffs-sql() {
590 local -a SHARDS=( "$@" )
591
592 local is_first_shard=T
593
594 # Now insert data from all the shards
595 for ((i=0; i<${#SHARDS[@]}; i++)); do
596 local shard_dir="${SHARDS[i]}"
597 shard_name=$(basename $shard_dir)
598
599 # Handle incomplete shard
600 if ! test -d $shard_dir/baseline || ! test -d $shard_dir/osh-as-sh; then
601 continue
602 fi
603
604 echo "ATTACH DATABASE '$shard_dir/diff_baseline.db' AS temp_shard;"
605
606 if test -n "$is_first_shard"; then
607 # Create table from first shard
608 echo "
609 CREATE TABLE diff_merged AS
610 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.diff_baseline where 1=0;
611
612 CREATE TABLE metrics AS
613 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.metrics where 1=0;
614 "
615 is_first_shard='' # don't create table next time
616 fi
617
618 # Now insert data
619 echo "
620 INSERT INTO diff_merged
621 SELECT *, '$shard_name' as shard FROM temp_shard.diff_baseline;
622
623 INSERT INTO metrics
624 SELECT *, '$shard_name' as shard FROM temp_shard.metrics;
625
626 DETACH DATABASE temp_shard;
627 "
628 done
629
630 # Does not involve metaprogramming
631 cat regtest/aports/merge.sql
632}
633
634merge-diffs() {
635 local epoch_dir=${1:-_tmp/aports-report/2025-10-15-main}
636 local do_disagree=${2:-}
637
638 local db=$PWD/$epoch_dir/diff_merged.db
639 rm -f $db
640
641 local -a shards
642 if test -n "$do_disagree"; then
643 # Hack: distinguish disagree-2025 from disagree-packages.txt
644 shards=( $epoch_dir/disagree-2* ) # Usually 1 shard
645 else
646 shards=( $epoch_dir/shard* )
647 fi
648
649 echo SHARDS "${shards[@]}"
650
651 merge-diffs-sql "${shards[@]}" | sqlite3 $db
652 #echo $db
653
654 # copied from above
655 pushd $epoch_dir > /dev/null
656
657 db-to-tsv $db diff_merged 'order by pkg'
658 db-to-tsv $db metrics
659
660 db-to-tsv $db notable_disagree 'order by pkg'
661 db-to-tsv $db baseline_only 'order by pkg'
662 db-to-tsv $db other_fail 'order by pkg'
663 db-to-tsv $db timeout 'order by pkg'
664
665 db-to-tsv $db cause_hist
666
667 # For re-running failures
668 sqlite3 diff_merged.db >disagree-packages.txt <<EOF
669.headers off
670select pkg from diff_merged where disagree = 1 and timeout = 0;
671EOF
672 #wc -l disagree-packages.txt
673
674 popd > /dev/null
675
676 local title1='OSH Disagreements - regtest/aports'
677 local out=$epoch_dir/diff_merged.html
678 merge-diff-html $epoch_dir '../../../web' "$title1" > $out
679 echo "Wrote $out"
680
681 local name2=metrics
682 local title2='Metrics - regtest/aports'
683 local out=$epoch_dir/$name2.html
684 table-page-html $epoch_dir $name2 '../../../web' "$title2" > $out
685 echo "Wrote $out"
686
687 # After merging, regenerate other stuff too
688
689 html-tree "$epoch_dir"
690
691 update-published # also done in deploy-published
692}
693
694write-shard-reports() {
695 local base_dir=$1 # e.g. _tmp/aports-report/2025-08-02/shard3
696
697 index-html > $base_dir/index.html
698
699 for config in baseline osh-as-sh; do
700 # Incomplete shard
701 if ! test -d "$base_dir/$config"; then
702 return
703 fi
704 write-tables-for-config "$base_dir" "$config"
705 done
706
707 local name=diff_baseline
708 local title="$base_dir differences"
709 make-diff-db $base_dir
710 table-page-html $base_dir $name '' "$title" > $base_dir/$name.html
711 echo "Wrote $base_dir/$name.html"
712}
713
714write-all-reports() {
715 local epoch_dir=${1:-_tmp/aports-report/2025-08-03}
716
717 for shard_dir in $epoch_dir/shard*; do
718 write-shard-reports "$shard_dir"
719 done
720
721 merge-diffs "$epoch_dir"
722}
723
724write-disagree-reports() {
725 local epoch_dir=${1:-_tmp/aports-build/2025-09-27}
726
727 # Hack: distinguish disagree-2025 from disagree-packages.txt
728 for shard_dir in $epoch_dir/disagree-2*; do
729 write-shard-reports "$shard_dir"
730 done
731
732 merge-diffs "$epoch_dir" T
733}
734
735html-tree() {
736 local epoch_dir=${1:-_tmp/aports-report/2025-08-07-fix}
737
738 local epoch
739 epoch=$(basename $epoch_dir)
740
741 pushd $epoch_dir
742 # -L 3 goes 3 levels deeps, omitting logs
743 tree \
744 -H './' \
745 -T "regtest/aports - $epoch" \
746 -L 3 \
747 --charset=ascii \
748 > tree.html
749 popd
750
751 echo "Wrote $epoch_dir/tree.html"
752}
753
754update-published() {
755 local out=$REPORT_DIR/published.html
756 published-html > $out
757 echo "Wrote $out"
758}
759
760remove-apk() {
761 local base_dir=${1:-$REPORT_DIR/2025-09-07}
762 # temporary
763
764 find $base_dir -name '*.apk' -o -name 'APKINDEX*' | xargs -d $'\n' --verbose -- rm -v
765}
766
767make-wwz() {
768 local base_dir=${1:-$REPORT_DIR/2025-08-03}
769
770 # must not end with slash
771 base_dir=${base_dir%'/'}
772
773 local wwz=$base_dir.wwz
774 rm -f -v $wwz
775
776 zip -r $wwz $base_dir web/
777
778 echo "Wrote $wwz"
779}
780
781readonly WEB_HOST=op.oils.pub
782
783deploy-wwz-op() {
784 local wwz=${1:-$REPORT_DIR/2025-08-03.wwz}
785
786 local dest_dir=$WEB_HOST/aports-build
787
788 update-published # slightly redundant
789
790 ssh $WEB_HOST mkdir -p $dest_dir
791
792 scp $wwz $REPORT_DIR/published.html \
793 $WEB_HOST:$dest_dir/
794
795 echo "Visit https://$dest_dir/published.html"
796 echo " https://$dest_dir/$(basename $wwz)/"
797}
798
799deploy-published() {
800 local dest_dir=$WEB_HOST/aports-build
801
802 update-published # slightly redundant
803
804 scp $REPORT_DIR/published.html \
805 $WEB_HOST:$dest_dir/
806
807 echo "Visit https://$dest_dir/published.html"
808}
809
810#
811# For editing
812#
813
814readonly EDIT_DIR=_tmp/aports-edit
815
816readonly EDITING_APORTS_EPOCH='2025-11-02-main-patch.wwz'
817
818sync-old-wwz() {
819 local wwz=${1:-$EDITING_APORTS_EPOCH}
820
821 mkdir -p $EDIT_DIR
822 rm -f -v $EDIT_DIR/$wwz
823
824 wget --directory $EDIT_DIR \
825 "https://$WEB_HOST/aports-build/$wwz"
826
827 ls -l $EDIT_DIR
828 #echo "Wrote $wwz"
829}
830
831extract-old-wwz() {
832 local new_epoch=$1
833 local wwz=${2:-$EDITING_APORTS_EPOCH}
834
835 # Extract the whole thing into a temp dir
836 local tmp_dir=$EDIT_DIR/$new_epoch
837 rm -r -f $tmp_dir
838 mkdir -p $tmp_dir
839
840 pushd $tmp_dir
841 unzip ../$wwz
842 popd
843
844 # Now re-create the old structure under _tmp/aports-report/2025-09-06-edit
845
846 local dest_dir=$REPORT_DIR/$new_epoch
847 mkdir -p $dest_dir
848
849 local old_epoch
850 old_epoch=$(basename $wwz .wwz)
851 mv -v --no-target-directory $tmp_dir/_tmp/aports-report/$old_epoch $dest_dir
852}
853
854rebuild-both() {
855 for a_repo in main comm; do
856 local old=2025-11-02-${a_repo}-patch.wwz
857 sync-old-wwz $old
858 local new=2025-11-09-${a_repo}-cause
859
860 rm -r -f _tmp/aports-report/$new
861
862 extract-old-wwz $new $old
863
864 write-disagree-reports _tmp/aports-report/$new
865
866 make-wwz _tmp/aports-report/$new
867
868 deploy-wwz-op _tmp/aports-report/$new.wwz
869 done
870}
871
872#
873# Dev tools
874#
875
876out-of-vm() {
877 local dest=~/vm-shared/$EPOCH
878 mkdir -p $dest
879 cp $REPORT_DIR/$EPOCH.wwz $dest
880 pushd ~/vm-shared/$EPOCH
881 unzip $EPOCH.wwz
882 popd
883}
884
885task-five "$@"