Merge pull request #307098 from r-ryantm/auto-update/cilium-cli
[NixPkgs.git] / pkgs / development / julia-modules / package-closure.nix
blobd1138394e9936050e9182dc64cca6752f9284b90
1 { lib
2 , julia
3 , python3
4 , runCommand
6 , augmentedRegistry
7 , packageNames
8 , packageOverrides
9 , packageImplications
12 let
13   # The specific package resolution code depends on the Julia version
14   # These are pretty similar and could be combined to reduce duplication
15   resolveCode = if lib.versionOlder julia.version "1.7" then resolveCode1_6 else resolveCode1_8;
17   resolveCode1_6 = ''
18     import Pkg.API: check_package_name
19     import Pkg.Types: Context!, PRESERVE_NONE, manifest_info, project_deps_resolve!, registry_resolve!, stdlib_resolve!, ensure_resolved
20     import Pkg.Operations: _resolve, assert_can_add, is_dep, update_package_add
22     foreach(pkg -> check_package_name(pkg.name, :add), pkgs)
23     pkgs = deepcopy(pkgs)  # deepcopy for avoid mutating PackageSpec members
24     Context!(ctx)
26     project_deps_resolve!(ctx, pkgs)
27     registry_resolve!(ctx, pkgs)
28     stdlib_resolve!(pkgs)
29     ensure_resolved(ctx, pkgs, registry=true)
31     assert_can_add(ctx, pkgs)
33     for (i, pkg) in pairs(pkgs)
34         entry = manifest_info(ctx, pkg.uuid)
35         pkgs[i] = update_package_add(ctx, pkg, entry, is_dep(ctx, pkg))
36     end
38     foreach(pkg -> ctx.env.project.deps[pkg.name] = pkg.uuid, pkgs)
40     pkgs, deps_map = _resolve(ctx, pkgs, PRESERVE_NONE)
41 '';
43   resolveCode1_8 = ''
44     import Pkg.API: handle_package_input!
45     import Pkg.Types: PRESERVE_NONE, project_deps_resolve!, registry_resolve!, stdlib_resolve!, ensure_resolved
46     import Pkg.Operations: _resolve, assert_can_add, update_package_add
48     foreach(handle_package_input!, pkgs)
50     # The handle_package_input! call above clears pkg.path, so we have to apply package overrides after
51     overrides = Dict{String, String}(${builtins.concatStringsSep ", " (lib.mapAttrsToList (name: path: ''"${name}" => "${path}"'') packageOverrides)})
52     println("Package overrides: ")
53     println(overrides)
54     for pkg in pkgs
55       if pkg.name in keys(overrides)
56         pkg.path = overrides[pkg.name]
57       end
58     end
60     project_deps_resolve!(ctx.env, pkgs)
61     registry_resolve!(ctx.registries, pkgs)
62     stdlib_resolve!(pkgs)
63     ensure_resolved(ctx, ctx.env.manifest, pkgs, registry=true)
65     assert_can_add(ctx, pkgs)
67     for (i, pkg) in pairs(pkgs)
68         entry = Pkg.Types.manifest_info(ctx.env.manifest, pkg.uuid)
69         is_dep = any(uuid -> uuid == pkg.uuid, [uuid for (name, uuid) in ctx.env.project.deps])
70         pkgs[i] = update_package_add(ctx, pkg, entry, is_dep)
71     end
73     foreach(pkg -> ctx.env.project.deps[pkg.name] = pkg.uuid, pkgs)
75     # Save the original pkgs for later. We might need to augment it with the weak dependencies
76     orig_pkgs = pkgs
78     pkgs, deps_map = _resolve(ctx.io, ctx.env, ctx.registries, pkgs, PRESERVE_NONE, ctx.julia_version)
80     if VERSION >= VersionNumber("1.9")
81         while true
82             # Check for weak dependencies, which appear on the RHS of the deps_map but not in pkgs.
83             # Build up weak_name_to_uuid
84             uuid_to_name = Dict()
85             for pkg in pkgs
86                 uuid_to_name[pkg.uuid] = pkg.name
87             end
88             weak_name_to_uuid = Dict()
89             for (uuid, deps) in pairs(deps_map)
90                 for (dep_name, dep_uuid) in pairs(deps)
91                     if !haskey(uuid_to_name, dep_uuid)
92                         weak_name_to_uuid[dep_name] = dep_uuid
93                     end
94                 end
95             end
97             if isempty(weak_name_to_uuid)
98                 break
99             end
101             # We have nontrivial weak dependencies, so add each one to the initial pkgs and then re-run _resolve
102             println("Found weak dependencies: $(keys(weak_name_to_uuid))")
104             orig_uuids = Set([pkg.uuid for pkg in orig_pkgs])
106             for (name, uuid) in pairs(weak_name_to_uuid)
107                 if uuid in orig_uuids
108                     continue
109                 end
111                 pkg = PackageSpec(name, uuid)
113                 push!(orig_uuids, uuid)
114                 push!(orig_pkgs, pkg)
115                 ctx.env.project.deps[name] = uuid
116                 entry = Pkg.Types.manifest_info(ctx.env.manifest, uuid)
117                 orig_pkgs[length(orig_pkgs)] = update_package_add(ctx, pkg, entry, false)
118             end
120             global pkgs, deps_map = _resolve(ctx.io, ctx.env, ctx.registries, orig_pkgs, PRESERVE_NONE, ctx.julia_version)
121         end
122     end
123   '';
125   juliaExpression = packageNames: ''
126     import Pkg
127     Pkg.Registry.add(Pkg.RegistrySpec(path="${augmentedRegistry}"))
129     import Pkg.Types: Context, PackageSpec
131     input = ${lib.generators.toJSON {} packageNames}
133     if isfile("extra_package_names.txt")
134       append!(input, readlines("extra_package_names.txt"))
135     end
137     input = unique(input)
139     println("Resolving packages: " * join(input, " "))
141     pkgs = [PackageSpec(pkg) for pkg in input]
143     ctx = Context()
145     ${resolveCode}
147     open(ENV["out"], "w") do io
148       for spec in pkgs
149         println(io, "- name: " * spec.name)
150         println(io, "  uuid: " * string(spec.uuid))
151         println(io, "  version: " * string(spec.version))
152         if endswith(spec.name, "_jll") && haskey(deps_map, spec.uuid)
153           println(io, "  depends_on: ")
154           for (dep_name, dep_uuid) in pairs(deps_map[spec.uuid])
155             println(io, "    \"$(dep_name)\": \"$(dep_uuid)\"")
156           end
157         end
158       end
159     end
160   '';
163 runCommand "julia-package-closure.yml" { buildInputs = [julia (python3.withPackages (ps: with ps; [pyyaml]))]; } ''
164   mkdir home
165   export HOME=$(pwd)/home
167   echo "Resolving Julia packages with the following inputs"
168   echo "Julia: ${julia}"
169   echo "Registry: ${augmentedRegistry}"
171   # Prevent a warning where Julia tries to download package server info
172   export JULIA_PKG_SERVER=""
174   julia -e '${juliaExpression packageNames}';
176   # See if we need to add any extra package names based on the closure
177   # and the packageImplications
178   python ${./python}/find_package_implications.py "$out" '${lib.generators.toJSON {} packageImplications}' extra_package_names.txt
180   if [ -f extra_package_names.txt ]; then
181     echo "Re-resolving with additional package names"
182     julia -e '${juliaExpression packageNames}';
183   fi