summary refs log tree commit diff
path: root/pkgs/development/tools/parsing
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2022-09-12 22:07:20 +0200
committerProfpatsch <mail@profpatsch.de>2022-11-04 18:14:33 +0100
commit3b0b6d1b612e85b7aebcb089e8c59b8614c21a05 (patch)
tree56c02a836a2985c9426b8a3415de9a17ecec03a3 /pkgs/development/tools/parsing
parent484bce31b7cf3541e01835545453c7545d20d043 (diff)
tree-sitter/update: move atomically-write to python
It should do the same thing, but take with a grain of salt maybe.
Diffstat (limited to 'pkgs/development/tools/parsing')
-rw-r--r--pkgs/development/tools/parsing/tree-sitter/update.nix25
-rw-r--r--pkgs/development/tools/parsing/tree-sitter/update_impl.py62
2 files changed, 34 insertions, 53 deletions
diff --git a/pkgs/development/tools/parsing/tree-sitter/update.nix b/pkgs/development/tools/parsing/tree-sitter/update.nix
index 055f42dc720a3..78b07c59d44e5 100644
--- a/pkgs/development/tools/parsing/tree-sitter/update.nix
+++ b/pkgs/development/tools/parsing/tree-sitter/update.nix
@@ -392,7 +392,6 @@ let
       binaries = {
         curl = "${curl}/bin/curl";
         nix-prefetch-git = "${nix-prefetch-git}/bin/nix-prefetch-git";
-        inherit atomically-write;
         printf = "${coreutils}/bin/printf";
       };
       inherit
@@ -460,30 +459,6 @@ let
     })"
   '';
 
-  # Atomically write a file (just `>` redirection in bash
-  # empties a file even if the command crashes).
-  #
-  # Maybe there is an existing tool for that?
-  # But it’s easy enough to implement.
-  #
-  # Example:
-  #   atomically-write
-  #     ./to
-  #     echo "foo"
-  #
-  # will atomically write the string "foo" into ./to
-  atomically-write = writeShellScript "atomically-write" ''
-    set -e
-    to=$1
-    shift
-    # assumes that the tempfile is on the same file system, (or in memory)
-    # for the `mv` at the end to be more-or-less atomic.
-    tmp=$(${coreutils}/bin/mktemp -d)
-    trap 'rm -r "$tmp"' EXIT
-    "$@" \
-      > "$tmp/out"
-    mv "$tmp/out" "$to"
-  '';
 
 in
 update-all-grammars
diff --git a/pkgs/development/tools/parsing/tree-sitter/update_impl.py b/pkgs/development/tools/parsing/tree-sitter/update_impl.py
index e9113c1ebd31b..92db75ef6502b 100644
--- a/pkgs/development/tools/parsing/tree-sitter/update_impl.py
+++ b/pkgs/development/tools/parsing/tree-sitter/update_impl.py
@@ -4,6 +4,7 @@ import subprocess as sub
 import os
 import sys
 from typing import Iterator, Any, Literal, TypedDict
+from tempfile import NamedTemporaryFile
 
 debug: bool = True if os.environ.get("DEBUG", False) else False
 Bin = str
@@ -20,6 +21,23 @@ def log(msg: str) -> None:
     print(msg, file=sys.stderr)
 
 
+def atomically_write(file_path: str, content: bytes) -> None:
+    """atomically write the content into `file_path`"""
+    with NamedTemporaryFile(
+        # write to the parent dir, so that it’s guaranteed to be on the same filesystem
+        dir=os.path.dirname(file_path),
+        delete=False
+    ) as tmp:
+        try:
+            tmp.write(content)
+            os.rename(
+                src=tmp.name,
+                dst=file_path
+            )
+        except Exception:
+            os.unlink(tmp.name)
+
+
 def curl_github_args(token: str | None, url: str) -> Args:
     """Query the github API via curl"""
     yield bins["curl"]
@@ -69,12 +87,6 @@ def run_cmd(args: Args) -> bytes:
 Dir = str
 
 
-def atomically_write_args(to: Dir, cmd: Args) -> Args:
-    yield bins["atomically-write"]
-    yield to
-    yield from cmd
-
-
 def fetchRepo() -> None:
     """fetch the given repo and write its nix-prefetch output to the corresponding grammar json file"""
     match jsonArg:
@@ -104,19 +116,18 @@ def fetchRepo() -> None:
 
             log(f"Fetching latest release ({release}) of {orga}/{repo} …")
             res = run_cmd(
-                atomically_write_args(
-                    os.path.join(
-                        outputDir,
-                        f"{nixRepoAttrName}.json"
-                    ),
-                    nix_prefetch_git_args(
-                        url=f"https://github.com/{quote(orga)}/{quote(repo)}",
-                        version_rev=release
-
-                    )
+                nix_prefetch_git_args(
+                    url=f"https://github.com/{quote(orga)}/{quote(repo)}",
+                    version_rev=release
                 )
             )
-            sys.stdout.buffer.write(res)
+            atomically_write(
+                file_path=os.path.join(
+                    outputDir,
+                    f"{nixRepoAttrName}.json"
+                ),
+                content=res
+            )
         case _:
             sys.exit("input json must have `orga` and `repo` keys")
 
@@ -184,18 +195,13 @@ def printAllGrammarsNixFile() -> None:
         yield "}"
         yield ""
 
-    out = run_cmd(
-        # TODO: implement atomic file write in python
-        atomically_write_args(
-            os.path.join(
-                outputDir,
-                "default.nix"
-            ),
-            iter([bins["printf"], "%s", "\n".join(list(file()))])
-        )
+    atomically_write(
+        file_path=os.path.join(
+            outputDir,
+            "default.nix"
+        ),
+        content="\n".join(file()).encode()
     )
-    if out:
-        log(str(out))
 
 
 match mode: