Mirror the source tree onto the system disk
A list of files in a makefile goes stale the moment somebody adds a program and forgets to name it, and what they forgot is invisible until they go looking for it on the machine. So SplitDisk gained a mirror command and the disk rule is one line: putting a file where the others live is now the whole of putting it on the disk. EVERY FILE GOES THROUGH put AND EVERY DIRECTORY THROUGH mkdir. That is the point of it - mirror adds a walk and no filesystem code at all, so anything the format refuses here it refuses everywhere, in the same words. What is new is the walk, and the walk is what the six checks in Tests/disk.sh are about: that it goes all the way down, that it leaves dotfiles and named directories behind, and that a name too long stops it. REFUSED RATHER THAN SKIPPED, because a disk quietly missing a file is the exact failure a mirror exists to prevent. Which meant four sources had to be renamed - a directory entry holds 22 characters and they were 23, 23, 24 and 29: 16bitSegmentedSieve.asm -> 16bitSieve.asm 16bitSegmentedSieveModern.asm -> 16bitSieveModern.asm consoleInterruptTest.asm -> consoleInterrupt.asm controllerWriteTest.asm -> controllerWrite.asm The test names in the manifest are unchanged, since those are identifiers and every recorded result is filed under them. Only where the source lives has moved. The entries are sorted before anything is written. readdir hands them back in whatever order the host filesystem feels like, and a disk image that comes out different from one run to the next is an image no test could compare against another. The disk grew from one megabyte to four and from 192 directory entries to 1,024. The sources are 2,850 blocks and the mirror filled the old directory on its first run, which is a thing that should not need thinking about again. The Tests fixture disk is deliberately NOT mirrored. It is a controlled fixture with known contents, and the shipped disk is the one meant to be useful; they want different things. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
ff4b025058
commit
0852666e73
+41
-1
@@ -76,7 +76,7 @@ for f in empty.bin one.bin exact.bin part.bin whole.bin; do
|
||||
check "$f comes back byte for byte" roundTrip "$f"
|
||||
done
|
||||
|
||||
refuses "refuse a name of 29 characters" "$TOOL" put work.img part.bin 16bitSegmentedSieveModern.asm
|
||||
refuses "refuse a name of 29 characters" "$TOOL" put work.img part.bin twentyNineCharactersLong.asm
|
||||
refuses "refuse a duplicate name" "$TOOL" put work.img one.bin
|
||||
refuses "refuse a file that is not there" "$TOOL" get work.img nosuch.bin out.bin
|
||||
check "delete" "$TOOL" delete work.img one.bin
|
||||
@@ -228,6 +228,46 @@ check "a fresh disk is settled" python3 -c "
|
||||
import sys
|
||||
sys.exit(0 if open('plain.img','rb').read()[17] == 0 else 1)"
|
||||
|
||||
# ---- Mirroring a host directory ----
|
||||
#
|
||||
# What the system disk is built with. Every file goes through put and every directory
|
||||
# through mkdir, so this is a walk over machinery already checked above - what wants
|
||||
# checking is the walk: that it goes all the way down, that it leaves behind what it was
|
||||
# told to, and that it REFUSES a name the format cannot hold rather than skipping it, since
|
||||
# a disk quietly missing a file is the failure a mirror exists to prevent.
|
||||
mkdir -p tree/inner/deeper tree/leave
|
||||
printf 'top' > tree/top.txt
|
||||
printf 'inner' > tree/inner/middle.txt
|
||||
printf 'deep' > tree/inner/deeper/bottom.txt
|
||||
printf 'not this' > tree/leave/ignored.txt
|
||||
: > tree/.hidden
|
||||
|
||||
"$TOOL" format mirror.img 256 8 >/dev/null
|
||||
check "mirror a directory tree" "$TOOL" mirror mirror.img tree /
|
||||
|
||||
"$TOOL" list mirror.img > mirrored.txt 2>&1
|
||||
grep -q '/inner/deeper/bottom.txt' mirrored.txt \
|
||||
&& { PASS=$((PASS + 1)); printf " [%sok %s] %s\n" "$GREEN" "$RESET" "it goes all the way down"; } \
|
||||
|| { FAIL=$((FAIL + 1)); FAILED_NAMES+=("depth"); printf " [%sFAIL%s] %s\n" "$RED" "$RESET" "it goes all the way down"; }
|
||||
grep -q 'hidden' mirrored.txt \
|
||||
&& { FAIL=$((FAIL + 1)); FAILED_NAMES+=("hidden"); printf " [%sFAIL%s] %s\n" "$RED" "$RESET" "and leaves dotfiles behind"; } \
|
||||
|| { PASS=$((PASS + 1)); printf " [%sok %s] %s\n" "$GREEN" "$RESET" "and leaves dotfiles behind"; }
|
||||
|
||||
# Named on the command line, which is how a project keeps what it builds out of what it
|
||||
# wrote.
|
||||
"$TOOL" format skipped.img 256 8 >/dev/null
|
||||
check "mirror with something left out" "$TOOL" mirror skipped.img tree / leave
|
||||
"$TOOL" list skipped.img > skipped.txt 2>&1
|
||||
grep -q 'ignored.txt' skipped.txt \
|
||||
&& { FAIL=$((FAIL + 1)); FAILED_NAMES+=("skip"); printf " [%sFAIL%s] %s\n" "$RED" "$RESET" "and the skipped one is not there"; } \
|
||||
|| { PASS=$((PASS + 1)); printf " [%sok %s] %s\n" "$GREEN" "$RESET" "and the skipped one is not there"; }
|
||||
|
||||
# Twenty-three characters, one more than a directory entry holds.
|
||||
printf 'too long' > tree/aNameOfTwentyThreeChars
|
||||
"$TOOL" format refused.img 256 8 >/dev/null
|
||||
refuses "a name too long stops the mirror" "$TOOL" mirror refused.img tree /
|
||||
rm -f tree/aNameOfTwentyThreeChars
|
||||
|
||||
echo
|
||||
if [ "$FAIL" -eq 0 ]; then
|
||||
echo "All $PASS disk tool checks passed."
|
||||
|
||||
Reference in New Issue
Block a user