fix(deploy-win): don't re-patch an already-patched ISO
deploy-win patched its input into vm_dir/install-noprompt.iso and only its own sidecar cache could skip the repack — so feeding an already-patched ISO (e.g. from `template patch-win-iso`, or via --win-iso) triggered a wasteful second extract+repack that double-injected the answer files. deploy-win now detects a patched input (autounattend.xml present at the ISO root via `iso_patch.iso_has_root_file`) and uses it as-is, skipping Step 4. Raw ISOs are still patched once and cached as before.
This commit is contained in:
@@ -2256,24 +2256,29 @@ def template_deploy_win(
|
||||
# ── Step 4: patch ISO (inject answer files + no-prompt boot) ───────────────
|
||||
_deploy_step("Step 4: patch ISO (inject autounattend + no-prompt boot)", 4, start_from_step)
|
||||
if start_from_step <= 4:
|
||||
key = _patched_iso_inputs_key(base_iso, autounattend_xml, post_install_ps1)
|
||||
sidecar = patched_iso.with_suffix(patched_iso.suffix + ".inputs")
|
||||
cached = (
|
||||
patched_iso.is_file()
|
||||
and sidecar.is_file()
|
||||
and sidecar.read_text(encoding="utf-8").strip() == key
|
||||
)
|
||||
if cached:
|
||||
click.echo(f" [OK] patched ISO up to date — skipping repack: {patched_iso}")
|
||||
if win_iso_patch.iso_has_root_file(base_iso, "autounattend.xml"):
|
||||
# Already patched (e.g. produced by `template patch-win-iso`) — use as-is.
|
||||
click.echo(f" [OK] ISO already patched (autounattend.xml present) — using as-is: {base_iso}")
|
||||
patched_iso = base_iso
|
||||
else:
|
||||
win_iso_patch.patch_iso(
|
||||
base_iso,
|
||||
autounattend_xml=autounattend_xml,
|
||||
post_install_ps1=post_install_ps1,
|
||||
out_iso=patched_iso,
|
||||
work_dir=vm_dir,
|
||||
key = _patched_iso_inputs_key(base_iso, autounattend_xml, post_install_ps1)
|
||||
sidecar = patched_iso.with_suffix(patched_iso.suffix + ".inputs")
|
||||
cached = (
|
||||
patched_iso.is_file()
|
||||
and sidecar.is_file()
|
||||
and sidecar.read_text(encoding="utf-8").strip() == key
|
||||
)
|
||||
sidecar.write_text(key, encoding="utf-8")
|
||||
if cached:
|
||||
click.echo(f" [OK] patched ISO up to date — skipping repack: {patched_iso}")
|
||||
else:
|
||||
win_iso_patch.patch_iso(
|
||||
base_iso,
|
||||
autounattend_xml=autounattend_xml,
|
||||
post_install_ps1=post_install_ps1,
|
||||
out_iso=patched_iso,
|
||||
work_dir=vm_dir,
|
||||
)
|
||||
sidecar.write_text(key, encoding="utf-8")
|
||||
|
||||
# ── Step 5: create VMDK ────────────────────────────────────────────────────
|
||||
_deploy_step("Step 5: create VMDK", 5, start_from_step)
|
||||
|
||||
@@ -38,6 +38,18 @@ def _require_7z() -> str:
|
||||
raise click.ClickException("7z not found. Install p7zip-full.")
|
||||
|
||||
|
||||
def iso_has_root_file(iso: Path, name: str) -> bool:
|
||||
"""True if ``name`` exists at the root of ``iso`` (used to detect a patched ISO)."""
|
||||
sevenz = _require_7z()
|
||||
proc = subprocess.run(
|
||||
[sevenz, "l", str(iso), f"-i!{name}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
return proc.returncode == 0 and name.lower() in proc.stdout.lower()
|
||||
|
||||
|
||||
def _read_volid(base_iso: Path) -> str:
|
||||
"""Read the ISO volume id (label); fall back to a sane default."""
|
||||
label = ""
|
||||
|
||||
Reference in New Issue
Block a user