Browse Source

build outputs: mapped-file replace helpers into bootsupport, _vfscommon and the thin layouts

Regenerated by 'make.tcl modules' + 'bootsupport' + 'vfscommonupdate'. The thin-layout
make.tcl copies and the templates modpod carry ::punkboot::replace_possibly_mapped_file and
::punkboot::mapped_file_hint, so generated projects get the same behaviour - a project whose
own bootsupport carries a zip-based .tm meets exactly the same windows constraint.

Note the templates modpod copy in this commit was itself replaced by the new delete-then-
place path: the bootsupport run reported "in-place overwrite refused - replaced by
delete-then-place" and completed, where the previous three runs this session failed and
needed a hand copy. The fix was exercised by the change-set that introduced it.

Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
master
Julian Noble 5 days ago
parent
commit
8a2e216490
  1. BIN
      src/bootsupport/modules/punk/mix/templates-0.2.0.tm
  2. 114
      src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/project_layouts/vendor/punk/project-0.1/src/make.tcl
  3. 114
      src/project_layouts/vendor/punk/basic/src/make.tcl
  4. 114
      src/project_layouts/vendor/punk/project-0.1/src/make.tcl
  5. BIN
      src/vfs/_vfscommon.vfs/modules/punk/mix/templates-0.2.0.tm

BIN
src/bootsupport/modules/punk/mix/templates-0.2.0.tm

Binary file not shown.

114
src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/project_layouts/vendor/punk/project-0.1/src/make.tcl vendored

@ -3287,6 +3287,60 @@ proc ::punkboot::get_src_provenance_warnings {projectroot label} {
set checked_vcs_roots [dict create]
return [list 1 [::punkboot::utils::vcs_dirty_warnings $projectroot checked_vcs_roots $label src]]
}
#Replace a file that may be MEMORY-MAPPED by another process (or by this one).
#
#On windows an ordinary 'file copy -force' onto a mapped file is refused: a zipfs mount
#maps its archive (tclZipfs.c CreateFileMappingW + MapViewOfFile), so a zip-based .tm
#modpod that any running shell - including this build - has mounted cannot be overwritten
#in place. Windows reports ERROR_USER_MAPPED_FILE (1224); Tcl's Tcl_WinConvertError maps
#only Win32 codes 0..267 and sends everything above them to EINVAL, so it surfaces as the
#uninformative "invalid argument" (same code in 8.6 and 9.x).
#
#UNLINKING a mapped file IS allowed - the holder keeps reading its own mapping and new
#content lands at the name - so delete-then-place succeeds where overwrite cannot. The new
#content goes to a sibling temp FIRST so a mid-sequence failure can never leave the target
#missing.
#
#Returns one of: ok (plain copy worked), replaced (needed the delete-then-place path),
#failed (target untouched), broken (target was unlinked and could not be restored - the
#caller must treat this as serious). The first copy's error message is written to the
#variable named by firsterrvar.
proc ::punkboot::replace_possibly_mapped_file {srcfile tgtfile firsterrvar} {
upvar 1 $firsterrvar firsterr
set firsterr ""
if {![catch {file copy -force $srcfile $tgtfile} firsterr]} {
return ok
}
if {![file exists $tgtfile]} {
#nothing to unlink - whatever failed, it was not an in-place overwrite
return failed
}
set tmpfile $tgtfile.punkboot-new
catch {file delete -force -- $tmpfile}
if {[catch {file copy -- $srcfile $tmpfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file delete -- $tgtfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file rename -- $tmpfile $tgtfile}]} {
return broken
}
return replaced
}
#Actionable text for a file-operation failure whose message is windows' catch-all.
#Returns "" when the error does not look like that case.
proc ::punkboot::mapped_file_hint {errmsg tgtfile} {
if {![string match -nocase "*invalid argument*" $errmsg]} {
return ""
}
return "'invalid argument' is Tcl's catch-all for any windows error above 267 (Tcl_WinConvertError), not a bad argument.\
For a file replace the usual cause is ERROR_USER_MAPPED_FILE: '$tgtfile' is memory-mapped by a process that has it mounted -\
a zipfs/modpod mount does this, so a running punk shell (or this build) holding that .tm blocks an in-place overwrite.\
Close shells holding it, or rerun - the update now replaces such files by delete-then-place rather than overwrite."
}
#Availability probe + boot-precondition check of an assembled kit vfs (G-125), shared by the
#kit gate in the bake loop and the 'check' command report. Same guarded-require treatment as
#the provenance check above: a stale or missing punkboot::utils snapshot must not brick the
@ -4370,31 +4424,47 @@ if {$::punkboot::command eq "bootsupport"} {
$boot_event targetset_started
# -- --- --- --- --- ---
puts "\nBOOTSUPPORT module$which update: $srcfile -> $tgtfile"
if {[catch {
file copy -force $srcfile $tgtfile
} errM]} {
#a copy onto a modpod this make.tcl process has mounted (e.g punk::mix::templates)
#fails on windows even when the target content is already current (a prior failed
#record forces a retry). If content is already identical, record OK so the record
#converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
#An in-place overwrite is refused when the target is memory-mapped -
#which is what a mounted zip-based .tm modpod (e.g punk::mix::templates)
#is. replace_possibly_mapped_file falls back to delete-then-place, which
#windows does allow. See its comment for why the error reads "invalid
#argument" and why unlinking is safe for the process holding the mapping.
switch -- [::punkboot::replace_possibly_mapped_file $srcfile $tgtfile errM] {
ok {
$boot_event targetset_end OK
}
replaced {
puts stdout " (in-place overwrite refused - replaced by delete-then-place; target was memory-mapped, e.g a mounted modpod)"
$boot_event targetset_end OK -note "overwrite refused ($errM) - replaced via delete-then-place (target memory-mapped)"
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical (self-mounted modpod?)"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
broken {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile was unlinked and could not be replaced - restore it from $srcfile by hand ($errM)"
$boot_event targetset_end FAILED
}
} else {
$boot_event targetset_end OK
default {
#target untouched. If its content is already identical, record OK so a
#prior failed record converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
set _hint [::punkboot::mapped_file_hint $errM $tgtfile]
if {$_hint ne ""} {
puts stderr " $_hint"
}
$boot_event targetset_end FAILED
}
}
}
# -- --- --- --- --- ---
} else {

114
src/project_layouts/vendor/punk/basic/src/make.tcl vendored

@ -3287,6 +3287,60 @@ proc ::punkboot::get_src_provenance_warnings {projectroot label} {
set checked_vcs_roots [dict create]
return [list 1 [::punkboot::utils::vcs_dirty_warnings $projectroot checked_vcs_roots $label src]]
}
#Replace a file that may be MEMORY-MAPPED by another process (or by this one).
#
#On windows an ordinary 'file copy -force' onto a mapped file is refused: a zipfs mount
#maps its archive (tclZipfs.c CreateFileMappingW + MapViewOfFile), so a zip-based .tm
#modpod that any running shell - including this build - has mounted cannot be overwritten
#in place. Windows reports ERROR_USER_MAPPED_FILE (1224); Tcl's Tcl_WinConvertError maps
#only Win32 codes 0..267 and sends everything above them to EINVAL, so it surfaces as the
#uninformative "invalid argument" (same code in 8.6 and 9.x).
#
#UNLINKING a mapped file IS allowed - the holder keeps reading its own mapping and new
#content lands at the name - so delete-then-place succeeds where overwrite cannot. The new
#content goes to a sibling temp FIRST so a mid-sequence failure can never leave the target
#missing.
#
#Returns one of: ok (plain copy worked), replaced (needed the delete-then-place path),
#failed (target untouched), broken (target was unlinked and could not be restored - the
#caller must treat this as serious). The first copy's error message is written to the
#variable named by firsterrvar.
proc ::punkboot::replace_possibly_mapped_file {srcfile tgtfile firsterrvar} {
upvar 1 $firsterrvar firsterr
set firsterr ""
if {![catch {file copy -force $srcfile $tgtfile} firsterr]} {
return ok
}
if {![file exists $tgtfile]} {
#nothing to unlink - whatever failed, it was not an in-place overwrite
return failed
}
set tmpfile $tgtfile.punkboot-new
catch {file delete -force -- $tmpfile}
if {[catch {file copy -- $srcfile $tmpfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file delete -- $tgtfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file rename -- $tmpfile $tgtfile}]} {
return broken
}
return replaced
}
#Actionable text for a file-operation failure whose message is windows' catch-all.
#Returns "" when the error does not look like that case.
proc ::punkboot::mapped_file_hint {errmsg tgtfile} {
if {![string match -nocase "*invalid argument*" $errmsg]} {
return ""
}
return "'invalid argument' is Tcl's catch-all for any windows error above 267 (Tcl_WinConvertError), not a bad argument.\
For a file replace the usual cause is ERROR_USER_MAPPED_FILE: '$tgtfile' is memory-mapped by a process that has it mounted -\
a zipfs/modpod mount does this, so a running punk shell (or this build) holding that .tm blocks an in-place overwrite.\
Close shells holding it, or rerun - the update now replaces such files by delete-then-place rather than overwrite."
}
#Availability probe + boot-precondition check of an assembled kit vfs (G-125), shared by the
#kit gate in the bake loop and the 'check' command report. Same guarded-require treatment as
#the provenance check above: a stale or missing punkboot::utils snapshot must not brick the
@ -4370,31 +4424,47 @@ if {$::punkboot::command eq "bootsupport"} {
$boot_event targetset_started
# -- --- --- --- --- ---
puts "\nBOOTSUPPORT module$which update: $srcfile -> $tgtfile"
if {[catch {
file copy -force $srcfile $tgtfile
} errM]} {
#a copy onto a modpod this make.tcl process has mounted (e.g punk::mix::templates)
#fails on windows even when the target content is already current (a prior failed
#record forces a retry). If content is already identical, record OK so the record
#converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
#An in-place overwrite is refused when the target is memory-mapped -
#which is what a mounted zip-based .tm modpod (e.g punk::mix::templates)
#is. replace_possibly_mapped_file falls back to delete-then-place, which
#windows does allow. See its comment for why the error reads "invalid
#argument" and why unlinking is safe for the process holding the mapping.
switch -- [::punkboot::replace_possibly_mapped_file $srcfile $tgtfile errM] {
ok {
$boot_event targetset_end OK
}
replaced {
puts stdout " (in-place overwrite refused - replaced by delete-then-place; target was memory-mapped, e.g a mounted modpod)"
$boot_event targetset_end OK -note "overwrite refused ($errM) - replaced via delete-then-place (target memory-mapped)"
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical (self-mounted modpod?)"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
broken {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile was unlinked and could not be replaced - restore it from $srcfile by hand ($errM)"
$boot_event targetset_end FAILED
}
} else {
$boot_event targetset_end OK
default {
#target untouched. If its content is already identical, record OK so a
#prior failed record converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
set _hint [::punkboot::mapped_file_hint $errM $tgtfile]
if {$_hint ne ""} {
puts stderr " $_hint"
}
$boot_event targetset_end FAILED
}
}
}
# -- --- --- --- --- ---
} else {

114
src/project_layouts/vendor/punk/project-0.1/src/make.tcl vendored

@ -3287,6 +3287,60 @@ proc ::punkboot::get_src_provenance_warnings {projectroot label} {
set checked_vcs_roots [dict create]
return [list 1 [::punkboot::utils::vcs_dirty_warnings $projectroot checked_vcs_roots $label src]]
}
#Replace a file that may be MEMORY-MAPPED by another process (or by this one).
#
#On windows an ordinary 'file copy -force' onto a mapped file is refused: a zipfs mount
#maps its archive (tclZipfs.c CreateFileMappingW + MapViewOfFile), so a zip-based .tm
#modpod that any running shell - including this build - has mounted cannot be overwritten
#in place. Windows reports ERROR_USER_MAPPED_FILE (1224); Tcl's Tcl_WinConvertError maps
#only Win32 codes 0..267 and sends everything above them to EINVAL, so it surfaces as the
#uninformative "invalid argument" (same code in 8.6 and 9.x).
#
#UNLINKING a mapped file IS allowed - the holder keeps reading its own mapping and new
#content lands at the name - so delete-then-place succeeds where overwrite cannot. The new
#content goes to a sibling temp FIRST so a mid-sequence failure can never leave the target
#missing.
#
#Returns one of: ok (plain copy worked), replaced (needed the delete-then-place path),
#failed (target untouched), broken (target was unlinked and could not be restored - the
#caller must treat this as serious). The first copy's error message is written to the
#variable named by firsterrvar.
proc ::punkboot::replace_possibly_mapped_file {srcfile tgtfile firsterrvar} {
upvar 1 $firsterrvar firsterr
set firsterr ""
if {![catch {file copy -force $srcfile $tgtfile} firsterr]} {
return ok
}
if {![file exists $tgtfile]} {
#nothing to unlink - whatever failed, it was not an in-place overwrite
return failed
}
set tmpfile $tgtfile.punkboot-new
catch {file delete -force -- $tmpfile}
if {[catch {file copy -- $srcfile $tmpfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file delete -- $tgtfile}]} {
catch {file delete -force -- $tmpfile}
return failed
}
if {[catch {file rename -- $tmpfile $tgtfile}]} {
return broken
}
return replaced
}
#Actionable text for a file-operation failure whose message is windows' catch-all.
#Returns "" when the error does not look like that case.
proc ::punkboot::mapped_file_hint {errmsg tgtfile} {
if {![string match -nocase "*invalid argument*" $errmsg]} {
return ""
}
return "'invalid argument' is Tcl's catch-all for any windows error above 267 (Tcl_WinConvertError), not a bad argument.\
For a file replace the usual cause is ERROR_USER_MAPPED_FILE: '$tgtfile' is memory-mapped by a process that has it mounted -\
a zipfs/modpod mount does this, so a running punk shell (or this build) holding that .tm blocks an in-place overwrite.\
Close shells holding it, or rerun - the update now replaces such files by delete-then-place rather than overwrite."
}
#Availability probe + boot-precondition check of an assembled kit vfs (G-125), shared by the
#kit gate in the bake loop and the 'check' command report. Same guarded-require treatment as
#the provenance check above: a stale or missing punkboot::utils snapshot must not brick the
@ -4370,31 +4424,47 @@ if {$::punkboot::command eq "bootsupport"} {
$boot_event targetset_started
# -- --- --- --- --- ---
puts "\nBOOTSUPPORT module$which update: $srcfile -> $tgtfile"
if {[catch {
file copy -force $srcfile $tgtfile
} errM]} {
#a copy onto a modpod this make.tcl process has mounted (e.g punk::mix::templates)
#fails on windows even when the target content is already current (a prior failed
#record forces a retry). If content is already identical, record OK so the record
#converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
#An in-place overwrite is refused when the target is memory-mapped -
#which is what a mounted zip-based .tm modpod (e.g punk::mix::templates)
#is. replace_possibly_mapped_file falls back to delete-then-place, which
#windows does allow. See its comment for why the error reads "invalid
#argument" and why unlinking is safe for the process holding the mapping.
switch -- [::punkboot::replace_possibly_mapped_file $srcfile $tgtfile errM] {
ok {
$boot_event targetset_end OK
}
replaced {
puts stdout " (in-place overwrite refused - replaced by delete-then-place; target was memory-mapped, e.g a mounted modpod)"
$boot_event targetset_end OK -note "overwrite refused ($errM) - replaced via delete-then-place (target memory-mapped)"
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical (self-mounted modpod?)"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
broken {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile was unlinked and could not be replaced - restore it from $srcfile by hand ($errM)"
$boot_event targetset_end FAILED
}
} else {
$boot_event targetset_end OK
default {
#target untouched. If its content is already identical, record OK so a
#prior failed record converges instead of churning FAILED forever.
set already_current 0
if {[file exists $tgtfile] && [file size $tgtfile] == [file size $srcfile]} {
catch {
set src_ck [dict get [punk::mix::base::lib::cksum_path $srcfile] cksum]
set tgt_ck [dict get [punk::mix::base::lib::cksum_path $tgtfile] cksum]
if {$src_ck ne "" && $src_ck eq $tgt_ck} {
set already_current 1
}
}
}
if {$already_current} {
$boot_event targetset_end OK -note "copy failed ($errM) but target content already identical"
} else {
puts stderr "BOOTSUPPORT module$which update FAILED: $tgtfile ($errM)"
set _hint [::punkboot::mapped_file_hint $errM $tgtfile]
if {$_hint ne ""} {
puts stderr " $_hint"
}
$boot_event targetset_end FAILED
}
}
}
# -- --- --- --- --- ---
} else {

BIN
src/vfs/_vfscommon.vfs/modules/punk/mix/templates-0.2.0.tm

Binary file not shown.
Loading…
Cancel
Save