fix(ssh): narrow symlink fallback to WinError 1314 only

The previous catch-all except OSError would silently swallow real
errors (disk full, bad path, permission issues unrelated to symlink
privilege). Narrow the handler to winerror == 1314 — the specific
Windows error code for "A required privilege is not held by the
client" — and re-raise every other OSError so genuine failures are
not hidden.
This commit is contained in:
kewe63
2026-04-13 15:20:17 +03:00
committed by Teknium
parent 46abf04012
commit dfe6fbb0b3

View File

@ -179,8 +179,10 @@ class SSHEnvironment(BaseEnvironment):
raise RuntimeError(f"remote mkdir failed: {result.stderr.strip()}") raise RuntimeError(f"remote mkdir failed: {result.stderr.strip()}")
# Symlink staging avoids fragile GNU tar --transform rules. # Symlink staging avoids fragile GNU tar --transform rules.
# On Windows, symlink creation requires admin rights or Developer Mode, # On Windows without Developer Mode, symlink creation raises
# so fall back to copying the file when os.symlink raises OSError. # OSError with winerror 1314 (privilege not held). Catch only
# that specific error and fall back to a plain copy; all other
# OSErrors (e.g. disk full, bad path) are re-raised as normal.
with tempfile.TemporaryDirectory(prefix="hermes-ssh-bulk-") as staging: with tempfile.TemporaryDirectory(prefix="hermes-ssh-bulk-") as staging:
for host_path, remote_path in files: for host_path, remote_path in files:
try: try:
@ -199,8 +201,12 @@ class SSHEnvironment(BaseEnvironment):
os.makedirs(os.path.dirname(staged), exist_ok=True) os.makedirs(os.path.dirname(staged), exist_ok=True)
try: try:
os.symlink(os.path.abspath(host_path), staged) os.symlink(os.path.abspath(host_path), staged)
except OSError: except OSError as e:
shutil.copy2(host_path, staged) # WinError 1314: symlink privilege not held (Windows without Dev Mode)
if getattr(e, "winerror", None) == 1314:
shutil.copy2(host_path, staged)
else:
raise
tar_cmd = ["tar", "-chf", "-", "-C", staging, "."] tar_cmd = ["tar", "-chf", "-", "-C", staging, "."]
ssh_cmd = self._build_ssh_command() ssh_cmd = self._build_ssh_command()