-sub propsfile_set_prop ($$$) {
- # set $value to undef to delete; returns old value
- my ($propsfile, $prop, $value) = @_;
- my $wf = wf_start(".topbloke/$propsfile");
- my $oldvalue;
- open FI, '<', ".topbloke/$propsfile" or die $!;
- while (<FI>) {
- chomp or die;
- m/ / or m/$/;
- if ($` eq $prop) {
- die "prop $prop repeated in $propsfile ?!" if defined $oldvalue;
- $oldvalue = $'; #';
- } else {
+sub metafile_process ($$$$$) {
+ my ($metafile, $startcode, $linecode, $endcode, $enoentcode) = @_;
+ # runs $startcode->($outwf) at start
+ # runs $linecode->($outwf) for each old line, with $_ the chomped line
+ # may modify $_, which will be written to $outf
+ # at end runs $endcode->($outwf);
+ # runs $enoentcode->($outwf) instead of ever calling $linecode
+ # if the existing file does not exist;
+ # if it's false dies instead
+ # any of these may return false, in which case we quit immediately
+ # any of these except enoentcode may be undef to mean "noop"
+ # if they all return true, we install the new file
+ my $wf = wf_start(".topbloke/$metafile");
+ my $call = sub {
+ return 1 unless $_->[0];
+ return 1 if $_->[0]($wf);
+ wf_abort($wf);
+ close FI;
+ return 0;
+ };
+ return unless $call->($startcode);
+ if (!open FI, '<', ".topbloke/$metafile") {
+ die "$metafile $!" unless $!==ENOENT;
+ die "$metafile $!" unless $enoentcode;
+ return unless $call->($enoentcode);
+ } else {
+ while (<FI>) {
+ chomp or die;
+ return unless $call->($linecode);