1#!/usr/bin/env nix-shell
2#! nix-shell -i python3 -p python3 python3.pkgs.xmltodict
3import os
4from argparse import ArgumentParser
5from xmltodict import parse
6from json import dump
7from sys import stdout
8
9def get_args() -> (str, list[str]):
10 parser = ArgumentParser(
11 description="Given the path of a intellij source tree, make a list of urls and hashes of maven artefacts required to build"
12 )
13 parser.add_argument("out", help="File to output json to")
14 parser.add_argument("path", help="Path to the intellij-community source dir")
15 args = parser.parse_args()
16 return args.path, args.out
17
18
19def ensure_is_list(x):
20 if type(x) != list:
21 return [x]
22 return x
23
24def add_entries(sources, targets, hashes):
25 for num, artefact in enumerate(sources):
26 hashes.append({
27 "url": artefact["@url"][26:],
28 "hash": artefact["sha256sum"],
29 "path": targets[num]["@url"][25:-2]
30 })
31
32
33def add_libraries(root_path: str, hashes: list[dict[str, str]], projects_to_process: list[str]):
34 library_paths = os.listdir(root_path + "/libraries/")
35 for path in library_paths:
36 file_contents = parse(open(root_path + "/libraries/" + path).read())
37 if "properties" not in file_contents["component"]["library"]:
38 continue
39 sources = ensure_is_list(file_contents["component"]["library"]["properties"]["verification"]["artifact"])
40 targets = ensure_is_list(file_contents["component"]["library"]["CLASSES"]["root"])
41 add_entries(sources, targets, hashes)
42
43 modules_xml = parse(open(root_path+"/modules.xml").read())
44 for module in modules_xml["project"]["component"]["modules"]["module"]:
45 projects_to_process.append(module["@filepath"])
46
47
48def add_iml(path: str, hashes: list[dict[str, str]], projects_to_process: list[str]):
49 try:
50 contents = parse(open(path).read())
51 except FileNotFoundError:
52 print(f"Warning: path {path} does not exist (did you forget the android directory?)")
53 return
54 for manager in ensure_is_list(contents["module"]["component"]):
55 if manager["@name"] != "NewModuleRootManager":
56 continue
57
58 for entry in manager["orderEntry"]:
59 if type(entry) != dict or \
60 entry["@type"] != "module-library" or \
61 "properties" not in entry["library"]:
62 continue
63
64 sources = ensure_is_list(entry["library"]["properties"]["verification"]["artifact"])
65 targets = ensure_is_list(entry["library"]["CLASSES"]["root"])
66 add_entries(sources, targets, hashes)
67
68
69def main():
70 root_path, out = get_args()
71 file_hashes = []
72 projects_to_process: list[str] = [root_path+"/.idea"]
73
74 while projects_to_process:
75 elem = projects_to_process.pop()
76 elem = elem.replace("$PROJECT_DIR$", root_path)
77 if elem.endswith(".iml"):
78 add_iml(elem, file_hashes, projects_to_process)
79 else:
80 add_libraries(elem, file_hashes, projects_to_process)
81
82 if out == "stdout":
83 dump(file_hashes, stdout, indent=4)
84 else:
85 file = open(out, "w")
86 dump(file_hashes, file, indent=4)
87 file.write("\n")
88
89
90if __name__ == '__main__':
91 main()