Skip to content

Instantly share code, notes, and snippets.

@melektron
Created July 3, 2026 20:44
Show Gist options
  • Select an option

  • Save melektron/c385d3d975e9cd361dfe0b4d79a487d5 to your computer and use it in GitHub Desktop.

Select an option

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)
#!/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
@melektron

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment