about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2022-09-07 02:18:47 +0200
committerProfpatsch <mail@profpatsch.de>2022-11-04 18:14:33 +0100
commita64a9d5552a62627ccb562c6f5ffa9c6312726e1 (patch)
treee2b4346d3b0c0026cf673dfc0a8e73a86cb5d019 /pkgs
parent26cb66b681f5df87c431868de4459103bb7446c4 (diff)
tree-sitter/update: Write files atomically
Otherwise you can’t interrupt the process without creating
broken/half-written files.
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/development/tools/parsing/tree-sitter/update.nix30
1 files changed, 28 insertions, 2 deletions
diff --git a/pkgs/development/tools/parsing/tree-sitter/update.nix b/pkgs/development/tools/parsing/tree-sitter/update.nix
index fb21f16d0657d..97e68b9814142 100644
--- a/pkgs/development/tools/parsing/tree-sitter/update.nix
+++ b/pkgs/development/tools/parsing/tree-sitter/update.nix
@@ -430,8 +430,9 @@ let
     mkdir -p "$outputDir"
     ${foreachSh allGrammars
       ({name, orga, repo}: ''
-        ${fetchImpl} fetch-repo '${lib.generators.toJSON {} {inherit orga repo;}}' \
-          > $outputDir/${name}.json
+        ${atomically-write} \
+          $outputDir/${name}.json \
+          ${fetchImpl} fetch-repo '${lib.generators.toJSON {} {inherit orga repo;}}'
       '')}
     ( echo "{ lib }:"
       echo "{"
@@ -443,5 +444,30 @@ let
       > "$outputDir/default.nix"
   '';
 
+  # 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