Skip to content

Script: HTML _static/ gets 225 macOS AppleDouble files (._*) from the Runestone Services archive #3249

Description

@rbeezer

Summary

Every HTML build that places Runestone Services in its own output (the default; not portable
HTML, nor resources from the CDN) ends up with 225 macOS AppleDouble
files in _static/, one beside each real file:

_static/._139.6404c46752b3e634.js
_static/._139.6404c46752b3e634.js.gz
_static/._139.6404c46752b3e634.js.map
...

Each is 163 bytes of Finder metadata (file reports "AppleDouble encoded Macintosh
file"), used by nothing. They are harmless in a browser, but they double the file count
of _static/ (450 files where 225 are wanted), and they travel with every site that is
uploaded or zipped from the output.

Cause

They are in the archive itself. dist-8.3.2.tgz from https://runestone.academy/cdn/runestone/
has 450 entries, 225 of them ._*, all owned by bmiller/staff; dist-8.2.13.tgz is the
same. This is what macOS tar does by default: it writes each file's extended
attributes as a ._ companion. The archive also carries LIBARCHIVE.xattr.com.apple.provenance
headers, which GNU tar reports as "Ignoring unknown extended header keyword" on every
entry; Python's tarfile passes over those silently.

_place_runestone_services (pretext/lib/pretext.py, lines 3958–3959 at 20d10545)
unpacks everything:

            services_file = tarfile.open(services_build_path)
            services_file.extractall(build_dir)

Suggested fix

Either end would do, and both would be best.

In the script, skip the AppleDouble members when extracting:

            services_file = tarfile.open(services_build_path)
            members = [m for m in services_file.getmembers()
                       if not os.path.basename(m.name).startswith("._")]
            services_file.extractall(build_dir, members=members)

Tried on dist-8.3.2.tgz: 225 files come out, none of them ._*, and they are exactly
the files a build places now, less the AppleDouble ones.

In the Runestone packaging, make the archive without the macOS metadata, for example
COPYFILE_DISABLE=1 tar --no-xattrs -czf dist-<version>.tgz ..., which also removes the
provenance headers. That fix belongs to the Runestone side.

Reproduce

Any HTML build with the default static files, at 20d10545:

pretext -c doc -f html -p publication.ptx -d out main.ptx
ls -A out/_static | grep -c '^\._'        # 225

A related observation

extractall() without a filter argument raises a DeprecationWarning on Python 3.12
and later ("Python 3.14 will, by default, filter extracted tar archives..."); it is not
seen because the warning comes from a library module. Passing filter="data" where
tarfile has it (3.12, and the security releases 3.10.12 and 3.11.4) would settle that
at the same spot.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions