Browse Source

fix: preserve competing import destinations

master
Codex 2 months ago
parent
commit
27ff4012d4
  1. 20
      ingestion/guided_imports.py

20
ingestion/guided_imports.py

@ -1,5 +1,6 @@
"""Safe discovery of local source documents for the guided import workflow.""" """Safe discovery of local source documents for the guided import workflow."""
import ctypes
import os import os
import stat import stat
from contextlib import contextmanager from contextlib import contextmanager
@ -157,6 +158,20 @@ def _validate_name(name: str) -> None:
raise ParseError("UNREADABLE_FILE") raise ParseError("UNREADABLE_FILE")
def _rename_without_replacement(name: str, source_fd: int, destination_fd: int) -> None:
# The supported Docker runtime is Linux. Fail closed if atomic no-replace
# rename is unavailable instead of falling back to a check-then-replace race.
try:
rename = ctypes.CDLL(None, use_errno=True).renameat2
except AttributeError:
raise ParseError("UNREADABLE_FILE") from None
rename.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_uint]
rename.restype = ctypes.c_int
encoded_name = os.fsencode(name)
if rename(source_fd, encoded_name, destination_fd, encoded_name, 1) != 0: # RENAME_NOREPLACE
raise OSError(ctypes.get_errno(), "Cannot move import source")
def _move_file(name: str, source: str | None, destination: str | None, *, overwrite=False) -> None: def _move_file(name: str, source: str | None, destination: str | None, *, overwrite=False) -> None:
_validate_name(name) _validate_name(name)
with _directory(source) as source_fd, _directory(destination) as destination_fd: with _directory(source) as source_fd, _directory(destination) as destination_fd:
@ -175,7 +190,10 @@ def _move_file(name: str, source: str | None, destination: str | None, *, overwr
else: else:
if not overwrite or not stat.S_ISREG(target.st_mode): if not overwrite or not stat.S_ISREG(target.st_mode):
raise ParseError("UNREADABLE_FILE") raise ParseError("UNREADABLE_FILE")
os.replace(name, name, src_dir_fd=source_fd, dst_dir_fd=destination_fd) if overwrite:
os.replace(name, name, src_dir_fd=source_fd, dst_dir_fd=destination_fd)
else:
_rename_without_replacement(name, source_fd, destination_fd)
def _recover_staging() -> None: def _recover_staging() -> None:

Loading…
Cancel
Save