Skip to content

fix: resolve '..' physically in absolute and ~ path-tables - #1606

Merged
thekevinbot merged 4 commits into
mainfrom
bot/1580-abs-dotdot-1104
Nov 4, 2026
Merged

thekevinbot merged 4 commits into
mainfrom
bot/1580-abs-dotdot-1104

Conversation

@thekevinbot

@thekevinbot thekevinbot commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1580

An absolute or ~/ path-table folded .. lexically before the filesystem saw it, so '/r/y/link/../f.md' read y/f.md while cat reads real/f.md when y/link is a symlinked directory. The ./ and ../ forms already passed .. through to the OS.

Red

Red-test commit f72c400, CI red for the asserted reason: https://github.com/thekevinscott/dirsql/actions/runs/41879257313 (Rust Integration tests job: https://github.com/thekevinscott/dirsql/actions/runs/41879258057/job/126747194405)

test parent_through_a_symlink::an_absolute_path_reads_the_file_the_shell_reads ... FAILED
  left: [("/tmp/.tmp8siZRO/y/f.md", "LEXICAL")]
 right: [("/tmp/.tmp8siZRO/y/link/../f.md", "PHYSICAL")]

Fix

path_table::absolute_target no longer calls normalize; the OS resolves .., and path reports the name as written (/r/y/link/../f.md), as the ./ form and bash do.

  • Verbatim Windows paths (\\?\), where the OS takes .. literally, still fold. Non-verbatim Windows paths keep folding: typed_path follows Win32, which folds .. lexically itself.
  • Config [[table]] glob anchors keep the lexical fold (unchanged behavior; out of scope here).

Tests: CLI e2e (tests/path_table_cli_e2e.rs, absolute and ~/), SDK integration (tests/path_table_symlinks.rs), unit tests in path_table.rs. The symlink tests are cfg(unix) like the existing symlink suite: on Windows the OS itself resolves .. lexically, so the physical expectation does not apply there.

Manual run (release binary, issue repro):

PHYSICAL                                                       # cat
[{"path":"/tmp/r1580.iaPG/y/link/../f.md","content":"PHYSICAL"}]   # absolute file
[{"path":"/tmp/r1580.iaPG/y/link/../f.md","content":"PHYSICAL"}]   # absolute glob '/…/y/link/../*.md'
[{"path":"y/link/../f.md","content":"PHYSICAL"}]                   # ./ form, unchanged
[{"path":"/tmp/r1580.iaPG/y/link/../f.md","content":"PHYSICAL"}]   # directory '/…/y/link/..'

E2E Verification

  • Ran e2e suites locally for every affected SDK
  • Python SDK e2e: pass (impacted subset)
  • TypeScript SDK e2e: pass
  • Rust core e2e (if applicable): pass
  • packages/python/e2e-attestations/<branch>.json receipt written if packages/python changed (just e2e-attest-python)
  • packages/ts/e2e-attestations/<branch>.json receipt written if packages/ts changed (just e2e-attest-ts)
  • Command(s) run: cd packages/python && testing-conventions e2e attest 'uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/on_file_query_test.py tests/e2e/use_case_join_test.py tests/e2e/glob_speed_symlink_test.py tests/e2e/fanout_test.py -x -q' (after maturin develop --release); just e2e-attest-ts; cargo test -p dirsql --features cli
  • Result summary: Python 17 passed; TS 19 passed; Rust all passed.

Changelog / Migrations

  • Changelog fragment added under <root>/<pkg>/changelog.d/ for each changed package (or: skip-changelog trailer on a commit with reason)
  • Migration fragment with the same slug added under <root>/<pkg>/migrations.d/ for each changed package (every subsection but Summary _None._ when nothing breaks)

Red ahead of the fix: a '..' after a symlinked directory is folded lexically, so the absolute and ~/ forms read a different file than the shell does.
Absolute and ~/ path-table names no longer fold '..' lexically; the OS resolves it, so a '..' after a symlinked directory climbs out of the link's target as in the shell, and path reports the name as written. Verbatim Windows paths, where the OS takes '..' literally, still fold. Config table anchors keep the lexical fold.
@thekevinbot
thekevinbot merged commit 147d2a8 into main Nov 4, 2026
89 checks passed
@thekevinbot
thekevinbot deleted the bot/1580-abs-dotdot-1104 branch November 4, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolve '..' physically in absolute and '~/' path-tables, as the shell does

1 participant