Skip to content

emrg: the runner's import root tells two spellings of one directory apart #2557

Closed

Description

@how2how2how2-arch

What is observed

emrg/tools/shell_env.py::_same_directory decides whether two spellings name one
directory by comparing os.path.normcase(canonical_path(...)). normcase folds case on
Windows and is the identity function on POSIX, so where a volume folds case while the
platform is POSIX — APFS's default, which is what macOS runs — two spellings of one
directory are reported as two directories.

runner_import_env asks exactly that question, to decide whether the running package's
root is already reachable through PYTHONPATH. When the answer is wrongly "no", it
prepends a second entry naming the same directory.

Where it was observed

macOS 26.6.2 (APFS, case-folding), on master 6a217042. emrg/tools/bash_tool_v2.py and
emrg/tools/pwsh_tool_v2.py both call runner_import_env(), so this is reachable on the
host platform and not only on the Windows rung the function was written for.

Reproduction, both directions, measured on that tree:

$ python3 -c "
import os
from emrg.tools.shell_env import runner_import_env, _running_package_root, _same_directory
root = _running_package_root()
variant = os.path.join(os.path.dirname(root), os.path.basename(root).upper())
print('same spelling    ->', runner_import_env({'PYTHONPATH': root}))
print('one directory?   ->', _same_directory(variant, root))
print('variant spelling ->', runner_import_env({'PYTHONPATH': variant}))
"
same spelling    -> {}
one directory?   -> False
variant spelling -> {'PYTHONPATH': '<root>'}

The first answer is correct: the root is already named, so nothing is added. The second
and third name the same directory — the volume says so — and an entry is still added.

What was expected instead

The function's docstring states the purpose it fails at on this volume: "treating them
as two would prepend a duplicate rather than leave a correct declaration alone."
Here it
prepends the duplicate that sentence exists to prevent.

What the fix must satisfy

  1. Two spellings that name one directory are one directory, decided by the filesystem's
    own identity (st_dev + st_ino, as os.path.samefile compares) rather than by a
    string transform. This is the same mechanism a protected daemon file is recognised by,
    and it answers on every platform without asking which one is running.
  2. A path that is not there still gets an answer — it is not the directory it is compared
    with, so the root is prepended. Prepending is the fail-safe direction: a duplicate
    entry is harmless, a missing one breaks the runner's import.
  3. Where the platform folds case by default, the two spellings must still read as one
    directory; the fix must not regress the Windows case the current spelling gets right.
  4. Both directions are measured, and a volume-dependent one skips with its reason stated
    where the volume keeps the spellings apart, rather than passing without asking.

Activity

  1. argszero commented on Oct 23, 2026

    @argszero
    Owner

    Handled by #2558 — the comparison now asks emrg.tools.file_policy.same_file (identity, st_dev+st_ino) instead of normcase, with the fold measured on APFS and a missing directory still answered by prepending.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions