| #!/usr/bin/env vpython3 |
| # Copyright 2025 The Dawn & Tint Authors |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, this |
| # list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # 3. Neither the name of the copyright holder nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| """Rolls DEPS entries shared with Chromium.""" |
| |
| import abc |
| import argparse |
| import base64 |
| import dataclasses |
| import logging |
| import pathlib |
| import posixpath |
| import subprocess |
| import sys |
| from typing import Any, Self |
| |
| import requests |
| |
| DAWN_ROOT = pathlib.Path(__file__).resolve().parents[1] |
| DEPS_FILE = DAWN_ROOT / 'DEPS' |
| |
| CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src' |
| CHROMIUM_REVISION_VAR = 'chromium_revision' |
| |
| # GN variables that need to be synced. A map from Dawn variable name to |
| # Chromium variable name. |
| SYNCED_VARIABLES = {} |
| |
| # DEPS entries which have dep_type = cipd. In the Chromium DEPS file, these |
| # will be prefixed with src/. |
| SYNCED_CIPD_DEPS = { |
| 'buildtools/linux64', |
| 'buildtools/mac', |
| 'buildtools/reclient', |
| 'buildtools/win', |
| 'third_party/ninja', |
| 'third_party/siso/cipd', |
| } |
| |
| # DEPS entries which have dep_type = gcs. In the Chromium DEPS file, these will |
| # be prefixed with src/. |
| SYNCED_GCS_DEPS = { |
| 'build/linux/debian_bullseye_arm64-sysroot', |
| 'build/linux/debian_bullseye_armhf-sysroot', |
| 'build/linux/debian_bullseye_i386-sysroot', |
| 'build/linux/debian_bullseye_mipsel-sysroot', |
| 'build/linux/debian_bullseye_mips64el-sysroot', |
| 'build/linux/debian_bullseye_amd64-sysroot', |
| } |
| |
| # Repos that are independently synced by Chromium and Dawn. A map from Dawn |
| # names to Chromium names. None means that the names are identical. In the |
| # Chromium DEPS file, these will be prefixed with src/. |
| # The following repos are already synced by dedicated autorollers: |
| # * https://autoroll.skia.org/r/angle-dawn-autoroll |
| # * third_party/angle |
| # * https://autoroll.skia.org/r/swiftshader-dawn-autoroll |
| # * third_party/swiftshader |
| # * https://autoroll.skia.org/r/vulkan-deps-dawn-autoroll |
| # * third_party/glslang/src |
| # * third_party/spirv-headers/src |
| # * third_party/spirv-tools/src |
| # * third_party/vulkan-deps |
| # * third_party/vulkan-headers/src |
| # * third_party/vulkan-loader/src |
| # * third_party/vulkan-tools/src |
| # * third_party/vulkan-utility-libraries/src |
| # * third_party/vulkan-validation-layers/src |
| SYNCED_REPOS = { |
| 'third_party/catapult': None, |
| 'third_party/clang-format/script': None, |
| 'third_party/depot_tools': None, |
| # third_party/dxheaders is technically used by both Chromium and Dawn, but |
| # for different purposes and on non-overlapping platforms. Thus, there is |
| # no need to sync their revisions. |
| 'third_party/google_benchmark/src': None, |
| 'third_party/googletest': 'third_party/googletest/src', |
| 'third_party/jsoncpp': 'third_party/jsoncpp/source', |
| 'third_party/libc++/src': None, |
| 'third_party/libc++abi/src': None, |
| 'third_party/libprotobuf-mutator/src': None, |
| 'third_party/llvm-libc/src': None, |
| 'third_party/libdrm/src': None, |
| 'third_party/libFuzzer/src': None, |
| # third_party/vulkan_memory_allocator is shared with Chromium, but is |
| # manually rolled since it typically requires additional code changes in |
| # the repo. |
| # third_party/webgpu-cts is technically used by both Chromium and Dawn, but |
| # they are used for different purposes and the CTS roller needs to roll |
| # Dawn's copy in order to update expectations. |
| } |
| |
| # Chromium directories that are exported as pseudo-repos in |
| # chromium.googlesource.com under chromium/src/. Mapping of Dawn path to |
| # Chromium src-relative path. None means that the names are identical. |
| EXPORTED_CHROMIUM_REPOS = { |
| 'build': None, |
| 'buildtools': None, |
| 'testing': None, |
| 'third_party/abseil-cpp': None, |
| 'third_party/jinja2': None, |
| 'third_party/markupsafe': None, |
| 'third_party/partition_alloc': 'base/allocator/partition_allocator', |
| 'third_party/protobuf': None, |
| 'third_party/zlib': None, |
| 'tools/clang': None, |
| 'tools/mb': None, |
| 'tools/memory': None, |
| 'tools/protoc_wrapper': None, |
| 'tools/valgrind': None, |
| 'tools/win': None, |
| } |
| |
| |
| class ChangedDepsEntry(abc.ABC): |
| """Base class for all changed DEPS entries.""" |
| |
| @abc.abstractmethod |
| def setdep_args(self) -> list[str]: |
| """Returns 'gclient setdep'-compatible arguments. |
| |
| The returned arguments will cause 'gclient setdep' to update the DEPS |
| file content to the new version. |
| """ |
| |
| |
| @dataclasses.dataclass |
| class ChangedVariable(ChangedDepsEntry): |
| """Represents a single changed DEPS variable.""" |
| # The name of the variable in Dawn's DEPS file. |
| name: str |
| # The old version in Dawn's DEPS file. |
| old_version: str |
| # The new version that Dawn's DEPS file will contain. |
| new_version: str |
| |
| def setdep_args(self) -> list[str]: |
| return [ |
| '--var', |
| f'{self.name}={self.new_version}', |
| ] |
| |
| |
| @dataclasses.dataclass |
| class ChangedRepo(ChangedDepsEntry): |
| """Represents a single changed DEPS repo entry.""" |
| # The name of the dependency in Dawn's DEPS file. |
| name: str |
| # The old revision in Dawn's DEPS file. |
| old_revision: str |
| # The new revision that Dawn's DEPS file will contain. |
| new_revision: str |
| |
| def setdep_args(self) -> list[str]: |
| return [ |
| '--revision', |
| f'{self.name}@{self.new_revision}', |
| ] |
| |
| |
| @dataclasses.dataclass |
| class CipdPackage: |
| """Represents a single element of a CIPD DEPS entry's 'packages' list.""" |
| package: str |
| version: str |
| |
| @classmethod |
| def from_dict(cls, dict_repr: dict[str, str]) -> Self: |
| """Creates an instance from a DEPS entry dict. |
| |
| Args: |
| dict_repr: A dictionary from a GCS DEPS entry's 'packages' list. |
| |
| Returns: |
| A CipdPackage instance filled with the information contained within |
| |dict_repr|. |
| """ |
| return cls( |
| package=dict_repr['package'], |
| version=dict_repr['version'], |
| ) |
| |
| def setdep_str(self) -> str: |
| """Gets a 'gclient setdep'-compatible string representation.""" |
| # Remove any double curly braces, e.g. ${{arch}} |
| package = self.package.format() |
| return f'{package}@{self.version}' |
| |
| |
| @dataclasses.dataclass |
| class ChangedCipd(ChangedDepsEntry): |
| """Represents a single changed DEPS CIPD entry.""" |
| # The name of the dependency in Dawn's DEPS file. |
| name: str |
| # The old packages in Dawn's DEPS file |
| old_packages: list[CipdPackage] |
| # The new packages that Dawn's DEPS file will contain. |
| new_packages: list[CipdPackage] |
| |
| def setdep_args(self) -> list[str]: |
| revisions = [ |
| f'{self.name}:{p.setdep_str()}' for p in self.new_packages |
| ] |
| return ['--revision'] + revisions |
| |
| |
| @dataclasses.dataclass |
| class GcsObject: |
| """Represents a single element of a GCS DEPS entry's 'objects' list.""" |
| object_name: str |
| sha256sum: str |
| size_bytes: int |
| generation: int |
| |
| @classmethod |
| def from_dict(cls, dict_repr: dict[str, str | int]) -> Self: |
| """Creates an instance from a DEPS entry dict. |
| |
| Args: |
| dict_repr: A dictionary from a GCS DEPS entry's 'objects' list. |
| |
| Returns: |
| A GcsObject instance filled with the information contained within |
| |dict_repr|. |
| """ |
| return cls( |
| object_name=dict_repr['object_name'], |
| sha256sum=dict_repr['sha256sum'], |
| size_bytes=dict_repr['size_bytes'], |
| generation=dict_repr['generation'], |
| ) |
| |
| def as_comma_separated_str(self) -> str: |
| return (f'{self.object_name},{self.sha256sum},{self.size_bytes},' |
| f'{self.generation}') |
| |
| |
| @dataclasses.dataclass |
| class ChangedGcs(ChangedDepsEntry): |
| """Represents a single changed DEPS GCS entry.""" |
| # The name of the dependency in Dawn's DEPS file. |
| name: str |
| # The old objects in Dawn's DEPS file. |
| old_objects: list[GcsObject] |
| # The new objects that Dawn's DEPS file will contain. |
| new_objects: list[GcsObject] |
| |
| def setdep_args(self) -> list[str]: |
| comma_separated_objects = [ |
| o.as_comma_separated_str() for o in self.new_objects |
| ] |
| object_string = '?'.join(comma_separated_objects) |
| return ['--revision', f'{self.name}@{object_string}'] |
| |
| |
| def _parse_deps_file(deps_content: str) -> dict[str, Any]: |
| """Parses DEPS file content into a Python dict. |
| |
| Args: |
| deps_content: The content of a DEPS file. |
| |
| Returns: |
| A dict containing all content of the DEPS file. For example, the top |
| level `vars` mapping in a DEPS file can be accessed via the 'vars' item |
| in the returned dictionary. |
| """ |
| local_scope = {} |
| global_scope = { |
| 'Str': lambda str_value: str_value, |
| 'Var': lambda var_name: local_scope['vars'][var_name], |
| } |
| exec(deps_content, global_scope, local_scope) |
| return local_scope |
| |
| |
| def _add_depot_tools_to_path() -> None: |
| sys.path.append(str(DAWN_ROOT / 'build')) |
| import find_depot_tools |
| find_depot_tools.add_depot_tools_to_path() |
| |
| |
| def _get_remote_head_revision(remote_url: str) -> str: |
| """Retrieves the HEAD revision for a remote git URL. |
| |
| Args: |
| remote_url: The remote git URL to get HEAD from. |
| |
| Returns: |
| The revision currently corresponding to HEAD. |
| """ |
| cmd = [ |
| 'git', |
| 'ls-remote', |
| remote_url, |
| 'HEAD', |
| ] |
| proc = subprocess.run(cmd, |
| check=True, |
| text=True, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.STDOUT) |
| head_revision = proc.stdout.strip().split()[0] |
| return head_revision |
| |
| |
| def _get_roll_revision_range(target_revision: str | None, |
| dawn_deps: dict) -> ChangedRepo: |
| """Determines the range being rolled. |
| |
| Args: |
| target_revision: The revision being targeted for the roll. If not |
| specified, the HEAD revision will be determined and used. |
| dawn_deps: The parsed contents of the Dawn DEPS file. |
| |
| Returns: |
| A ChangedRepo with the determined revision range. |
| """ |
| old_revision = dawn_deps['vars'][CHROMIUM_REVISION_VAR] |
| new_revision = target_revision |
| if not new_revision: |
| new_revision = _get_remote_head_revision(CHROMIUM_SRC_URL) |
| logging.info('Using %s as the HEAD revision.', new_revision) |
| return ChangedRepo(name='chromium/src', |
| old_revision=old_revision, |
| new_revision=new_revision) |
| |
| |
| def _read_gitiles_content(file_url: str) -> str: |
| """Reads the contents of a file from Gitiles. |
| |
| Args: |
| file_url: A URL pointing to a file to read from Gitiles. |
| |
| Returns: |
| The string content of the specified file. |
| """ |
| file_url = file_url + '?format=TEXT' |
| r = requests.get(file_url) |
| r.raise_for_status() |
| return base64.b64decode(r.text).decode('utf-8') |
| |
| |
| def _read_remote_chromium_file(src_relative_path: str, revision: str) -> str: |
| """Reads the contents of a Chromium file from Gitiles. |
| |
| Args: |
| src_relative_path: A POSIX path to the file to read relative to |
| chromium/src. |
| revision: The Chromium revision to read the file contents at. |
| """ |
| file_url = posixpath.join(CHROMIUM_SRC_URL, '+', revision, |
| src_relative_path) |
| return _read_gitiles_content(file_url) |
| |
| |
| def _get_changed_deps_entries(dawn_deps: dict, |
| chromium_deps: dict) -> list[ChangedDepsEntry]: |
| """Gets all entries that have changed between the two provided DEPS. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| chromium_deps: The parsed content of the Chromium DEPS file. |
| |
| Returns: |
| A list ChangedDepsEntry objects, each one corresponding to a change |
| between the two DEPS files. |
| """ |
| changed_entries = [] |
| changed_entries.extend(_get_changed_variables(dawn_deps, chromium_deps)) |
| changed_entries.extend(_get_changed_cipd(dawn_deps, chromium_deps)) |
| changed_entries.extend(_get_changed_gcs(dawn_deps, chromium_deps)) |
| changed_entries.extend( |
| _get_changed_non_exported_repos(dawn_deps, chromium_deps)) |
| changed_entries.extend(_get_changed_exported_repos(dawn_deps)) |
| return changed_entries |
| |
| |
| def _get_changed_variables(dawn_deps: dict, |
| chromium_deps: dict) -> list[ChangedVariable]: |
| """Gets all GN variables that have changed between the two provided DEPS. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| chromium_deps: The parsed content of the Chromium DEPS file. |
| |
| Returns: |
| A list of all variable entries that have changed between the two DEPS |
| files. |
| """ |
| changed_variables = [] |
| for dawn_var, chromium_var in SYNCED_VARIABLES.items(): |
| dawn_value = dawn_deps['vars'].get(dawn_var) |
| chromium_value = chromium_deps['vars'].get(chromium_var) |
| if not dawn_value: |
| raise RuntimeError( |
| f'Could not find Dawn GN variable {dawn_var}. Was it removed?') |
| if not chromium_value: |
| raise RuntimeError( |
| f'Could not find Chromium GN variable {chromium_var}. Was it ' |
| f'removed?') |
| changed_variables.append( |
| ChangedVariable( |
| name=dawn_var, |
| old_version=dawn_value, |
| new_version=chromium_value, |
| )) |
| return changed_variables |
| |
| |
| def _get_changed_cipd(dawn_deps: dict, |
| chromium_deps: dict) -> list[ChangedCipd]: |
| """Gets all CIPD entries that have changed between the two provided DEPS. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| chromium_deps: The parsed content of the Chromium DEPS file. |
| |
| Returns: |
| A list of all CIPD DEPS entries that have changed between the two |
| DEPS files. |
| """ |
| changed_cipd = [] |
| for dawn_name in SYNCED_CIPD_DEPS: |
| chromium_name = 'src/' + dawn_name |
| if dawn_name not in dawn_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Dawn CIPD entry {dawn_name}. Was it removed?') |
| if chromium_name not in chromium_deps['deps']: |
| raise RuntimeErrror( |
| f'Unable to find Chromium CIPD entry {chromium_name}. Was it ' |
| f'removed?') |
| |
| dawn_packages = [ |
| CipdPackage.from_dict(p) |
| for p in dawn_deps['deps'][dawn_name]['packages'] |
| ] |
| chromium_packages = [ |
| CipdPackage.from_dict(p) |
| for p in chromium_deps['deps'][chromium_name]['packages'] |
| ] |
| # Unlike GCS entries which provide all object content with a single |
| # --revision, CIPD entries provide one package to update per |
| # --revision. The behavior when a package within an entry disappears is |
| # not clearly defined, so just fail if we ever see that. This should |
| # rarely happen, though. |
| dawn_package_names = set(p.package for p in dawn_packages) |
| chromium_package_names = set(p.package for p in chromium_packages) |
| if not dawn_package_names.issubset(chromium_package_names): |
| raise RuntimeError( |
| f'Packages for CIPD entry {dawn_name} appear to have changed. ' |
| f'Please manually sync the package list.') |
| if dawn_packages != chromium_packages: |
| changed_cipd.append( |
| ChangedCipd( |
| name=dawn_name, |
| old_packages=dawn_packages, |
| new_packages=chromium_packages, |
| )) |
| return changed_cipd |
| |
| |
| def _get_changed_gcs(dawn_deps: dict, chromium_deps: dict) -> list[ChangedGcs]: |
| """Gets all GCS entries that have changed between the two provided DEPS. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| chromium_deps: The parsed content of the Chromium DEPS file. |
| |
| Returns: |
| A list of all GCS DEPS entries that have changed between the two DEPS |
| files. |
| """ |
| changed_gcs = [] |
| for dawn_name in SYNCED_GCS_DEPS: |
| chromium_name = 'src/' + dawn_name |
| if dawn_name not in dawn_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Dawn GCS entry {dawn_name}. Was it removed?') |
| if chromium_name not in chromium_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Chromium GCS entry {chromium_name}. Was it ' |
| f'removed?') |
| |
| dawn_objects = [ |
| GcsObject.from_dict(o) |
| for o in dawn_deps['deps'][dawn_name]['objects'] |
| ] |
| chromium_objects = [ |
| GcsObject.from_dict(o) |
| for o in chromium_deps['deps'][chromium_name]['objects'] |
| ] |
| if dawn_objects != chromium_objects: |
| changed_gcs.append( |
| ChangedGcs( |
| name=dawn_name, |
| old_objects=dawn_objects, |
| new_objects=chromium_objects, |
| )) |
| return changed_gcs |
| |
| |
| def _get_changed_non_exported_repos(dawn_deps: dict, |
| chromium_deps: dict) -> list[ChangedRepo]: |
| """Gets all non-exported repos that have changed between the DEPS files. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| chromium_deps: The parsed content of the Chromium DEPS file. |
| |
| Returns: |
| A list of all repo entries that have changed between the two DEPS files |
| that are not exported pseudo-repos from Chromium. |
| """ |
| changed_repos = [] |
| for dawn_name, chromium_name in SYNCED_REPOS.items(): |
| chromium_name = chromium_name or dawn_name |
| chromium_name = 'src/' + chromium_name |
| if dawn_name not in dawn_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Dawn repo {dawn_name}. Was it removed?') |
| if chromium_name not in chromium_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Chromium repo {chromium_name}. Was it ' |
| f'removed?') |
| |
| _, dawn_revision = _get_url_and_revision( |
| _get_raw_url_for_dep_entry(dawn_name, dawn_deps), |
| dawn_deps['vars']) |
| _, chromium_revision = _get_url_and_revision( |
| _get_raw_url_for_dep_entry(chromium_name, chromium_deps), |
| chromium_deps['vars']) |
| if dawn_revision != chromium_revision: |
| changed_repos.append( |
| ChangedRepo( |
| name=dawn_name, |
| old_revision=dawn_revision, |
| new_revision=chromium_revision, |
| )) |
| return changed_repos |
| |
| |
| def _get_changed_exported_repos(dawn_deps: dict) -> list[ChangedRepo]: |
| """Gets all exported repos that have changed since the last roll. |
| |
| Args: |
| dawn_deps: The parsed content of the Dawn DEPS file. |
| |
| Returns: |
| A list of all repo entries for exported pseudo-repos from Chromium |
| whose HEAD revision is different from the revision currently used by |
| Dawn. |
| """ |
| changed_repos = [] |
| for dawn_name, chromium_path in EXPORTED_CHROMIUM_REPOS.items(): |
| chromium_path = chromium_path or dawn_name |
| if dawn_name not in dawn_deps['deps']: |
| raise RuntimeError( |
| f'Unable to find Dawn repo {dawn_name}. Was it removed?') |
| url, dawn_revision = _get_url_and_revision( |
| _get_raw_url_for_dep_entry(dawn_name, dawn_deps), |
| dawn_deps['vars']) |
| head_revision = _get_remote_head_revision(url) |
| if dawn_revision != head_revision: |
| changed_repos.append( |
| ChangedRepo( |
| name=dawn_name, |
| old_revision=dawn_revision, |
| new_revision=head_revision, |
| )) |
| return changed_repos |
| |
| |
| def _get_raw_url_for_dep_entry(dep_name: str, deps: dict) -> str: |
| """Gets the URL associated with the specified DEPS entry. |
| |
| Args: |
| dep_name: The name of the DEPS entry to retrieve the URL for. |
| deps: The parsed DEPS content to extract information from. |
| |
| Returns: |
| A string containing the URL associated with |dep_name|. |
| """ |
| dep_entry = deps['deps'][dep_name] |
| # Most entries are dicts, but it's also valid for an entry to just be a |
| # git URL. |
| if isinstance(dep_entry, str): |
| return dep_entry |
| return dep_entry['url'] |
| |
| |
| def _get_url_and_revision(deps_url: str, vars: dict) -> tuple[str, str]: |
| """Extracts the repo URL and revision from a DEPS url value. |
| |
| Known substitutions are also performed on the URL, e.g. replacing |
| {chromium_git} with the actual Chromium git URL. |
| |
| Args: |
| deps_url: The URL to operate on. |
| vars: The 'vars' mapping from the parsed DEPS content that |deps_url| |
| came from. |
| |
| Returns: |
| A tuple (url, revision). |
| """ |
| url, revision = deps_url.rsplit('@', 1) |
| for var, value in vars.items(): |
| if not isinstance(value, str): |
| continue |
| search_str = f'{{{var}}}' |
| url = url.replace(search_str, value) |
| return url, revision |
| |
| |
| def _apply_changed_deps(changed_entries: list[ChangedDepsEntry]) -> None: |
| """Applies all changed DEPS entries to the Dawn DEPS file. |
| |
| Args: |
| changed_entries: All calculated ChangedDepsEntry objects. |
| """ |
| cmd = [ |
| 'gclient', |
| 'setdep', |
| ] |
| for ce in changed_entries: |
| cmd.extend(ce.setdep_args()) |
| subprocess.run(cmd, check=True) |
| |
| |
| def _parse_args() -> argparse.Namespace: |
| """Parses and returns command line arguments.""" |
| parser = argparse.ArgumentParser('Roll DEPS entries shared with Chromium.') |
| parser.add_argument('--verbose', |
| '-v', |
| action='store_true', |
| help='Increase logging verbosity') |
| parser.add_argument('--autoroll', |
| action='store_true', |
| help='Run the script in autoroll mode') |
| parser.add_argument('--revision', |
| help=('A Chromium revision to roll to. If ' |
| 'unspecified, HEAD is used.')) |
| return parser.parse_args() |
| |
| |
| def main() -> None: |
| args = _parse_args() |
| if args.verbose: |
| logging.basicConfig(level=logging.DEBUG) |
| else: |
| logging.basicConfig(level=logging.INFO) |
| |
| # The autoroller does not have locally synced dependencies, so we cannot use |
| # the copy under //third_party. |
| if not args.autoroll: |
| _add_depot_tools_to_path() |
| |
| with open(DEPS_FILE, encoding='utf-8') as infile: |
| dawn_deps = _parse_deps_file(infile.read()) |
| revision_range = _get_roll_revision_range(args.revision, dawn_deps) |
| chromium_deps = _parse_deps_file( |
| _read_remote_chromium_file('DEPS', revision_range.new_revision)) |
| changed_entries = _get_changed_deps_entries(dawn_deps, chromium_deps) |
| changed_entries.append( |
| ChangedVariable( |
| name=CHROMIUM_REVISION_VAR, |
| old_version=revision_range.old_revision, |
| new_version=revision_range.new_revision, |
| )) |
| _apply_changed_deps(changed_entries) |
| |
| |
| if __name__ == '__main__': |
| main() |