lol

tree-sitter/update: Fetch repositories in parallel

This was the main annoyance with the existing script, it would fetch
one repository after the other instead of multiple in parallel.
The `xe` tool is a simple `xargs`-like that can do that.

We put the json information for all repositories into a file with one
object per line, then pass that to xe.

+34 -18
+31 -17
pkgs/development/tools/parsing/tree-sitter/update.nix
··· 419 419 lib.concatMapStringsSep "\n" f 420 420 (lib.mapAttrsToList (k: v: { name = k; } // v) attrs); 421 421 422 + jsonNewlines = lib.concatMapStringsSep "\n" (lib.generators.toJSON {}); 423 + 424 + # Run the given script for each of the attr list. 425 + # The attrs are passed to the script as a json value. 426 + forEachParallel = name: script: listOfAttrs: writeShellScript "for-each-parallel.sh" '' 427 + < ${writeText "${name}.json" (jsonNewlines listOfAttrs)} \ 428 + ${xe}/bin/xe -F -j5 ${script} {} 429 + ''; 430 + 431 + outputDir = "${toString ./.}/grammars"; 422 432 update-all-grammars = writeShellScript "update-all-grammars.sh" '' 423 433 set -euo pipefail 424 434 echo "fetching list of grammars" 1>&2 425 435 treeSitterRepos=$(${fetchImpl} fetch-orga-latest-repos '{"orga": "tree-sitter"}') 426 436 echo "checking the tree-sitter repo list against the grammars we know" 1>&2 427 437 printf '%s' "$treeSitterRepos" | ${checkTreeSitterRepos} 428 - outputDir="${toString ./.}/grammars" 429 - echo "writing files to $outputDir" 1>&2 430 - mkdir -p "$outputDir" 431 - ${foreachSh allGrammars 432 - ({name, orga, repo}: '' 433 - ${atomically-write} \ 434 - $outputDir/${name}.json \ 435 - ${fetchImpl} fetch-repo '${lib.generators.toJSON {} {inherit orga repo;}}' 436 - '')} 437 - ( echo "{ lib }:" 438 - echo "{" 439 - ${foreachSh allGrammars 440 - ({name, ...}: '' 441 - # indentation hack 442 - printf " %s = lib.importJSON ./%s.json;\n" "${name}" "${name}"'')} 443 - echo "}" ) \ 444 - > "$outputDir/default.nix" 438 + echo "writing files to ${outputDir}" 1>&2 439 + mkdir -p "${outputDir}" 440 + ${forEachParallel 441 + "repos-to-fetch" 442 + (writeShellScript "fetch-repo" '' 443 + ${atomically-write} \ 444 + "${outputDir}/$(jq --raw-output --null-input '$ARGS.positional[0].name' --jsonargs "$1").json" \ 445 + ${fetchImpl} fetch-repo "$1" 446 + '') 447 + (lib.mapAttrsToList (name: attrs: attrs // { inherit name; }) allGrammars) 448 + } 449 + ${atomically-write} \ 450 + "${outputDir}/default.nix" \ 451 + ${writeShellScript "print-all-grammars" '' 452 + echo "{ lib }:" 453 + echo "{" 454 + ${foreachSh allGrammars 455 + ({name, ...}: '' 456 + printf " %s = lib.importJSON ./%s.json;\n" "${name}" "${name}"'')} 457 + echo "}" 458 + ''} 445 459 ''; 446 460 447 461 # Atomically write a file (just `>` redirection in bash
+3 -1
pkgs/development/tools/parsing/tree-sitter/update_impl.py
··· 19 19 """Query the github API via curl""" 20 20 if not debug: 21 21 yield "--silent" 22 + # follow redirects 23 + yield "--location" 22 24 if token: 23 25 yield "-H" 24 26 yield f"Authorization: token {token}" ··· 79 81 case {"tag_name": tag_name}: 80 82 release = tag_name 81 83 case _: 82 - sys.exit("git result did not have a `tag_name` field") 84 + sys.exit(f"git result for {orga}/{repo} did not have a `tag_name` field") 83 85 84 86 print(f"Fetching latest release ({release}) of {orga}/{repo} …", file=sys.stderr) 85 87 res = run_bin(