Skip to content

Nothing detects drift between polyfile/magic_defs and the file submodule #3479

Closed

Description

@ESultanik

Summary

polyfile/magic_defs/ is a hand-maintained copy of file/magic/Magdir/ from the file submodule, and nothing verifies that the two agree. A definition can be deleted, truncated, or left behind at an older revision, and the whole test suite stays green.

This matters because the copy is not append-only in either direction:

  • Stale definitions accumulate. The update procedure has historically been cp file/magic/Magdir/* polyfile/magic_defs/, which never removes what upstream deleted. Six definitions that libmagic dropped between 2021 and 2024 — alpha, dsf, guile, neko, pc88, rinex — were still shipped and still matching until the libmagic 5.48 update removed them.
  • Local patches get reverted. polyfile/magic_defs/c-lang carries the rewrite from Example files that cause an unexpected delay iterating (infinite?) matches  #3411, so it deliberately differs from upstream. A plain copy silently reverts it, reintroducing a matcher that does not terminate on CRLF C++ headers. tests/test_magic.py::test_cpp_class_test_terminates does happen to catch that one, but only because someone wrote a targeted test for it; nothing generalizes.

Reproducer

Delete a bundled definition that the submodule still ships:

rm polyfile/magic_defs/partclone
pytest tests/test_magic.py -q

Output on master (commit eed1f27, with the 5.48 definitions):

21 passed, 91 subtests passed in 5.59s

partclone declares no !:mime, so even the MIME type count is unchanged at 895. The definition is simply gone.

A definition carrying text tests would trip test_text_tests by accident, since that golden set is keyed by file name and line number, but that is a side effect of an unrelated assertion rather than a drift check.

Suggested check

A test in the spirit of tests/test_licensing.py, which already guards an analogous invariant between MANIFEST.in and the Kaitai license allowlist:

  1. Every file in file/magic/Magdir/ exists in polyfile/magic_defs/.
  2. The only extra entries in polyfile/magic_defs/ are the five PolyFile owns: __init__.py, COPYING, csv, json, polyfile_zip.
  3. Every shared file is byte-identical, except for an explicit, documented allowlist of locally patched files. That allowlist currently holds one entry, c-lang, and each entry should name the issue that justifies it.
  4. polyfile/magic_defs/COPYING matches file/COPYING.

Point 3 is the valuable one: it turns "someone remembered to re-apply the patch" into something CI enforces, and it makes the set of local patches discoverable instead of folklore. It also fails loudly when upstream rewrites the same lines a patch touches, which is the moment a maintainer needs to think rather than copy.

The test needs the submodule checked out. CI already does submodules: recursive, and test_magic.py::test_file_corpus already asserts file/tests exists, so a skipUnless on file/magic/Magdir would match existing practice for local runs without it.

docs/updating_libmagic_defs.md, added by the libmagic 5.48 update, documents the manual
verification commands. This issue is about making CI run them.

Environment

  • PolyFile at commit eed1f27
  • libmagic 5.48

Activity

  1. self-assigned this
    on Sep 11, 2026
  2. added this to the v0.6.0 milestone on Sep 11, 2026
  3. ESultanik commented on Sep 11, 2026

    @ESultanik
    CollaboratorAuthor

    One addition to the allowlist, decided while planning v0.6.0

    The suggested check's point 3 allows an explicit list of locally patched files, currently holding
    one entry, c-lang.

    #3473 adds a second: polyfile/magic_defs/gentoo. It rewrites the gentoo-manifest regex at
    :38, which takes superlinear time on runs of whitespace. That work is in the same wave as this
    issue, so whichever merges second has to add the entry to the other's allowlist. Call it out in the
    PR body either way.

    Each allowlist entry should name the issue that justifies it, as the issue proposes: c-lang →
    #3411, gentoo → #3473.

    The rest of the plan stands as written. tests/test_licensing.py is the model — it already guards
    the analogous invariant between MANIFEST.in and the Kaitai license allowlist, and its
    @skipUnless(HAVE_FORMAT_LIBRARY, ...) at :25 is the pattern to copy for a check that needs a
    submodule checked out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions