Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
7.6 kB · 277 lines
Shell
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278#!/usr/bin/env nix-shell#! nix-shell -i bash -p coreutils gnugrep gnused
################################################################################# nix-diff.sh ################################################################################## This script "diffs" Nix profile generations. ## ## Example: ################################################################################## > nix-diff.sh 90 92 ## + gnumake-4.2.1 ## + gnumake-4.2.1-doc ## - htmldoc-1.8.29 ################################################################################## The example shows that as of generation 92 and since generation 90, ## gnumake-4.2.1 and gnumake-4.2.1-doc have been installed, while ## htmldoc-1.8.29 has been removed. ## ## The example above shows the default, minimal output mode of this script. ## For more features, run `nix-diff.sh -h` for usage instructions. #################################################################################
usage() { cat <<EOFusage: nix-diff.sh [-h | [-p profile | -s] [-q] [-l] [range]]-h: print this message before exiting-q: list the derivations installed in the parent generation-l: diff every available intermediate generation between parent and child-p profile: specify the Nix profile to use * defaults to ~/.nix-profile-s: use the system profile * equivalent to: -p /nix/var/nix/profiles/systemprofile: * should be something like /nix/var/nix/profiles/default, not a generation link like /nix/var/nix/profiles/default-2-linkrange: the range of generations to diff * the following patterns are allowed, where A, B, and N are positive integers, and G is the currently active generation: A..B => diffs from generation A to generation B ~N => diffs from the Nth newest generation (older than G) to G A => diffs from generation A to G * defaults to ~1EOF}
usage_tip() { echo 'run `nix-diff.sh -h` for usage instructions' >&2 exit 1}
while getopts :hqlp:s opt; do case $opt in h) usage exit ;; q) opt_query=1 ;; l) opt_log=1 ;; p) opt_profile=$OPTARG ;; s) opt_profile=/nix/var/nix/profiles/system ;; \?) echo "error: invalid option -$OPTARG" >&2 usage_tip ;; esacdoneshift $((OPTIND-1))
if [ -n "$opt_profile" ]; then if ! [ -L "$opt_profile" ]; then echo "error: expecting \`$opt_profile\` to be a symbolic link" >&2 usage_tip fielse opt_profile=$(readlink ~/.nix-profile) if (( $? != 0 )); then echo 'error: unable to dereference `~/.nix-profile`' >&2 echo 'specify the profile manually with the `-p` flag' >&2 usage_tip fifi
list_gens() { nix-env -p "$opt_profile" --list-generations \ | sed -r 's:^\s*::' \ | cut -d' ' -f1}
current_gen() { nix-env -p "$opt_profile" --list-generations \ | grep -E '\(current\)\s*$' \ | sed -r 's:^\s*::' \ | cut -d' ' -f1}
neg_gen() { local i=0 from=$1 n=$2 tmp for gen in $(list_gens | sort -rn); do if ((gen < from)); then tmp=$gen ((i++)) ((i == n)) && break fi done if ((i < n)); then echo -n "error: there aren't $n generation(s) older than" >&2 echo " generation $from" >&2 return 1 fi echo $tmp}
match() { argv=("$@") for i in $(seq $(($#-1))); do if grep -E "^${argv[$i]}\$" <(echo "$1") >/dev/null; then echo $i return fi done echo 0}
case $(match "$1" '' '[0-9]+' '[0-9]+\.\.[0-9]+' '~[0-9]+') in 1) diffTo=$(current_gen) diffFrom=$(neg_gen $diffTo 1) (($? == 1)) && usage_tip ;; 2) diffFrom=$1 diffTo=$(current_gen) ;; 3) diffFrom=${1%%.*} diffTo=${1##*.} ;; 4) diffTo=$(current_gen) diffFrom=$(neg_gen $diffTo ${1#*~}) (($? == 1)) && usage_tip ;; 0) echo 'error: invalid invocation' >&2 usage_tip ;;esac
dirA="${opt_profile}-${diffFrom}-link"dirB="${opt_profile}-${diffTo}-link"
declare -a temp_filestemp_length() { echo -n ${#temp_files[@]}}temp_make() { temp_files[$(temp_length)]=$(mktemp)}temp_clean() { rm -f ${temp_files[@]}}temp_name() { echo -n "${temp_files[$(($(temp_length)-1))]}"}trap 'temp_clean' EXIT
temp_makeversA=$(temp_name)refs=$(nix-store -q --references "$dirA")(( $? != 0 )) && exit 1echo "$refs" \ | grep -v env-manifest.nix \ | sort \ > "$versA"
print_tag() { local gen=$1 nix-env -p "$opt_profile" --list-generations \ | grep -E "^\s*${gen}" \ | sed -r 's:^\s*::' \ | sed -r 's:\s*$::'}
if [ -n "$opt_query" ]; then print_tag $diffFrom cat "$versA" \ | sed -r 's:^[^-]+-(.*)$: \1:'
print_line=1fi
if [ -n "$opt_log" ]; then gens=$(for gen in $(list_gens); do ((diffFrom < gen && gen < diffTo)) && echo $gen done) # Force the $diffTo generation to be included in this list, instead of using # `gen <= diffTo` in the preceding loop, so we encounter an error upon the # event of its nonexistence. gens=$(echo "$gens" echo $diffTo)else gens=$diffTofi
temp_makeadd=$(temp_name)temp_makerem=$(temp_name)temp_makeout=$(temp_name)
for gen in $gens; do
[ -n "$print_line" ] && echo
temp_make versB=$(temp_name)
dirB="${opt_profile}-${gen}-link" refs=$(nix-store -q --references "$dirB") (( $? != 0 )) && exit 1 echo "$refs" \ | grep -v env-manifest.nix \ | sort \ > "$versB"
in=$(comm -3 -1 "$versA" "$versB") sed -r 's:^[^-]*-(.*)$:\1+:' <(echo "$in") \ | sort -f \ > "$add"
un=$(comm -3 -2 "$versA" "$versB") sed -r 's:^[^-]*-(.*)$:\1-:' <(echo "$un") \ | sort -f \ > "$rem"
cat "$rem" "$add" \ | sort -f \ | sed -r 's:(.*)-$:- \1:' \ | sed -r 's:(.*)\+$:\+ \1:' \ | grep -v '^$' \ > "$out"
if [ -n "$opt_query" -o -n "$opt_log" ]; then
lines=$(wc -l "$out" | cut -d' ' -f1) tag=$(print_tag "$gen") (( $? != 0 )) && exit 1 if [ $lines -eq 0 ]; then echo "$tag (no change)" else echo "$tag" fi cat "$out" \ | sed 's:^: :'
print_line=1
else echo "diffing from generation $diffFrom to $diffTo" cat "$out" fi
versA=$versB
done
exit 0