fix(extension): 产物收割排除代码副本+删 work 目录——输出契约校验语义不变
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -266,27 +266,39 @@ def _find_code_dir(ext_dir: Path) -> Path | None:
|
||||
return None
|
||||
|
||||
|
||||
def _copy_code_tree(src: Path, dst: Path) -> None:
|
||||
"""把代码树复制进可写目录(shutil.copytree,目标已存在)。"""
|
||||
def _copy_code_tree(src: Path, dst: Path) -> set[str]:
|
||||
"""把代码树复制进可写目录;返回原始代码相对路径集合(收割时排除)。"""
|
||||
import shutil
|
||||
rels: set[str] = set()
|
||||
if not src.is_dir():
|
||||
return
|
||||
for item in src.iterdir():
|
||||
dest = dst / item.name
|
||||
return rels
|
||||
for item in src.rglob("*"):
|
||||
rel = item.relative_to(src).as_posix()
|
||||
dest = dst / rel
|
||||
if item.is_dir():
|
||||
shutil.copytree(item, dest, dirs_exist_ok=True)
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
else:
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(item, dest)
|
||||
rels.add(rel)
|
||||
return rels
|
||||
|
||||
|
||||
def _merge_tree(src: Path, dst: Path) -> None:
|
||||
"""把 src 全部内容合并进 dst(含子目录;同名覆盖)。"""
|
||||
def _harvest_outputs(src: Path, dst: Path, exclude: set[str]) -> None:
|
||||
"""把 src 内产物(排除原始代码路径)合并进 dst,保留相对路径。"""
|
||||
import shutil
|
||||
for item in src.iterdir():
|
||||
dest = dst / item.name
|
||||
for item in src.rglob("*"):
|
||||
rel = item.relative_to(src).as_posix()
|
||||
if rel in exclude:
|
||||
continue
|
||||
# 排除路径是原始代码文件所在目录时也跳过其祖先目录本身
|
||||
if any(rel == e or rel.startswith(e + "/") for e in exclude):
|
||||
continue
|
||||
dest = dst / rel
|
||||
if item.is_dir():
|
||||
shutil.copytree(item, dest, dirs_exist_ok=True)
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
else:
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(item, dest)
|
||||
|
||||
|
||||
@@ -390,9 +402,9 @@ def main(argv: list[str] | None = None) -> int:
|
||||
# 2026-09-15 修复:代码挂载只读,但 18 用例语义是「cd 代码目录后脚本写
|
||||
# outputs/ 相对目录」。等价做法 = 把代码复制进可写 run_dir 执行,
|
||||
# 结束后把 run_dir 产物收割进 output_dir。显式 --work-dir 可覆盖。
|
||||
work_dir = Path(args.work_dir) if args.work_dir else (output_dir / "work")
|
||||
work_dir = Path(args.work_dir) if args.work_dir else (output_dir / "_work")
|
||||
work_dir.mkdir(parents=True, exist_ok=True)
|
||||
_copy_code_tree(code_dir, work_dir)
|
||||
code_rel_paths = _copy_code_tree(code_dir, work_dir)
|
||||
# 模板中 {code_dir} 指向可写副本(而非只读挂载)
|
||||
effective_code_dir = work_dir
|
||||
|
||||
@@ -439,9 +451,11 @@ def main(argv: list[str] | None = None) -> int:
|
||||
if code != EXIT_OK:
|
||||
print(f"[run_extension] command exited with code {code}", file=sys.stderr)
|
||||
return code
|
||||
# 收割:work_dir 内全部产物(含 outputs/ 子目录与中间文件)合并进 output_dir
|
||||
# 收割:work_dir 产物(排除原始代码文件)合并进 output_dir,然后删除 work 目录
|
||||
try:
|
||||
_merge_tree(work_dir, output_dir)
|
||||
_harvest_outputs(work_dir, output_dir, code_rel_paths)
|
||||
import shutil
|
||||
shutil.rmtree(work_dir, ignore_errors=True)
|
||||
except OSError as exc:
|
||||
print(f"[run_extension] 产物收割失败: {exc}", file=sys.stderr)
|
||||
return EXIT_SETUP
|
||||
|
||||
Reference in New Issue
Block a user