Created
July 3, 2026 20:44
-
-
Save melektron/c385d3d975e9cd361dfe0b4d79a487d5 to your computer and use it in GitHub Desktop.
Script to sync the locked revisions your nix flake inputs to those of the system flake (or any other flake)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -e | |
| # argument handling based on: | |
| # https://stackoverflow.com/a/14203146 | |
| POSITIONAL_ARGS=() | |
| # default system flake (adjust according to your needs) | |
| SYSFLAKE="/home/username/sysflake" # <-- adjust here | |
| # default target flake is current directory | |
| TARGET=. | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -i|--ignore-mismatch) | |
| IGNORE_MISMATCH=YES | |
| shift # past argument | |
| ;; | |
| -t|--target) | |
| if [[ -z "$2" ]]; then echo "Target path must be provided after -t"; exit 1; fi | |
| TARGET="$2" | |
| shift # past argument | |
| shift # past value | |
| ;; | |
| -s|--sysflake) | |
| if [[ -z "$2" ]]; then echo "Sysflake path must be provided after -s"; exit 1; fi | |
| SYSFLAKE="$2" | |
| shift # past argument | |
| shift # past value | |
| ;; | |
| -*|--*) | |
| echo "Unknown option $1" | |
| exit 1 | |
| ;; | |
| *) | |
| POSITIONAL_ARGS+=("$1") # save positional arg | |
| shift # past argument | |
| ;; | |
| esac | |
| done | |
| # if no mapping was passed, we default to setting "nixpkgs" to the latest one in my system flake | |
| if [[ -z $POSITIONAL_ARGS ]]; then | |
| POSITIONAL_ARGS+=("nixpkgs=desktop-linux-nixpkgs-2605") # <-- adjust here | |
| fi | |
| set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters | |
| echo "IGNORE_MISMATCH = ${IGNORE_MISMATCH}" | |
| echo "SYSFLAKE = ${SYSFLAKE}" | |
| echo "TARGET = ${TARGET}" | |
| # go through each mapping on the arg list | |
| for MAPPING; do | |
| SRC="${MAPPING#*=}" # after = | |
| DST="${MAPPING%=*}" # before = | |
| # both must be non-emoty | |
| if [[ (-z $SRC) || (-z $DST) ]]; then | |
| echo "Invalid mapping syntax, expected dst=src" | |
| exit 1 | |
| fi | |
| # using § to indicate inputs (similar to the standard # for outputs) | |
| ORIGINALS_EQUAL=$(jq -n \ | |
| --slurpfile sysflake <(nix flake metadata $SYSFLAKE --json) \ | |
| --slurpfile target <(nix flake metadata $TARGET --json) \ | |
| --arg src $SRC \ | |
| --arg dst $DST \ | |
| '$target[0].locks.nodes[$dst].original == $sysflake[0].locks.nodes[$src].original' | |
| ) | |
| if [[ ($ORIGINALS_EQUAL == false) && (! $IGNORE_MISMATCH) ]]; then | |
| echo "Input definition of '$TARGET§$DST' doesn't match that of '$SYSFLAKE§$SRC'. This might not be intended and may not work. Ignore this warning using the -i flag." | |
| exit 1 | |
| fi | |
| echo "Locking '$TARGET§$DST' to '$SYSFLAKE§$SRC'" | |
| # replace "locked" section in target flake input with that of the sysflake | |
| # while updating lastModified | |
| OLD_SYS_METADATA=$(nix flake metadata $TARGET --json) | |
| echo $OLD_SYS_METADATA | jq \ | |
| --slurpfile sysflake <(nix flake metadata $SYSFLAKE --json) \ | |
| --arg src $SRC \ | |
| --arg dst $DST \ | |
| --argjson timestamp $(date +%s) \ | |
| '.locks.nodes[$dst].locked = $sysflake[0].locks.nodes[$src].locked | .locks.nodes[$dst].locked.lastModified = $timestamp | .locks' \ | |
| > "$TARGET/flake.lock" | |
| done |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See https://elektron.work/posts/nix-flake-syslock/ for explanation