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''')