This commit is contained in:
Rome Thorstenson 2026-09-18 12:42:49 -06:00 committed by GitHub
commit 85c59dc9c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 80 additions and 4 deletions

View file

@ -814,6 +814,7 @@ def _classify_diff_entries(entries: list[DiffEntry]) -> dict[str, Any]:
analyzable_files: list[str] = []
analyzable_seen: set[str] = set()
modified_seen: set[str] = set()
added_seen: set[str] = set()
for entry in entries:
path = entry.path
@ -825,7 +826,7 @@ def _classify_diff_entries(entries: list[DiffEntry]) -> dict[str, Any]:
continue
if entry.status == "A":
added_files.append(path)
_append_unique(added_files, added_seen, path)
_append_unique(analyzable_files, analyzable_seen, path)
continue
@ -848,7 +849,7 @@ def _classify_diff_entries(entries: list[DiffEntry]) -> dict[str, Any]:
continue
if entry.status == "C":
_append_unique(modified_files, modified_seen, path)
_append_unique(added_files, added_seen, path)
_append_unique(analyzable_files, analyzable_seen, path)
continue
@ -1283,6 +1284,7 @@ def derive_local_base_name(path_str: str) -> str:
def assign_workspace_subdirs(targets_info: list[dict[str, Any]]) -> None:
name_counts: dict[str, int] = {}
allocated_subdirs: set[str] = set()
for target in targets_info:
target_type = target["type"]
@ -1298,10 +1300,22 @@ def assign_workspace_subdirs(targets_info: list[dict[str, Any]]) -> None:
continue
count = name_counts.get(base_name, 0) + 1
name_counts[base_name] = count
workspace_subdir = base_name if count == 1 else f"{base_name}-{count}"
# Avoid colliding with a subdir already allocated to another target
# (e.g. base names ["api-2", "api", "api"] would otherwise both map to "api-2").
# Track allocated subdirs separately from base-name counts so a derived
# suffix never poisons the count of a later target sharing that name.
max_attempts = len(targets_info) + 1
attempts = 0
while workspace_subdir in allocated_subdirs and attempts < max_attempts:
count += 1
workspace_subdir = f"{base_name}-{count}"
attempts += 1
name_counts[base_name] = count
allocated_subdirs.add(workspace_subdir)
details["workspace_subdir"] = workspace_subdir

View file

@ -0,0 +1,62 @@
"""Tests for diff classification and workspace-subdir assignment in interface.utils."""
from __future__ import annotations
from typing import Any
from strix.interface.utils import (
DiffEntry,
_classify_diff_entries,
assign_workspace_subdirs,
)
def _local_target(path: str) -> dict[str, Any]:
return {"type": "local_code", "details": {"target_path": path}}
def test_assign_workspace_subdirs_avoids_suffix_collision() -> None:
# Base names derive to ["api-2", "api", "api"]; the third target's naive
# suffix "api-2" would collide with the first, silently dropping a repo.
targets = [
_local_target("/srv/api-2"),
_local_target("/srv/api"),
_local_target("/other/api"),
]
assign_workspace_subdirs(targets)
subdirs = [t["details"]["workspace_subdir"] for t in targets]
assert len(set(subdirs)) == 3
assert subdirs[0] == "api-2"
assert subdirs[1] == "api"
assert subdirs[2] not in {"api-2", "api"}
def test_assign_workspace_subdirs_suffix_does_not_poison_later_base() -> None:
# Base names ["api", "api", "api-2"]: the second "api" target allocates the
# subdir "api-2"; the later real "api-2" target must still get a unique,
# non-colliding subdir without the earlier allocation poisoning its counter.
targets = [
_local_target("/srv/api"),
_local_target("/other/api"),
_local_target("/srv/api-2"),
]
assign_workspace_subdirs(targets)
subdirs = [t["details"]["workspace_subdir"] for t in targets]
assert len(set(subdirs)) == 3
assert subdirs[0] == "api"
assert subdirs[1] == "api-2"
assert subdirs[2].startswith("api-2")
def test_classify_diff_entries_copy_is_added_not_modified() -> None:
result = _classify_diff_entries(
[DiffEntry(status="C", path="new.py", old_path="orig.py", similarity=100)]
)
assert "new.py" in result["added_files"]
assert "new.py" not in result["modified_files"]
assert "new.py" in result["analyzable_files"]