1#! /usr/bin/env nix-shell
2#! nix-shell -i python -p python3
3"""
4This is a heavily simplified variant of electron's update.py
5for use in ./update.mjs and should not be called manually.
6
7It resolves chromium's DEPS file recursively when called with
8a working depot_tools checkout and a ref to fetch and prints
9the result as JSON to stdout.
10"""
11import base64
12import json
13from typing import Optional
14from urllib.request import urlopen
15
16import sys
17
18if len(sys.argv) != 3:
19 print("""This internal script has been called with the wrong amount of parameters.
20This script is not supposed to be called manually.
21Refer to ./update.mjs instead.""")
22 exit(1)
23
24_, depot_tools_checkout, chromium_version = sys.argv
25
26sys.path.append(depot_tools_checkout)
27import gclient_eval
28import gclient_utils
29
30
31class Repo:
32 fetcher: str
33 args: dict
34
35 def __init__(self) -> None:
36 self.deps: dict = {}
37 self.hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
38
39 def get_deps(self, repo_vars: dict, path: str) -> None:
40 print(
41 "evaluating " + json.dumps(self, default=vars, sort_keys=True),
42 file=sys.stderr,
43 )
44
45 deps_file = self.get_file("DEPS")
46 evaluated = gclient_eval.Parse(deps_file, vars_override=repo_vars, filename="DEPS")
47
48 repo_vars = dict(evaluated.get("vars", {})) | repo_vars
49
50 prefix = f"{path}/" if evaluated.get("use_relative_paths", False) else ""
51
52 self.deps = {
53 prefix + dep_name: repo_from_dep(dep)
54 for dep_name, dep in evaluated.get("deps", {}).items()
55 if (
56 gclient_eval.EvaluateCondition(dep["condition"], repo_vars)
57 if "condition" in dep
58 else True
59 )
60 and repo_from_dep(dep) != None
61 }
62
63 for key in evaluated.get("recursedeps", []):
64 dep_path = prefix + key
65 if dep_path in self.deps and dep_path != "src/third_party/squirrel.mac":
66 self.deps[dep_path].get_deps(repo_vars, dep_path)
67
68 def flatten_repr(self) -> dict:
69 return {"fetcher": self.fetcher, "hash": self.hash, **self.args}
70
71 def flatten(self, path: str) -> dict:
72 out = {path: self.flatten_repr()}
73 for dep_path, dep in self.deps.items():
74 out |= dep.flatten(dep_path)
75 return out
76
77 def get_file(self, filepath: str) -> str:
78 raise NotImplementedError
79
80
81class GitilesRepo(Repo):
82 def __init__(self, url: str, rev: str) -> None:
83 super().__init__()
84 self.fetcher = "fetchFromGitiles"
85 self.args = {
86 "url": url,
87 "rev": rev,
88 }
89
90 def get_file(self, filepath: str) -> str:
91 return base64.b64decode(
92 urlopen(
93 f"{self.args['url']}/+/{self.args['rev']}/{filepath}?format=TEXT"
94 ).read()
95 ).decode("utf-8")
96
97
98def repo_from_dep(dep: dict) -> Optional[Repo]:
99 if "url" in dep:
100 url, rev = gclient_utils.SplitUrlRevision(dep["url"])
101 return GitilesRepo(url, rev)
102 else:
103 # Not a git dependency; skip
104 return None
105
106
107
108chromium = GitilesRepo("https://chromium.googlesource.com/chromium/src.git", chromium_version)
109chromium.get_deps(
110 {
111 **{
112 f"checkout_{platform}": platform == "linux" or platform == "x64" or platform == "arm64" or platform == "arm"
113 for platform in ["ios", "chromeos", "android", "mac", "win", "linux"]
114 },
115 **{
116 f"checkout_{arch}": True
117 for arch in ["x64", "arm64", "arm", "x86", "mips", "mips64", "ppc"]
118 },
119 },
120 "",
121)
122print(json.dumps(chromium.flatten("src")))