fix(scripts): check_third_party reads git check-ignore in bytes, so Windows skips ignored files #80
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!80
Loading…
Reference in a new issue
No description provided.
Delete branch "d4nkn3ss/Longshot:fix/check-third-party-windows-newlines"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
On Windows,
scripts/check_third_party.pyfails on any checkout set up the way CONTRIBUTING.md says: the Builder's binaries copied intothird_party/(a64emit.dll,lld-link.exe,SDL2.dll,zbic.dlland others) are counted although.gitignoreleaves them out, so a64-kit, sdl2 and zbic "differ from their notes".What changed
ignored()inscripts/check_third_party.pyasksgit check-ignore --no-index -z --stdin, NUL-separated and as UTF-8 bytes both ways, instead of newline-separated text. Two bugs went with the old form:as `, so git read every path with a trailing`, matched no rule, and nothing was skipped.
-z, git quotes a path with a non-ASCII byte in its answer ("third_party/x/é.dll"), which matched none of ours, so an ignoredé.dllwas hashed with its part, on every OS (from HumanBean's review).test_a_clean_tree_passesintests/test_check_third_party.pyadds an ignoredé.dllbesidefoo.dll; it fails without-zon Linux too, where CI runs.Flags and settings
None
Measurements
Not a performance change, so no fps or timings: the check's result on both sides.
main:
1be180bb(2026-11-13)this PR: fix/check-third-party-windows-newlines @
6c00bdcfHardware: Windows 11, Python 3 from python.org, git 2.56.1 (
core.autocrlf=true)Scene: n/a (game-free)
Method: each command run once on each side, on the same checkout, set up as CONTRIBUTING.md says with the Builder's third_party binaries copied in
How to reproduce: on Windows, copy the Builder's
tools\third_partybinaries in as CONTRIBUTING.md says, then run the two commands below1be180bb6c00bdcfpython -I scripts/check_third_party.pythird_party: 11 parts as their notes saypython -I -B tests/test_check_third_party.pyé.dllcase, against this PR's first commit (bytes, no-z)Testing
Tested: the two commands above on Windows 11, on main and on this PR, and:
git check-ignore --no-index --stdingiventhird_party/sdl2/SDL2.dll\nthrough Python withtext=Trueprints nothing (exit 1); given the same bytes it prints the path (exit 0).HEADon disk, so the difference was only the ignored binaries.python -I -B tests/run_all.pyon this branch: 456 passed, 4 failed.test_setup_runtime.pyandtest_release.pyfail on main @77f605a2too.test_fpx_sticky.pyandtest_spawn_emit.pypass when run alone, on main and here. In the full run,test_fpx_sticky.pyfailed becauseLONGSHOT_MINGWwasn't set in that shell; whytest_spawn_emit.pyfailed only in the full run I don't know.Not tested: Linux and macOS: the bytes and text paths are the same there, and CI's third-party job runs on Linux.
Needs other testers: None
Screenshots
Nothing on screen
Risk and rollback
Only the check script changes; reverting the commit is enough. With
-zgit neither quotes nor escapes the paths, so what comes back is byte for byte what was sent.Reviewer notes
CI runs this check on Linux only, which is why it didn't catch this.
Issues
None
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.🤖 Generated with Claude Code
I read the diff against
ignored()and its callers inscripts/check_third_party.py, andtests/test_check_third_party.py. The diagnosis holds: I tried it with git 2.56 here, andgit check-ignore --no-index --stdinmatches nothing fora.dll\r\n, so the\rthat text mode writes on Windows really does stop every rule from matching. Sending bytes fixes that, and Linux behaves the same as before.Two things before it goes in. Neither blocks it, but both are cheap:
-z, git quotes any path that has a non-ASCII byte in it (core.quotePath). An ignoredthird_party/x/é.dllcomes back as"third_party/x/\303\251.dll", doesn't match, and gets hashed with no error. So the Risk section's "the decode would fail loudly" isn't what happens.-zon both sides fixes the\rand the quoting together, and theencode/decodethen really are byte for byte.é.dllbesidefoo.dllintest_a_clean_tree_passes) would fail on Linux today and pass with-z. It would also guard the Windows case, because it pins the same parsing.The title is a fine Conventional Commit, and no check under tests/ cuts this function by its text.
@ -59,2 +58,2 @@capture_output=True, text=True, encoding="utf-8")return set(out.stdout.split("\n")) - {""}# (bytes, not text: in text mode Windows sends each path with a \r, which matches no rule, so ignored files counted)out = subprocess.run(["git", "check-ignore", "--no-index", "--stdin"], cwd=root,Suggest
-zhere:["git", "check-ignore", "-z", "--no-index", "--stdin"]withinput="\0".join(paths).encode("utf-8"). Without it git C-quotes non-ASCII paths in its output (core.quotePath, on by default), so an ignoredé.dllcomes back as"third_party/x/\303\251.dll", never matches, and is hashed silently. I checked with git 2.56:printf 'é.dll\n' | git check-ignore --no-index --stdinprints the quoted form, and with-zit prints the raw UTF-8 bytes. With-z, input lines are NUL-terminated, so the\rproblem goes away too.@ -61,0 +58,4 @@# (bytes, not text: in text mode Windows sends each path with a \r, which matches no rule, so ignored files counted)out = subprocess.run(["git", "check-ignore", "--no-index", "--stdin"], cwd=root,input=("\n".join(paths) + "\n").encode("utf-8"), capture_output=True)return set(out.stdout.decode("utf-8").splitlines()) - {""}With
-zthis becomesout.stdout.decode("utf-8").split("\0"). Small thing: as it stands,splitlines()also splits on\x0b,\x0c,\x1c-\x1e,\x85and\u2028/\u2029. That's harmless for real paths, butsplit("\n")(or"\0") says exactly what git sends.388d24f8f26c00bdcff9Thanks, both points taken in
6c00bdcf(rebased onto main1be180bb):ignored()now asksgit check-ignore --no-index -z --stdin, NUL-separated bytes both ways, so the\rand the quoting go together. You were right about the Risk line: the quoted name came back as a different string and was hashed silently, nothing failed. The line now says what-zgives.test_a_clean_tree_passesadds an ignoredé.dllbesidefoo.dll. Against this PR's first commit (bytes, no-z) it fails,FAILED (failures=1); with-z, OK. It doesn't depend on the OS, so it guards Linux CI as well as the Windows case.python -I scripts/check_third_party.pyon the Windows checkout with the Builder's binaries copied in still saysthird_party: 11 parts as their notes say. The description is updated to match.Approved current head
6c00bdcff9after inspecting the two-file diff and independently checking the pathname protocol on native Windows and Linux.Native Windows Python 3.14.7: all 9 checker tests ran successfully (1 platform skip), and the production checker accepted all 11 vendored parts with the ignored SDK SDL DLLs present. Two interleaved runs of the Unicode regression failed on main
d906c8f4and passed on this head each time.Linux Python 3.12.3 / Git 2.43.0, default core.quotePath=true: the same regression failed on main and passed on this head in two interleaved pairs. This used a separate valid Linux Git fixture, with Git path/config overrides removed; main checker bytes match the Windows baseline. Binary NUL records address both Git pathname quoting and Windows text newline translation without changing the provenance digest definition.
No blocking code findings. I did not run an independent full Longshot suite for this focused review; the checks above cover both changed files and the reported failure modes. No game or generated game code was involved.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.