Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 lib, 3 runCommand, 4 writeText, 5}: 6 7{ 8 beforeDir, 9 afterDir, 10 evalSystem, 11}: 12 13let 14 /* 15 Computes the key difference between two attrs 16 17 { 18 added: [ <keys only in the second object> ], 19 removed: [ <keys only in the first object> ], 20 changed: [ <keys with different values between the two objects> ], 21 rebuilds: [ <keys in the second object with values not present at all in first object> ], 22 } 23 */ 24 diff = 25 old: new: 26 let 27 filterKeys = cond: attrs: lib.attrNames (lib.filterAttrs cond attrs); 28 oldOutputs = lib.pipe old [ 29 (lib.mapAttrsToList (_: lib.attrValues)) 30 lib.concatLists 31 (lib.flip lib.genAttrs (_: true)) 32 ]; 33 in 34 { 35 added = filterKeys (n: _: !(old ? ${n})) new; 36 removed = filterKeys (n: _: !(new ? ${n})) old; 37 changed = filterKeys ( 38 n: v: 39 # Filter out attributes that don't exist anymore 40 (new ? ${n}) 41 42 # Filter out attributes that are the same as the new value 43 && (v != (new.${n})) 44 ) old; 45 # A "rebuild" is every attrpath ... 46 rebuilds = filterKeys ( 47 _: pkg: 48 # ... that has at least one output ... 49 lib.any ( 50 output: 51 # ... which has not been built in "old" already. 52 !(oldOutputs ? ${output}) 53 ) (lib.attrValues pkg) 54 ) new; 55 }; 56 57 getAttrs = 58 dir: 59 let 60 raw = builtins.readFile "${dir}/${evalSystem}/paths.json"; 61 # The file contains Nix paths; we need to ignore them for evaluation purposes, 62 # else there will be a "is not allowed to refer to a store path" error. 63 data = builtins.unsafeDiscardStringContext raw; 64 in 65 builtins.fromJSON data; 66 67 beforeAttrs = getAttrs beforeDir; 68 afterAttrs = getAttrs afterDir; 69 diffAttrs = diff beforeAttrs afterAttrs; 70 diffJson = writeText "diff.json" (builtins.toJSON diffAttrs); 71in 72runCommand "diff" { } '' 73 mkdir -p $out/${evalSystem} 74 75 cp -r ${beforeDir} $out/before 76 cp -r ${afterDir} $out/after 77 cp ${diffJson} $out/${evalSystem}/diff.json 78''