1
2from collections import defaultdict
3import json
4import os
5from pathlib import Path
6import sys
7import toml
8import yaml
9
10
11desired_packages_path = Path(sys.argv[1])
12stdlib_infos_path = Path(sys.argv[2])
13package_overrides = json.loads(sys.argv[3])
14dependencies_path = Path(sys.argv[4])
15out_path = Path(sys.argv[5])
16
17with open(desired_packages_path, "r") as f:
18 desired_packages = yaml.safe_load(f) or []
19
20with open(stdlib_infos_path, "r") as f:
21 stdlib_infos = yaml.safe_load(f) or []
22
23with open(dependencies_path, "r") as f:
24 uuid_to_store_path = yaml.safe_load(f)
25
26result = {
27 "deps": defaultdict(list)
28}
29
30for pkg in desired_packages:
31 if pkg["uuid"] in package_overrides:
32 info = package_overrides[pkg["uuid"]]
33 result["deps"][info["name"]].append({
34 "uuid": pkg["uuid"],
35 "path": info["src"],
36 })
37 continue
38
39 path = uuid_to_store_path.get(pkg["uuid"], None)
40 isStdLib = False
41 if pkg["uuid"] in stdlib_infos["stdlibs"]:
42 path = stdlib_infos["stdlib_root"] + "/" + stdlib_infos["stdlibs"][pkg["uuid"]]["name"]
43 isStdLib = True
44
45 if path:
46 if (Path(path) / "Project.toml").exists():
47 project_toml = toml.load(Path(path) / "Project.toml")
48
49 deps = []
50 weak_deps = project_toml.get("weakdeps", {})
51 extensions = project_toml.get("extensions", {})
52
53 if "deps" in project_toml:
54 # Build up deps for the manifest, excluding weak deps
55 weak_deps_uuids = weak_deps.values()
56 for (dep_name, dep_uuid) in project_toml["deps"].items():
57 if not (dep_uuid in weak_deps_uuids):
58 deps.append(dep_name)
59 else:
60 # Not all projects have a Project.toml. In this case, use the deps we
61 # calculated from the package resolve step. This isn't perfect since it
62 # will fail to properly split out weak deps, but it's better than nothing.
63 print(f"""WARNING: package {pkg["name"]} didn't have a Project.toml in {path}""")
64 deps = [x["name"] for x in pkg.get("deps", [])]
65 weak_deps = {}
66 extensions = {}
67
68 tree_hash = pkg.get("tree_hash", "")
69
70 result["deps"][pkg["name"]].append({
71 "version": pkg["version"],
72 "uuid": pkg["uuid"],
73 "git-tree-sha1": (tree_hash if tree_hash != "nothing" else None) or None,
74 "deps": deps or None,
75 "weakdeps": weak_deps or None,
76 "extensions": extensions or None,
77
78 # We *don't* set "path" here, because then Julia will try to use the
79 # read-only Nix store path instead of cloning to the depot. This will
80 # cause packages like Conda.jl to fail during the Pkg.build() step.
81 #
82 # "path": None if isStdLib else path ,
83 })
84 else:
85 print("WARNING: adding a package that we didn't have a path for, and it doesn't seem to be a stdlib", pkg)
86 result["deps"][pkg["name"]].append({
87 "version": pkg["version"],
88 "uuid": pkg["uuid"],
89 "deps": [x["name"] for x in pkg["deps"]]
90 })
91
92os.makedirs(out_path)
93
94with open(out_path / "Manifest.toml", "w") as f:
95 f.write(f'julia_version = "{stdlib_infos["julia_version"]}"\n')
96 f.write('manifest_format = "2.0"\n\n')
97 toml.dump(result, f)
98
99with open(out_path / "Project.toml", "w") as f:
100 f.write('[deps]\n')
101
102 for pkg in desired_packages:
103 if pkg.get("is_input", False):
104 f.write(f'''{pkg["name"]} = "{pkg["uuid"]}"\n''')