1#!/usr/bin/env nix-shell
2# ! nix-shell -i python3 -p python3 python3.pkgs.xmltodict
3import os
4import subprocess
5import pprint
6from argparse import ArgumentParser
7from xmltodict import parse
8from json import dump, loads
9from sys import stdout
10
11def convert_hash_to_sri(base32: str) -> str:
12 result = subprocess.run(["nix-hash", "--to-sri", "--type", "sha256", base32], capture_output=True, check=True, text=True)
13 return result.stdout.strip()
14
15
16def ensure_is_list(x):
17 if type(x) != list:
18 return [x]
19 return x
20
21
22def jar_repositories(root_path: str) -> list[str]:
23 repositories = []
24 file_contents = parse(open(root_path + "/.idea/jarRepositories.xml").read())
25 component = file_contents['project']['component']
26 if component['@name'] != 'RemoteRepositoriesConfiguration':
27 return repositories
28 options = component['remote-repository']
29 for option in ensure_is_list(options):
30 for item in option['option']:
31 if item['@name'] == 'url':
32 repositories.append(item['@value'])
33
34 return repositories
35
36
37def kotlin_jps_plugin_info(root_path: str) -> (str, str):
38 file_contents = parse(open(root_path + "/.idea/kotlinc.xml").read())
39 components = file_contents['project']['component']
40 for component in components:
41 if component['@name'] != 'KotlinJpsPluginSettings':
42 continue
43
44 option = component['option']
45 version = option['@value']
46
47 print(f"* Prefetching Kotlin JPS Plugin version {version}...")
48 prefetch = subprocess.run(["nix-prefetch-url", "--type", "sha256", f"https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies/org/jetbrains/kotlin/kotlin-jps-plugin-classpath/{version}/kotlin-jps-plugin-classpath-{version}.jar"], capture_output=True, check=True, text=True)
49
50 return (version, convert_hash_to_sri(prefetch.stdout.strip()))
51
52
53def requested_kotlinc_version(root_path: str) -> str:
54 file_contents = parse(open(root_path + "/.idea/kotlinc.xml").read())
55 components = file_contents['project']['component']
56 for component in components:
57 if component['@name'] != 'KotlinJpsPluginSettings':
58 continue
59
60 option = component['option']
61 version = option['@value']
62
63 return version
64
65
66def prefetch_intellij_community(variant: str, buildNumber: str) -> (str, str):
67 print("* Prefetching IntelliJ community source code...")
68 prefetch = subprocess.run(["nix-prefetch-url", "--print-path", "--unpack", "--name", "source", "--type", "sha256", f"https://github.com/jetbrains/intellij-community/archive/{variant}/{buildNumber}.tar.gz"], capture_output=True, check=True, text=True)
69 parts = prefetch.stdout.strip().split()
70
71 hash = convert_hash_to_sri(parts[0])
72 outPath = parts[1]
73
74 return (hash, outPath)
75
76
77def prefetch_android(variant: str, buildNumber: str) -> str:
78 print("* Prefetching Android plugin source code...")
79 prefetch = subprocess.run(["nix-prefetch-url", "--unpack", "--name", "source", "--type", "sha256", f"https://github.com/jetbrains/android/archive/{variant}/{buildNumber}.tar.gz"], capture_output=True, check=True, text=True)
80 return convert_hash_to_sri(prefetch.stdout.strip())
81
82
83def get_args() -> (str, str):
84 parser = ArgumentParser(
85 description="Updates the IDEA / PyCharm source build infomations"
86 )
87 parser.add_argument("out", help="File to output json to")
88 parser.add_argument("path", help="Path to the bin/versions.json file")
89 args = parser.parse_args()
90 return args.path, args.out
91
92
93def main():
94 versions_path, out = get_args()
95 versions = loads(open(versions_path).read())
96 idea_data = versions['x86_64-linux']['idea-community']
97 pycharm_data = versions['x86_64-linux']['pycharm-community']
98
99 result = { 'idea-community': {}, 'pycharm-community': {} }
100 result['idea-community']['version'] = idea_data['version']
101 result['idea-community']['buildNumber'] = idea_data['build_number']
102 result['idea-community']['buildType'] = 'idea'
103 result['pycharm-community']['version'] = pycharm_data['version']
104 result['pycharm-community']['buildNumber'] = pycharm_data['build_number']
105 result['pycharm-community']['buildType'] = 'pycharm'
106 print('Fetching IDEA info...')
107 result['idea-community']['ideaHash'], ideaOutPath = prefetch_intellij_community('idea', result['idea-community']['buildNumber'])
108 result['idea-community']['androidHash'] = prefetch_android('idea', result['idea-community']['buildNumber'])
109 result['idea-community']['jpsHash'] = ''
110 result['idea-community']['restarterHash'] = ''
111 result['idea-community']['mvnDeps'] = 'idea_maven_artefacts.json'
112 result['idea-community']['repositories'] = jar_repositories(ideaOutPath)
113 result['idea-community']['kotlin-jps-plugin'] = {}
114 result['idea-community']['kotlin-jps-plugin']['version'], result['idea-community']['kotlin-jps-plugin']['hash'] = kotlin_jps_plugin_info(ideaOutPath)
115 kotlinc_version = requested_kotlinc_version(ideaOutPath)
116 print(f"* Prefetched IDEA Community requested Kotlin compiler {kotlinc_version}")
117 print('Fetching PyCharm info...')
118 result['pycharm-community']['ideaHash'], pycharmOutPath = prefetch_intellij_community('pycharm', result['pycharm-community']['buildNumber'])
119 result['pycharm-community']['androidHash'] = prefetch_android('pycharm', result['pycharm-community']['buildNumber'])
120 result['pycharm-community']['jpsHash'] = ''
121 result['pycharm-community']['restarterHash'] = ''
122 result['pycharm-community']['mvnDeps'] = 'pycharm_maven_artefacts.json'
123 result['pycharm-community']['repositories'] = jar_repositories(pycharmOutPath)
124 result['pycharm-community']['kotlin-jps-plugin'] = {}
125 result['pycharm-community']['kotlin-jps-plugin']['version'], result['pycharm-community']['kotlin-jps-plugin']['hash'] = kotlin_jps_plugin_info(pycharmOutPath)
126 kotlinc_version = requested_kotlinc_version(pycharmOutPath)
127 print(f"* Prefetched PyCharm Community requested Kotlin compiler {kotlinc_version}")
128
129 if out == "stdout":
130 dump(result, stdout, indent=2)
131 else:
132 file = open(out, "w")
133 dump(result, file, indent=2)
134 file.write("\n")
135
136
137if __name__ == '__main__':
138 main()