fix: cost the device prefix exactly rather than approximately
Build and publish container / build (pull_request) Successful in 3m54s

The budget subtracted the prefix length plus two, on the assumption of a
leading and a trailing slash. That is right for /Music and wrong for an empty
prefix, where there is only one slash -- losing a character at the card root,
which is exactly where the longest paths sit.

Computed from the prefix as it will actually appear instead: /Music/ costs
seven characters and gives a mirror-relative budget of 253, the root costs one
and gives 259.

Worth being exact about because the reverse error is worse. A checker
comparing mirror-relative paths against the flat 260 passes everything between
253 and 260, and those are precisely the paths closest to the edge.
This commit is contained in:
Emma Thorpe
2026-08-25 11:52:03 +01:00
parent 46435feebd
commit ece79515c0
4 changed files with 58 additions and 3 deletions
+13 -1
View File
@@ -28,6 +28,18 @@ PATH_LIMIT = 260
DEVICE_PREFIX = "/Music"
def device_prefix_length(prefix):
"""Return the on-device prefix as it will actually appear, with slashes.
"/Music" costs seven characters -- the leading slash, the name, and the
separator before the mirror's own path -- while an empty prefix costs one.
Approximating that loses a character at the root, which is precisely where
the longest paths are.
"""
cleaned = prefix.strip("/")
return f"/{cleaned}/" if cleaned else "/"
def problems_with(relative, budget=PATH_LIMIT):
"""Return every reason this relative path is unfit for FAT32."""
found = []
@@ -68,7 +80,7 @@ def main(argv=None):
f" of the budget (default {DEVICE_PREFIX})",
)
args = parser.parse_args(argv)
budget = max(0, args.max_path - len(args.device_prefix.strip("/")) - 2)
budget = max(0, args.max_path - len(device_prefix_length(args.device_prefix)))
root = Path(args.root)
if not root.is_dir():