mirror of
https://github.com/usestrix/strix.git
synced 2026-10-12 03:47:56 +00:00
fix: dedupe local targets so a dir is never both copied and mounted
If the same directory is passed via --target and --mount (or as duplicate values), it previously produced two targets — copied AND bind-mounted, and the copied one could trip the size pre-flight. Dedupe by resolved path, preferring the bind mount.
This commit is contained in:
parent
8e30ad68c9
commit
cd4b6c7a68
3 changed files with 60 additions and 0 deletions
|
|
@ -37,6 +37,7 @@ from strix.interface.utils import (
|
|||
check_docker_connection,
|
||||
clone_repository,
|
||||
collect_local_sources,
|
||||
dedupe_local_targets,
|
||||
find_oversized_local_targets,
|
||||
generate_run_name,
|
||||
image_exists,
|
||||
|
|
@ -507,6 +508,8 @@ Examples:
|
|||
except ValueError as e:
|
||||
parser.error(str(e))
|
||||
|
||||
args.targets_info = dedupe_local_targets(args.targets_info)
|
||||
|
||||
assign_workspace_subdirs(args.targets_info)
|
||||
rewrite_localhost_targets(args.targets_info, HOST_GATEWAY_HOSTNAME)
|
||||
|
||||
|
|
|
|||
|
|
@ -1290,6 +1290,31 @@ def build_mount_targets_info(mount_paths: list[str]) -> list[dict[str, Any]]:
|
|||
return targets_info
|
||||
|
||||
|
||||
def dedupe_local_targets(targets_info: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
"""Collapse local_code targets that resolve to the same path.
|
||||
|
||||
When a directory is supplied both as a copied ``--target`` and via
|
||||
``--mount`` (or as duplicate values of either), keep one entry and prefer
|
||||
the bind-mounted one — so the same tree is never both streamed in and
|
||||
mounted. Order is preserved; non-local targets pass through untouched.
|
||||
"""
|
||||
result: list[dict[str, Any]] = []
|
||||
index_by_path: dict[str, int] = {}
|
||||
for target in targets_info:
|
||||
details = target.get("details") or {}
|
||||
path = details.get("target_path")
|
||||
if target.get("type") != "local_code" or not path:
|
||||
result.append(target)
|
||||
continue
|
||||
existing = index_by_path.get(path)
|
||||
if existing is None:
|
||||
index_by_path[path] = len(result)
|
||||
result.append(target)
|
||||
elif details.get("mount") and not (result[existing].get("details") or {}).get("mount"):
|
||||
result[existing] = target # bind mount supersedes the copied entry
|
||||
return result
|
||||
|
||||
|
||||
def _is_localhost_host(host: str) -> bool:
|
||||
host_lower = host.lower().strip("[]")
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ if TYPE_CHECKING:
|
|||
from strix.interface.utils import (
|
||||
build_mount_targets_info,
|
||||
collect_local_sources,
|
||||
dedupe_local_targets,
|
||||
directory_size_bytes,
|
||||
find_oversized_local_targets,
|
||||
)
|
||||
|
|
@ -122,3 +123,34 @@ def test_build_mount_targets_info_rejects_empty_path(empty: str) -> None:
|
|||
# and silently bind-mount it into the sandbox.
|
||||
with pytest.raises(ValueError, match="must not be empty"):
|
||||
build_mount_targets_info([empty])
|
||||
|
||||
|
||||
def test_dedupe_keeps_distinct_targets_in_order() -> None:
|
||||
targets = [
|
||||
_local_target("/a"),
|
||||
{"type": "web_application", "details": {"target_url": "https://x"}},
|
||||
_local_target("/b", mount=True),
|
||||
]
|
||||
assert dedupe_local_targets(targets) == targets
|
||||
|
||||
|
||||
def test_dedupe_mount_supersedes_copied_same_path() -> None:
|
||||
copied = _local_target("/repo")
|
||||
mounted = _local_target("/repo", mount=True)
|
||||
|
||||
# Copied first, then mounted: the single surviving entry is the mount.
|
||||
result = dedupe_local_targets([copied, mounted])
|
||||
assert len(result) == 1
|
||||
assert result[0]["details"]["mount"] is True
|
||||
|
||||
# Order-independent: mounted first, copied second also yields the mount.
|
||||
result_rev = dedupe_local_targets([mounted, copied])
|
||||
assert len(result_rev) == 1
|
||||
assert result_rev[0]["details"]["mount"] is True
|
||||
|
||||
|
||||
def test_dedupe_collapses_duplicate_mounts() -> None:
|
||||
result = dedupe_local_targets(
|
||||
[_local_target("/repo", mount=True), _local_target("/repo", mount=True)]
|
||||
)
|
||||
assert len(result) == 1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue