at 18.09-beta 3.4 kB view raw
1#!/usr/bin/env bash 2set -e 3 4# --print: avoid dependency on environment 5optPrint= 6if [ "$1" == "--print" ]; then 7 optPrint=true 8 shift 9fi 10 11if [ "$#" != 1 ] && [ "$#" != 2 ]; then 12 cat <<-EOF 13 Usage: $0 [--print] commit-spec [commit-spec] 14 You need to be in a git-controlled nixpkgs tree. 15 The current state of the tree will be used if the second commit is missing. 16 EOF 17 exit 1 18fi 19 20# A slightly hacky way to get the config. 21parallel="$(echo 'config.rebuild-amount.parallel or false' | nix-repl . 2>/dev/null \ 22 | grep -v '^\(nix-repl.*\)\?$' | tail -n 1 || true)" 23 24echo "Estimating rebuild amount by counting changed Hydra jobs." 25 26toRemove=() 27 28cleanup() { 29 rm -rf "${toRemove[@]}" 30} 31trap cleanup EXIT SIGINT SIGQUIT ERR 32 33MKTEMP='mktemp --tmpdir nix-rebuild-amount-XXXXXXXX' 34 35nixexpr() { 36 cat <<-EONIX 37 let 38 lib = import $1/lib; 39 hydraJobs = import $1/pkgs/top-level/release.nix 40 # Compromise: accuracy vs. resources needed for evaluation. 41 { supportedSystems = cfg.systems or [ "x86_64-linux" "x86_64-darwin" ]; }; 42 cfg = (import $1 {}).config.rebuild-amount or {}; 43 44 recurseIntoAttrs = attrs: attrs // { recurseForDerivations = true; }; 45 46 # hydraJobs leaves recurseForDerivations as empty attrmaps; 47 # that would break nix-env and we also need to recurse everywhere. 48 tweak = lib.mapAttrs 49 (name: val: 50 if name == "recurseForDerivations" then true 51 else if lib.isAttrs val && val.type or null != "derivation" 52 then recurseIntoAttrs (tweak val) 53 else val 54 ); 55 56 # Some of these contain explicit references to platform(s) we want to avoid; 57 # some even (transitively) depend on ~/.nixpkgs/config.nix (!) 58 blacklist = [ 59 "tarball" "metrics" "manual" 60 "darwin-tested" "unstable" "stdenvBootstrapTools" 61 "moduleSystem" "lib-tests" # these just confuse the output 62 ]; 63 64 in 65 tweak (builtins.removeAttrs hydraJobs blacklist) 66 EONIX 67} 68 69# Output packages in tree $2 that weren't in $1. 70# Changing the output hash or name is taken as a change. 71# Extra nix-env parameters can be in $3 72newPkgs() { 73 # We use files instead of pipes, as running multiple nix-env processes 74 # could eat too much memory for a standard 4GiB machine. 75 local -a list 76 for i in 1 2; do 77 local l="$($MKTEMP)" 78 list[$i]="$l" 79 toRemove+=("$l") 80 81 local expr="$($MKTEMP)" 82 toRemove+=("$expr") 83 nixexpr "${!i}" > "$expr" 84 85 nix-env -f "$expr" -qaP --no-name --out-path --show-trace $3 \ 86 | sort > "${list[$i]}" & 87 88 if [ "$parallel" != "true" ]; then 89 wait 90 fi 91 done 92 93 wait 94 comm -13 "${list[@]}" 95} 96 97# Prepare nixpkgs trees. 98declare -a tree 99for i in 1 2; do 100 if [ -n "${!i}" ]; then # use the given commit 101 dir="$($MKTEMP -d)" 102 tree[$i]="$dir" 103 toRemove+=("$dir") 104 105 git clone --shared --no-checkout --quiet . "${tree[$i]}" 106 (cd "${tree[$i]}" && git checkout --quiet "${!i}") 107 else #use the current tree 108 tree[$i]="$(pwd)" 109 fi 110done 111 112newlist="$($MKTEMP)" 113toRemove+=("$newlist") 114# Notes: 115# - the evaluation is done on x86_64-linux, like on Hydra. 116# - using $newlist file so that newPkgs() isn't in a sub-shell (because of toRemove) 117newPkgs "${tree[1]}" "${tree[2]}" '--argstr system "x86_64-linux"' > "$newlist" 118 119# Hacky: keep only the last word of each attribute path and sort. 120sed -n 's/\([^. ]*\.\)*\([^. ]*\) .*$/\2/p' < "$newlist" \ 121 | sort | uniq -c 122 123if [ -n "$optPrint" ]; then 124 echo 125 cat "$newlist" 126fi 127