Skip to content

Commit 55122a8

Browse files
committed
fix: prevent recursive dev-workspace nesting in multi-repo mode
- copytree ignore filter in _import_repo_into_workspace - blocked path segments guard in upload_delta_bundle - dev-workspace added to _ANY_DEPTH_EXCLUDE_DIR_NAMES - bump extension to 0.1.55
1 parent 6ddf870 commit 55122a8

File tree

4 files changed

+585
-551
lines changed

4 files changed

+585
-551
lines changed

scripts/ctx_cli/commands/quickstart.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,26 @@ def _import_repo_into_workspace(source: Path, dev_workspace: Path) -> Path:
169169
raise ValueError(f"Import target exists and is not a directory: {target}")
170170
return target
171171

172-
shutil.copytree(source, target, symlinks=True)
172+
# Exclude directories that cause recursive nesting loops or are never useful
173+
# inside an imported workspace copy. The most critical entry is "dev-workspace"
174+
# itself: without this filter, importing the Context-Engine repo creates
175+
# dev-workspace/<slug>/dev-workspace/<slug>/… ad infinitum.
176+
_IMPORT_EXCLUDE_DIRS = {
177+
"dev-workspace",
178+
".codebase",
179+
".git",
180+
"node_modules",
181+
".venv",
182+
"venv",
183+
"__pycache__",
184+
".cache",
185+
".remote-git",
186+
}
187+
188+
def _ignore_on_copy(directory: str, contents: list[str]) -> list[str]:
189+
return [name for name in contents if name in _IMPORT_EXCLUDE_DIRS]
190+
191+
shutil.copytree(source, target, symlinks=True, ignore=_ignore_on_copy)
173192
return target
174193

175194

scripts/ingest/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ def _env_truthy(val: str | None, default: bool) -> bool:
239239
".remote-git",
240240
".codebase",
241241
"node_modules",
242+
"dev-workspace",
242243
}
243244

244245

scripts/upload_delta_bundle.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
WORK_DIR = os.environ.get("WORK_DIR") or os.environ.get("WORKDIR") or "/work"
2727
_SLUGGED_REPO_RE = re.compile(r"^.+-[0-9a-f]{16}(?:_old)?$")
2828

29+
# Paths containing any of these segments are never materialized from bundles.
30+
# Prevents recursive nesting (e.g. dev-workspace/<slug>/dev-workspace/…).
31+
_BLOCKED_PATH_SEGMENTS = {"dev-workspace", ".codebase", ".remote-git"}
32+
2933

3034
def get_workspace_key(workspace_path: str) -> str:
3135
"""Generate 16-char hash for collision avoidance in remote uploads.
@@ -394,6 +398,16 @@ def _apply_operation_to_workspace(workspace_root: Path) -> bool:
394398

395399
rel_path = sanitized_path
396400

401+
# Block paths that would create recursive nesting
402+
_path_parts = set(rel_path.replace("\\", "/").split("/"))
403+
if _path_parts & _BLOCKED_PATH_SEGMENTS:
404+
logger.debug(
405+
f"[upload_service] Blocking {op_type} for {rel_path}: "
406+
"contains a blocked path segment.",
407+
)
408+
operations_count["skipped"] += 1
409+
continue
410+
397411
replica_results: Dict[str, bool] = {}
398412
for slug, root in replica_roots.items():
399413
result = _apply_operation_to_workspace(root)

0 commit comments

Comments
 (0)