You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

156 lines
6.6 KiB

#family_artifacts.tcl (G-103): emit punkbin-layout artifact copies + per-artifact
#toml metadata + sha1sums for the verified runtime kit family members.
#
#Deliberately run UNDER THE PLAIN FAMILY KIT itself (not the builder shell): the
#sha1 digests come from the kit's attached tcllib/tcllibc, so every emission run
#doubles as a proof that the family runtime executes real tooling self-contained.
#
#Artifact tier naming (G-103 naming decision): <workingname minus .exe>-r<N>.exe -
#immutable punkbin names; the -r<N> assembly revision comes from the invocation
#(-rev, suite option -Dfamilyrev). The emitted tree mirrors a punkbin platform
#folder: <outdir>/<artifact>.exe + <artifact>.toml + sha1sums.txt (punkbin
#format: '<sha1> *<filename>'). Publication to the real punkbin repo is a
#deliberate user step (copy + build_sha1sums.tcl there); it is DEFERRED per the
#goal notes until the family shape is accepted.
#
#args: -outdir <dir> -rev <N> -target <punkbin platform, e.g win32-x86_64>
# -suite <name> -tclpatch <patchlevel> -zig <version> -optimize <mode>
# -components {<name> <ver> ...} (attached battery versions, all variants)
# -bicomponents {<name> <ver> ...} (additional bi-only batteries)
# -provenance {<name> <uuid> ...} (source checkout uuids)
# -testreports <dir> (G-107 evidence summaries; optional)
# -kits {<variant> <workingexepath> ...}
proc fail {msg} {puts stderr "family_artifacts FAIL: $msg"; flush stderr; exit 1}
proc note {msg} {puts stdout "family_artifacts: $msg"; flush stdout}
array set opt {
-outdir {} -rev 1 -target {} -suite {} -tclpatch {} -zig {} -optimize {}
-components {} -bicomponents {} -provenance {} -testreports {} -kits {}
}
foreach {k v} $argv {
if {![info exists opt($k)]} {fail "unknown option '$k'"}
set opt($k) $v
}
foreach req {-outdir -target -suite -tclpatch -zig -optimize -components -kits} {
if {$opt($req) eq ""} {fail "missing required option $req"}
}
if {![string is integer -strict $opt(-rev)] || $opt(-rev) < 1} {fail "-rev must be a positive integer"}
if {[catch {package require sha1} sha1ver]} {
fail "package require sha1 failed under [info nameofexecutable] - the family kit must carry tcllib: $sha1ver"
}
proc toml_str {s} {
#basic toml string: escape backslash and double-quote (values here are names,
#versions, uuids, iso dates - no control chars expected)
return "\"[string map {\\ \\\\ \" \\\"} $s]\""
}
proc exe_split {name} {
#{root ext} splitting only a .exe suffix - dotted tcl patchlevels make
#[file rootname] wrong for extensionless (unix) artifact names
#(tclsh9.0.5-punk-r1 would truncate at the last version dot)
if {[string match -nocase "*.exe" $name]} {
return [list [string range $name 0 end-4] .exe]
}
return [list $name ""]
}
file mkdir $opt(-outdir)
set built [clock format [clock seconds] -format %Y-%m-%dT%H:%M:%SZ -timezone :UTC]
set sha1lines {}
set emitted {}
foreach {variant kitpath} $opt(-kits) {
set kitpath [file normalize $kitpath]
if {![file exists $kitpath]} {fail "kit exe not found: $kitpath"}
set working [file tail $kitpath]
lassign [exe_split $working] wroot wext
set artifact "$wroot-r$opt(-rev)$wext"
set dest [file join $opt(-outdir) $artifact]
file delete -force $dest
file copy $kitpath $dest
set sha1 [sha1::sha1 -hex -file $dest]
set size [file size $dest]
lappend sha1lines "$sha1 *$artifact"
set components $opt(-components)
if {$variant eq "punk-bi"} {lappend components {*}$opt(-bicomponents)}
set batteries {}
foreach {n v} $components {lappend batteries [toml_str "$n $v"]}
set m {}
lappend m "#punkshell runtime artifact metadata (G-103) - generated by family_artifacts.tcl"
lappend m "\[artifact\]"
lappend m "name = [toml_str $artifact]"
lappend m "class = \"runtime\""
lappend m "variant = [toml_str $variant]"
lappend m "working_name = [toml_str $working]"
lappend m "revision = $opt(-rev)"
lappend m "target = [toml_str $opt(-target)]"
lappend m "sha1 = [toml_str $sha1]"
lappend m "size = $size"
lappend m "built = [toml_str $built]"
lappend m ""
lappend m "\[runtime\]"
lappend m "tcl_patchlevel = [toml_str $opt(-tclpatch)]"
set pr [expr {$variant ne "plain"}]
lappend m "piperepl = [expr {$pr ? "true" : "false"}]"
if {$pr} {
lappend m "piperepl_default = \"on\""
lappend m "piperepl_opt_out = \"TCLSH_PIPEREPL=0\""
}
lappend m "attached_batteries = \[[join $batteries {, }]\]"
lappend m ""
lappend m "\[provenance\]"
lappend m "suite = [toml_str $opt(-suite)]"
lappend m "toolchain = [toml_str "zig $opt(-zig)"]"
lappend m "optimize = [toml_str $opt(-optimize)]"
foreach {n uuid} $opt(-provenance) {
lappend m "${n}_checkout = [toml_str $uuid]"
}
#G-107 evidence summaries available at emission time (result lines only; the
#full line-record summaries stay the canonical evidence artifacts)
if {$opt(-testreports) ne "" && [file isdirectory $opt(-testreports)]} {
set tlines {}
foreach sf [lsort [glob -nocomplain -directory $opt(-testreports) *.summary]] {
set rec [dict create]
set f [open $sf r]
foreach line [split [read $f] \n] {
set line [string trim $line]
if {$line eq "" || [string index $line 0] eq "#"} continue
if {[catch {llength $line} n] || $n < 2} continue
dict set rec [lindex $line 0] [lrange $line 1 end]
}
close $f
if {![dict exists $rec library] || ![dict exists $rec result]} continue
set lib [dict get $rec library]
set parts [list "result=[dict get $rec result]"]
foreach fkey {mode total passed skipped failed} {
if {[dict exists $rec $fkey]} {lappend parts "$fkey=[dict get $rec $fkey]"}
}
lappend tlines "$lib = [toml_str [join $parts { }]]"
}
if {[llength $tlines]} {
lappend m ""
lappend m "\[tests\]"
lappend m {*}$tlines
}
}
set mf [file join $opt(-outdir) "[lindex [exe_split $artifact] 0].toml"]
set f [open $mf w]
fconfigure $f -translation lf
puts $f [join $m \n]
close $f
lappend emitted "$variant -> $artifact"
note "emitted $artifact (sha1 $sha1, [expr {$size/1024}] KB) + [file tail $mf]"
}
set f [open [file join $opt(-outdir) sha1sums.txt] w]
fconfigure $f -translation lf
puts $f [join $sha1lines \n]
close $f
note "sha1sums.txt written ([llength $sha1lines] artifacts)"
puts "family_artifacts OK: [join $emitted {; }] -> $opt(-outdir)"
exit 0