Generate flake.nix from module options. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix inputs

move npins bash to file (#75)

authored by oeiuwq.com and committed by

GitHub 8a5c8771 a12af104

+103 -103
+7 -103
modules/npins/default.nix
··· 11 11 # Seed the runtime queue with one tab-separated "name\turl" line per declared input. 12 12 queueSeed = 13 13 let 14 - lines = lib.mapAttrsToList ( 15 - name: input: " printf '%s\\t%s\\n' ${esc name} ${esc (input.url or "")}" 16 - ) pinnableInputs; 17 - in 18 - "{\n" + lib.concatStringsSep "\n" lines + "\n} >> \"$QUEUE_FILE\""; 14 + lines = lib.mapAttrsToList (name: input: "${name}\t${input.url or ""}") pinnableInputs; 15 + in lib.concatStringsSep "\n" lines; 19 16 20 17 write-npins = 21 18 pkgs: ··· 27 24 pkgs.curl 28 25 pkgs.nix 29 26 ]; 30 - text = '' 31 - cd ${flake-file.intoPath} 32 - npins init --bare 2>/dev/null || true 33 - 34 - SEEN_FILE=$(mktemp) 35 - QUEUE_FILE=$(mktemp) 36 - trap 'rm -f "$SEEN_FILE" "$QUEUE_FILE"' EXIT 37 - 38 - # Add a pin by its flake-style URL (github:o/r, gitlab:o/r, channel URL, etc.) 39 - npins_add_url() { 40 - local name="$1" url="$2" spec owner repo ref channel 41 - case "$url" in 42 - github:*) 43 - spec="''${url#github:}" owner="''${spec%%/*}" spec="''${spec#*/}" 44 - repo="''${spec%%/*}" ref="''${spec#*/}" 45 - if [ "$ref" != "$repo" ]; then 46 - npins add github --name "$name" -b "$ref" "$owner" "$repo" 47 - else 48 - # No explicit ref: prefer a release tag, fall back to common branches. 49 - npins add github --name "$name" "$owner" "$repo" 2>/dev/null \ 50 - || npins add github --name "$name" -b main "$owner" "$repo" 2>/dev/null \ 51 - || npins add github --name "$name" -b master "$owner" "$repo" 52 - fi ;; 53 - gitlab:*) 54 - spec="''${url#gitlab:}" owner="''${spec%%/*}" spec="''${spec#*/}" 55 - repo="''${spec%%/*}" ref="''${spec#*/}" 56 - if [ "$ref" != "$repo" ]; then 57 - npins add gitlab --name "$name" -b "$ref" "$owner" "$repo" 58 - else 59 - npins add gitlab --name "$name" "$owner" "$repo" 2>/dev/null \ 60 - || npins add gitlab --name "$name" -b main "$owner" "$repo" 2>/dev/null \ 61 - || npins add gitlab --name "$name" -b master "$owner" "$repo" 62 - fi ;; 63 - https://channels.nixos.org/*|https://releases.nixos.org/*) 64 - channel=$(printf '%s' "$url" | sed 's|https://[^/]*/||;s|/.*||') 65 - npins add channel --name "$name" "$channel" ;; 66 - https://*|http://*) 67 - npins add tarball --name "$name" "$url" ;; 68 - *) 69 - npins add git --name "$name" "$url" ;; 70 - esac 71 - } 72 - 73 - # Fetch a github input's flake.nix and append its deps to QUEUE_FILE. 74 - discover_transitive() { 75 - local name="$1" url="$2" spec owner repo ref 76 - [[ "$url" != github:* ]] && return 0 77 - spec="''${url#github:}" owner="''${spec%%/*}" spec="''${spec#*/}" 78 - repo="''${spec%%/*}" ref="''${spec#*/}" 79 - [ "$ref" = "$repo" ] && ref="HEAD" 80 - 81 - local flake_tmp nix_tmp 82 - flake_tmp=$(mktemp --suffix=.nix) 83 - nix_tmp=$(mktemp --suffix=.nix) 84 - 85 - curl -sf "https://raw.githubusercontent.com/''${owner}/''${repo}/''${ref}/flake.nix" \ 86 - > "$flake_tmp" || { rm -f "$flake_tmp" "$nix_tmp"; return 0; } 87 - 88 - # Write a nix expression that extracts just the inputs URLs (no network at eval time). 89 - printf 'let f = import %s; norm = v: if builtins.isString v then v else v.url or ""; in builtins.mapAttrs (_: norm) (f.inputs or {})\n' \ 90 - "$flake_tmp" > "$nix_tmp" 91 - 92 - nix-instantiate --eval --strict --json "$nix_tmp" 2>/dev/null \ 93 - | jq -r 'to_entries[] | select(.value != "") | [.key, .value] | @tsv' \ 94 - >> "$QUEUE_FILE" || true 95 - 96 - rm -f "$flake_tmp" "$nix_tmp" 97 - } 98 - 99 - # Seed the BFS queue with all declared inputs. 100 - ${queueSeed} 101 - 102 - # BFS: process queue items until none remain unvisited. 103 - while true; do 104 - name="" url="" 105 - while IFS=$'\t' read -r qname qurl; do 106 - if ! grep -qxF "$qname" "$SEEN_FILE" 2>/dev/null; then 107 - name="$qname" url="$qurl" 108 - break 109 - fi 110 - done < "$QUEUE_FILE" 111 - [ -z "$name" ] && break 112 - printf '%s\n' "$name" >> "$SEEN_FILE" 113 - if ! jq -e --arg n "$name" '.pins | has($n)' npins/sources.json >/dev/null 2>&1; then 114 - npins_add_url "$name" "$url" || true 115 - fi 116 - discover_transitive "$name" "$url" 117 - done 118 - 119 - # Remove any pins that were not reachable in this run. 120 - if [ -f npins/sources.json ]; then 121 - for existing in $(jq -r '.pins | keys[]' npins/sources.json); do 122 - if ! grep -qxF "$existing" "$SEEN_FILE"; then 123 - npins remove "$existing" 124 - fi 125 - done 126 - fi 127 - ''; 27 + runtimeEnv = { 28 + out = flake-file.intoPath; 29 + inherit queueSeed; 30 + }; 31 + text = builtins.readFile ./npins.bash; 128 32 }; 129 33 in 130 34 {
+96
modules/npins/npins.bash
··· 1 + cd "$out" 2 + npins init --bare 2>/dev/null || true 3 + 4 + SEEN_FILE=$(mktemp) 5 + QUEUE_FILE=$(mktemp) 6 + trap 'rm -f "$SEEN_FILE" "$QUEUE_FILE"' EXIT 7 + 8 + # Seed the BFS queue with all declared inputs. 9 + echo "$queueSeed" > "$QUEUE_FILE" 10 + 11 + # Add a pin by its flake-style URL (github:o/r, gitlab:o/r, channel URL, etc.) 12 + npins_add_url() { 13 + local name="$1" url="$2" spec owner repo ref channel 14 + case "$url" in 15 + github:*) 16 + spec="${url#github:}" owner="${spec%%/*}" spec="${spec#*/}" 17 + repo="${spec%%/*}" ref="${spec#*/}" 18 + if [ "$ref" != "$repo" ]; then 19 + npins add github --name "$name" -b "$ref" "$owner" "$repo" 20 + else 21 + # No explicit ref: prefer a release tag, fall back to common branches. 22 + npins add github --name "$name" "$owner" "$repo" 2>/dev/null \ 23 + || npins add github --name "$name" -b main "$owner" "$repo" 2>/dev/null \ 24 + || npins add github --name "$name" -b master "$owner" "$repo" 25 + fi ;; 26 + gitlab:*) 27 + spec="${url#gitlab:}" owner="${spec%%/*}" spec="${spec#*/}" 28 + repo="${spec%%/*}" ref="${spec#*/}" 29 + if [ "$ref" != "$repo" ]; then 30 + npins add gitlab --name "$name" -b "$ref" "$owner" "$repo" 31 + else 32 + npins add gitlab --name "$name" "$owner" "$repo" 2>/dev/null \ 33 + || npins add gitlab --name "$name" -b main "$owner" "$repo" 2>/dev/null \ 34 + || npins add gitlab --name "$name" -b master "$owner" "$repo" 35 + fi ;; 36 + https://channels.nixos.org/*|https://releases.nixos.org/*) 37 + channel=$(printf '%s' "$url" | sed 's|https://[^/]*/||;s|/.*||') 38 + npins add channel --name "$name" "$channel" ;; 39 + https://*|http://*) 40 + npins add tarball --name "$name" "$url" ;; 41 + *) 42 + npins add git --name "$name" "$url" ;; 43 + esac 44 + } 45 + 46 + # Fetch a github input's flake.nix and append its deps to QUEUE_FILE. 47 + discover_transitive() { 48 + local name="$1" url="$2" spec owner repo ref 49 + [[ "$url" != github:* ]] && return 0 50 + spec="${url#github:}" owner="${spec%%/*}" spec="${spec#*/}" 51 + repo="${spec%%/*}" ref="${spec#*/}" 52 + [ "$ref" = "$repo" ] && ref="HEAD" 53 + 54 + local flake_tmp nix_tmp 55 + flake_tmp=$(mktemp --suffix=.nix) 56 + nix_tmp=$(mktemp --suffix=.nix) 57 + 58 + curl -sf "https://raw.githubusercontent.com/${owner}/${repo}/${ref}/flake.nix" \ 59 + > "$flake_tmp" || { rm -f "$flake_tmp" "$nix_tmp"; return 0; } 60 + 61 + # Write a nix expression that extracts just the inputs URLs (no network at eval time). 62 + printf 'let f = import %s; norm = v: if builtins.isString v then v else v.url or ""; in builtins.mapAttrs (_: norm) (f.inputs or {})\n' \ 63 + "$flake_tmp" > "$nix_tmp" 64 + 65 + nix-instantiate --eval --strict --json "$nix_tmp" 2>/dev/null \ 66 + | jq -r 'to_entries[] | select(.value != "") | [.key, .value] | @tsv' \ 67 + >> "$QUEUE_FILE" || true 68 + 69 + rm -f "$flake_tmp" "$nix_tmp" 70 + } 71 + 72 + # BFS: process queue items until none remain unvisited. 73 + while true; do 74 + name="" url="" 75 + while IFS=$'\t' read -r qname qurl; do 76 + if ! grep -qxF "$qname" "$SEEN_FILE" 2>/dev/null; then 77 + name="$qname" url="$qurl" 78 + break 79 + fi 80 + done < "$QUEUE_FILE" 81 + [ -z "$name" ] && break 82 + printf '%s\n' "$name" >> "$SEEN_FILE" 83 + if ! jq -e --arg n "$name" '.pins | has($n)' npins/sources.json >/dev/null 2>&1; then 84 + npins_add_url "$name" "$url" || true 85 + fi 86 + discover_transitive "$name" "$url" 87 + done 88 + 89 + # Remove any pins that were not reachable in this run. 90 + if [ -f npins/sources.json ]; then 91 + for existing in $(jq -r '.pins | keys[]' npins/sources.json); do 92 + if ! grep -qxF "$existing" "$SEEN_FILE"; then 93 + npins remove "$existing" 94 + fi 95 + done 96 + fi