diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-12 16:49:01 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-12 16:49:01 +1000 |
| commit | a53a2568ec6e4e53d32a48443f50eee9d9fb8fcd (patch) | |
| tree | 73a2ecf05724309738f783fc5ed20514768fc624 | |
| parent | material: better mono scheme (diff) | |
| download | caelestia-cli-a53a2568ec6e4e53d32a48443f50eee9d9fb8fcd.tar.gz caelestia-cli-a53a2568ec6e4e53d32a48443f50eee9d9fb8fcd.tar.bz2 caelestia-cli-a53a2568ec6e4e53d32a48443f50eee9d9fb8fcd.zip | |
scheme: fix not saving atomically
Causes programs which rely on the save file (e.g. the shell) to fail occasionally as they try to read while the cli is writing
| -rw-r--r-- | src/caelestia/utils/paths.py | 10 | ||||
| -rw-r--r-- | src/caelestia/utils/scheme.py | 23 |
2 files changed, 21 insertions, 12 deletions
diff --git a/src/caelestia/utils/paths.py b/src/caelestia/utils/paths.py index 6a6e0a8..3b5a7a6 100644 --- a/src/caelestia/utils/paths.py +++ b/src/caelestia/utils/paths.py @@ -1,5 +1,8 @@ import hashlib +import json import os +import shutil +import tempfile from pathlib import Path config_dir = Path(os.getenv("XDG_CONFIG_HOME", Path.home() / ".config")) @@ -31,3 +34,10 @@ def compute_hash(path: str) -> str: sha.update(chunk) return sha.hexdigest() + + +def atomic_dump(path: Path, content: dict[str, any]) -> None: + with tempfile.NamedTemporaryFile("w") as f: + json.dump(content, f) + f.flush() + shutil.move(f.name, path) diff --git a/src/caelestia/utils/scheme.py b/src/caelestia/utils/scheme.py index c978231..9027589 100644 --- a/src/caelestia/utils/scheme.py +++ b/src/caelestia/utils/scheme.py @@ -3,7 +3,7 @@ import random from pathlib import Path from caelestia.utils.material import get_colours_for_image -from caelestia.utils.paths import scheme_data_dir, scheme_path +from caelestia.utils.paths import atomic_dump, scheme_data_dir, scheme_path class Scheme: @@ -100,17 +100,16 @@ class Scheme: def save(self) -> None: scheme_path.parent.mkdir(parents=True, exist_ok=True) - with scheme_path.open("w") as f: - json.dump( - { - "name": self.name, - "flavour": self.flavour, - "mode": self.mode, - "variant": self.variant, - "colours": self.colours, - }, - f, - ) + atomic_dump( + scheme_path, + { + "name": self.name, + "flavour": self.flavour, + "mode": self.mode, + "variant": self.variant, + "colours": self.colours, + }, + ) def set_random(self) -> None: self._name = random.choice(get_scheme_names()) |