1
2from collections import defaultdict
3import copy
4import json
5import os
6from pathlib import Path
7import shutil
8import subprocess
9import sys
10import tempfile
11import toml
12import util
13import yaml
14
15
16registry_path = Path(sys.argv[1])
17desired_packages_path = Path(sys.argv[2])
18package_overrides = json.loads(sys.argv[3])
19dependencies_path = Path(sys.argv[4])
20out_path = Path(sys.argv[5])
21
22with open(desired_packages_path, "r") as f:
23 desired_packages = yaml.safe_load(f) or []
24
25uuid_to_versions = defaultdict(list)
26for pkg in desired_packages:
27 uuid_to_versions[pkg["uuid"]].append(pkg["version"])
28
29with open(dependencies_path, "r") as f:
30 uuid_to_store_path = yaml.safe_load(f)
31
32os.makedirs(out_path)
33
34full_registry = toml.load(registry_path / "Registry.toml")
35registry = full_registry.copy()
36registry["packages"] = {k: v for k, v in registry["packages"].items() if k in uuid_to_versions}
37
38for (uuid, versions) in uuid_to_versions.items():
39 if uuid in package_overrides:
40 info = package_overrides[uuid]
41
42 # Make a registry entry based on the info from the package override
43 path = Path(info["name"][0].upper()) / Path(info["name"])
44 registry["packages"][uuid] = {
45 "name": info["name"],
46 "path": str(path),
47 }
48
49 os.makedirs(out_path / path)
50
51 # Read the Project.yaml from the src
52 project = toml.load(Path(info["src"]) / "Project.toml")
53
54 # Generate all the registry files
55 with open(out_path / path / Path("Compat.toml"), "w") as f:
56 f.write('["%s"]\n' % info["version"])
57 # Write nothing in Compat.toml, because we've already resolved everything
58 with open(out_path / path / Path("Deps.toml"), "w") as f:
59 f.write('["%s"]\n' % info["version"])
60 if "deps" in project:
61 toml.dump(project["deps"], f)
62 with open(out_path / path / Path("Versions.toml"), "w") as f:
63 f.write('["%s"]\n' % info["version"])
64 f.write('git-tree-sha1 = "%s"\n' % info["treehash"])
65 with open(out_path / path / Path("Package.toml"), "w") as f:
66 toml.dump({
67 "name": info["name"],
68 "uuid": uuid,
69 "repo": "file://" + info["src"],
70 }, f)
71
72 elif uuid in registry["packages"]:
73 registry_info = registry["packages"][uuid]
74 name = registry_info["name"]
75 path = registry_info["path"]
76
77 os.makedirs(out_path / path)
78
79 # Copy some files to the minimal repo unchanged
80 for f in ["Compat.toml", "Deps.toml", "WeakCompat.toml", "WeakDeps.toml"]:
81 if (registry_path / path / f).exists():
82 shutil.copy2(registry_path / path / f, out_path / path)
83
84 # Copy the Versions.toml file, trimming down to the versions we care about.
85 # In the case where versions=None, this is a weak dep, and we keep all versions.
86 all_versions = toml.load(registry_path / path / "Versions.toml")
87 versions_to_keep = {k: v for k, v in all_versions.items() if k in versions} if versions != None else all_versions
88 for k, v in versions_to_keep.items():
89 del v["nix-sha256"]
90 with open(out_path / path / "Versions.toml", "w") as f:
91 toml.dump(versions_to_keep, f)
92
93 if versions is None:
94 # This is a weak dep; just grab the whole Package.toml
95 shutil.copy2(registry_path / path / "Package.toml", out_path / path / "Package.toml")
96 elif uuid in uuid_to_store_path:
97 # Fill in the local store path for the repo
98 package_toml = toml.load(registry_path / path / "Package.toml")
99 package_toml["repo"] = "file://" + uuid_to_store_path[uuid]
100 with open(out_path / path / "Package.toml", "w") as f:
101 toml.dump(package_toml, f)
102
103# Look for missing weak deps and include them. This can happen when our initial
104# resolve step finds dependencies, but we fail to resolve them at the project.py
105# stage. Usually this happens because the package that depends on them does so
106# as a weak dep, but doesn't have a Package.toml in its repo making this clear.
107for pkg in desired_packages:
108 for dep in (pkg.get("deps", []) or []):
109 uuid = dep["uuid"]
110 if not uuid in uuid_to_versions:
111 entry = full_registry["packages"].get(uuid)
112 if not entry:
113 print(f"""WARNING: found missing UUID but couldn't resolve it: {uuid}""")
114 continue
115
116 # Add this entry back to the minimal Registry.toml
117 registry["packages"][uuid] = entry
118
119 # Bring over the Package.toml
120 path = Path(entry["path"])
121 if (out_path / path / "Package.toml").exists():
122 continue
123 Path(out_path / path).mkdir(parents=True, exist_ok=True)
124 shutil.copy2(registry_path / path / "Package.toml", out_path / path / "Package.toml")
125
126# Finally, dump the Registry.toml
127with open(out_path / "Registry.toml", "w") as f:
128 toml.dump(registry, f)