Compare commits

..
2 changed files with 5 additions and 16 deletions
+5 -6
View File
@@ -47,7 +47,6 @@ EFFECTS_DIR = os.path.join(DATA_DIR, "effects")
_RUN_ID = re.compile(r"[a-f0-9]{32}") _RUN_ID = re.compile(r"[a-f0-9]{32}")
_TYPES = {"claim": EffectClaim, "outcome": EffectOutcome, "observation": Observation} _TYPES = {"claim": EffectClaim, "outcome": EffectOutcome, "observation": Observation}
_VERSION = 1 _VERSION = 1
_O_BINARY = getattr(os, "O_BINARY", 0) # Windows: raw os.open() is text-mode without it
def _fsync_directory(directory: str | os.PathLike) -> None: def _fsync_directory(directory: str | os.PathLike) -> None:
@@ -244,7 +243,7 @@ class EffectLog:
"""Hold the file exclusively with every durable record merged.""" """Hold the file exclusively with every durable record merged."""
assert self.path is not None assert self.path is not None
_ensure_directory(self.path.parent) _ensure_directory(self.path.parent)
flags = os.O_RDWR | os.O_APPEND | os.O_CREAT | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0) | _O_BINARY flags = os.O_RDWR | os.O_APPEND | os.O_CREAT | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0)
descriptor = os.open(self.path, flags, 0o600) descriptor = os.open(self.path, flags, 0o600)
try: try:
if fcntl is not None: if fcntl is not None:
@@ -359,7 +358,7 @@ class EffectLog:
with self._lock: with self._lock:
try: try:
descriptor = os.open(self.path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) descriptor = os.open(self.path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
| getattr(os, "O_CLOEXEC", 0) | _O_BINARY) | getattr(os, "O_CLOEXEC", 0))
except FileNotFoundError: except FileNotFoundError:
return return
except OSError: except OSError:
@@ -395,7 +394,7 @@ class EffectLog:
log = cls(run_id, directory=directory) log = cls(run_id, directory=directory)
assert log.path is not None assert log.path is not None
try: try:
descriptor = os.open(log.path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0) | _O_BINARY) descriptor = os.open(log.path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0))
except FileNotFoundError: except FileNotFoundError:
return log return log
except OSError as error: except OSError as error:
@@ -461,7 +460,7 @@ class EffectLog:
temporary = target.with_suffix(".tmp") temporary = target.with_suffix(".tmp")
data = json.dumps({"run_id": self.run_id, "effect_id": effect_id}, sort_keys=True).encode() data = json.dumps({"run_id": self.run_id, "effect_id": effect_id}, sort_keys=True).encode()
_ensure_directory(target.parent) _ensure_directory(target.parent)
flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0) | _O_BINARY flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0)
descriptor = os.open(temporary, flags, 0o600) descriptor = os.open(temporary, flags, 0o600)
try: try:
view = memoryview(data) view = memoryview(data)
@@ -479,7 +478,7 @@ class EffectLog:
return None return None
base = Path(directory) if directory is not None else effects_dir() base = Path(directory) if directory is not None else effects_dir()
try: try:
descriptor = os.open(base / f"launch-{generation}.json", os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | _O_BINARY) descriptor = os.open(base / f"launch-{generation}.json", os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0))
with os.fdopen(descriptor, "rb") as stream: with os.fdopen(descriptor, "rb") as stream:
if os.fstat(stream.fileno()).st_nlink != 1: if os.fstat(stream.fileno()).st_nlink != 1:
return None return None
-10
View File
@@ -344,13 +344,3 @@ def test_hardlinked_effect_state_is_control_plane_without_scanning_the_store(tmp
elsewhere.write_text("y") elsewhere.write_text("y")
os.link(elsewhere, workspace / "pnpm-style.txt") os.link(elsewhere, workspace / "pnpm-style.txt")
assert resources._control_plane_path(str(workspace / "pnpm-style.txt")) is True assert resources._control_plane_path(str(workspace / "pnpm-style.txt")) is True
def test_consecutive_claims_write_lf_only_records(tmp_path, target):
# Raw os.open() is text-mode on Windows unless O_BINARY is set; the \r\n it
# wrote made the next append read a stray empty line as a corrupt tail.
log = EffectLog(RUN, directory=tmp_path / "fx")
claim(log, target, "e1", "act-1")
claim(log, target, "e2", "act-2")
assert b"\r" not in log.path.read_bytes()
assert len(records(log.path)) == 2