Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions src/extensions/score_mounts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ def _canonical_mount_dir(walk_dir: Path, spec: MountSpec) -> Path:
generated files below it can resolve to the action execroot spelling,
for example
``~/.cache/bazel/.../execroot/_main/bazel-out/.../docs/generated/index.rst``.
- for in-tree (same-workspace) source bundles, the mount root directory
exists in the sandbox but the individual source files are symlinks back
to the original workspace, for example
``.../sandbox/.../execroot/_main/score/socom/docs/index.rst``
``→ /home/user/workspace/score/socom/docs/index.rst``.

This applies to all bundle types: external repositories, generated data
bundles, and in-tree (same-workspace) source bundles. Resolve one mounted
source file first and walk back by its bundle-relative suffix to get the
canonical root.

Resolving only ``walk_dir`` therefore keeps the sandbox spelling, while
resolving a referenced image/include from Sphinx follows the file symlink.
Expand All @@ -143,19 +153,6 @@ def _canonical_mount_dir(walk_dir: Path, spec: MountSpec) -> Path:
the canonical mount root. For ``subdir/page.rst`` we walk back two
components, yielding the same canonical root.
"""
if not spec.external and not spec.data:
return walk_dir.resolve()

# Bazel materializes the mount directory structure in the sandbox but may
# symlink the individual files either to the external repository cache or to
# the action execroot's bazel-out tree. A mounted documentation source gives
# us the same canonical spelling that Sphinx will later see for dependency
# files. Walking back by the source file's path relative to the mount
# reconstructs the canonical mount root:
#
# source_file = walk_dir / "subdir/page.rst"
# relative_path.parts = ("subdir", "page.rst")
# source_file.resolve().parents[1] == canonical walk_dir
for source_file in walk_dir.rglob("*"):
if not source_file.is_file() or source_file.suffix not in {".md", ".rst"}:
continue
Expand Down
40 changes: 40 additions & 0 deletions src/extensions/score_mounts/tests/test_data_mounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,46 @@ def test_mount_entry_uses_canonical_directory_for_symlinked_bundle(
assert entry["dir"] == str(canonical_dir)


def test_canonical_mount_dir_in_tree_sandbox_bundle(tmp_path: Path) -> None:
"""In-tree bundles with symlinked files must resolve to the workspace root."""
workspace_docs = tmp_path / "workspace" / "module" / "docs"
workspace_docs.mkdir(parents=True)
(workspace_docs / "index.rst").write_text("Index", encoding="utf-8")
(workspace_docs / "guide").mkdir()
(workspace_docs / "guide" / "overview.rst").write_text("Overview", encoding="utf-8")

sandbox_docs = tmp_path / "sandbox" / "module" / "docs"
sandbox_docs.mkdir(parents=True)
sandbox_docs.joinpath("index.rst").symlink_to(workspace_docs / "index.rst")
(sandbox_docs / "guide").mkdir()
sandbox_docs.joinpath("guide", "overview.rst").symlink_to(
workspace_docs / "guide" / "overview.rst"
)

spec = MountSpec(
src_root="module/docs", runtime_path="module/docs", mount_at="module"
)

entry = _make_mount_entry(sandbox_docs, spec)

assert entry["dir"] == str(workspace_docs)


def test_canonical_mount_dir_empty_bundle_fallback(tmp_path: Path) -> None:
"""A bundle with no .rst/.md files falls back to walk_dir.resolve()."""
bundle_dir = tmp_path / "bundle"
bundle_dir.mkdir()
(bundle_dir / "diagram.puml").write_text("@startuml\n@enduml", encoding="utf-8")

spec = MountSpec(
src_root="module/docs", runtime_path="module/docs", mount_at="module"
)

entry = _make_mount_entry(bundle_dir, spec)

assert entry["dir"] == str(bundle_dir.resolve())


def test_mount_entry_uses_canonical_directory_for_generated_data_bundle(
tmp_path: Path,
) -> None:
Expand Down
Loading