main
1/*
2Selection of packages with `passthru.updateScript`, shared by the
3runner (scripts/update.nix) and scripts/update-package --list.
4
5Usage:
6
7 nix-instantiate --eval --json --strict \
8 -E 'map (p: p.attrPath) (import ./scripts/update-packages.nix {})'
9*/
10{
11 pkgs ? import <nixpkgs> {},
12 # Space-separated list of package attribute paths to update.
13 # Empty string means "update everything".
14 packages ? "",
15}: let
16 inherit (pkgs) lib;
17 nurPkgs = import ../default.nix {inherit pkgs;};
18
19 updateScriptOf = pkg: let
20 script =
21 (
22 if pkg.passthru or null != null
23 then pkg.passthru
24 else {}
25 ).updateScript or null;
26 in
27 if script == null
28 then null
29 else if lib.isDerivation script
30 then [(toString script)]
31 else if lib.isAttrs script
32 then
33 if script ? command
34 then map toString (lib.toList script.command)
35 else null
36 else map toString (lib.toList script);
37
38 reservedNames = [
39 "lib"
40 "overlays"
41 "nixosModules"
42 "homeModules"
43 "darwinModules"
44 "flakeModules"
45 ];
46
47 collect = prefix: attrs: let
48 names = builtins.tryEval (builtins.attrNames attrs);
49 in
50 if !names.success
51 then []
52 else
53 builtins.concatLists (
54 map (
55 name: let
56 result = builtins.tryEval attrs.${name};
57 in
58 if !result.success
59 then []
60 else if lib.isDerivation result.value
61 then let
62 script = updateScriptOf result.value;
63 meta = result.value.meta or null;
64 position =
65 if meta != null
66 then meta.position or null
67 else null;
68 in
69 lib.optional (script != null && !(meta.nurRenamed or false) && !(meta.nurDeprecated or false)) {
70 inherit name;
71 attrPath = lib.concatStringsSep "." (prefix ++ [name]);
72 inherit script;
73 pname = result.value.pname or (lib.getName result.value);
74 pkgName = result.value.name;
75 oldVersion = result.value.version or "";
76 inherit position;
77 }
78 else if lib.isAttrs result.value
79 then collect (prefix ++ [name]) result.value
80 else []
81 )
82 names.value
83 );
84
85 allPackages = collect [] (lib.filterAttrs (name: _: !builtins.elem name reservedNames) nurPkgs);
86
87 deduplicated = let
88 isClean = p: !(p.meta.nurRenamed or false) && !(p.meta.nurDeprecated or false);
89 grouped =
90 lib.foldl (
91 acc: cur: let
92 key = builtins.hashString "sha256" (
93 lib.concatStringsSep "\n" (cur.script ++ [(toString cur.position)])
94 );
95 prev = acc.${key} or null;
96 keep =
97 prev
98 == null
99 || (isClean cur && !isClean prev)
100 || (isClean cur == isClean prev && lib.hasInfix "." cur.attrPath && !lib.hasInfix "." prev.attrPath);
101 in
102 acc
103 // {
104 ${key} =
105 if keep
106 then cur
107 else prev;
108 }
109 ) {}
110 allPackages;
111 in
112 map (k: grouped.${k}) (builtins.attrNames grouped);
113
114 matchesSelection = p: sel: p.attrPath == sel || lib.hasSuffix ".${sel}" p.attrPath;
115
116 selected =
117 if packages != ""
118 then lib.filter (p: lib.any (sel: matchesSelection p sel) (lib.splitString " " packages)) deduplicated
119 else deduplicated;
120in
121 selected