| # Copyright 2024 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| from __future__ import annotations |
| |
| import configparser |
| import dataclasses |
| import io |
| import re |
| from typing import TYPE_CHECKING |
| |
| from PB.recipe_modules.pigweed.bazel.options import Options as BazelOptions |
| from recipe_engine import recipe_api |
| |
| if TYPE_CHECKING: # pragma: no cover |
| from typing import Generator |
| from PB.recipe_modules.pigweed.bazel_roll.git_repository import ( |
| GitRepository, |
| ) |
| from recipe_engine import config_types |
| from RECIPE_MODULES.fuchsia.git_roll_util import api as git_roll_util_api |
| from RECIPE_MODULES.pigweed.checkout import api as checkout_api |
| |
| |
| class BazelRollApi(recipe_api.RecipeApi): |
| |
| def workspace_path( |
| self, |
| root: config_types.Path, |
| value: str, |
| ) -> config_types.Path: |
| """Figure out the location of the WORKSPACE or MODULE.bazel file. |
| |
| If value is '', look for root / 'WORKSPACE' and root / 'MODULE.bazel'. |
| If exactly one exists, return it. If not, error out. |
| |
| If root / value is a file, return it. |
| |
| If root / value is a directory, set root = root / value and apply the |
| above logic. This enables applying this logic to subdirectories. |
| |
| Args: |
| api: Recipe API object. |
| root: Checkout root. |
| value: Relative path specified in properties. |
| |
| Returns: |
| Path to the WORKSPACE or MODULE.bazel file. |
| """ |
| if value: |
| value_path = root / value |
| self.m.path.mock_add_file(value_path) |
| if self.m.path.isfile(value_path): |
| return value_path |
| elif self.m.path.isdir(value_path): # pragma: no cover |
| root = value_path |
| else: |
| self.m.step.empty( # pragma: no cover |
| f'{value_path} does not exist', |
| status='FAILURE', |
| ) |
| |
| workspace = root / 'WORKSPACE' |
| module_bazel = root / 'MODULE.bazel' |
| |
| self.m.path.mock_add_file(workspace) |
| |
| if self.m.path.isfile(module_bazel) and self.m.path.isfile(workspace): |
| self.m.step.empty( # pragma: no cover |
| f'{module_bazel} and {workspace} both exist', |
| status='FAILURE', |
| ) |
| |
| if self.m.path.isfile(module_bazel): |
| return module_bazel # pragma: no cover |
| |
| if self.m.path.isfile(workspace): |
| return workspace |
| |
| self.m.step.empty( # pragma: no cover |
| 'no WORKSPACE or MODULE.bazel file found', |
| status='FAILURE', |
| ) |
| |
| def update_git_repository( |
| self, |
| checkout: checkout_self.m.CheckoutContext, |
| git_repository: GitRepository, |
| ) -> list[git_roll_util_api.Roll]: |
| project_name = git_repository.name |
| if not project_name: |
| project_name = git_repository.remote.split('/')[-1] |
| project_name = project_name.removesuffix('.git') |
| |
| with self.m.step.nest(project_name): |
| workspace_path = self.workspace_path( |
| checkout.root, |
| git_repository.workspace_path, |
| ) |
| git_repository.branch = git_repository.branch or 'main' |
| |
| new_revision = self.m.git_roll_util.resolve_new_revision( |
| git_repository.remote, |
| git_repository.branch, |
| checkout.remotes_equivalent, |
| ) |
| |
| update_result = self.m.bazel.update_commit_hash( |
| checkout=checkout, |
| project_remote=git_repository.remote, |
| new_revision=new_revision, |
| path=workspace_path, |
| delay_write=True, |
| ) |
| if not update_result: |
| self.m.step.empty( |
| 'failed to update commit hash', |
| status='FAILURE', |
| ) |
| |
| try: |
| roll = self.m.git_roll_util.get_roll( |
| repo_url=git_repository.remote, |
| repo_short_name=project_name, |
| old_rev=update_result.old_revision, |
| new_rev=new_revision, |
| ) |
| |
| except self.m.git_roll_util.BackwardsRollError: |
| return [] |
| |
| update_result.finalize() |
| |
| with self.m.step.nest('update MODULE.bazel.lock'): |
| runner = self.m.bazel.new_runner( |
| checkout=checkout, |
| options=BazelOptions(), |
| ) |
| |
| with self.m.context(cwd=checkout.root): |
| self.m.step( |
| 'bazelisk mod deps --lockfile_mode=update', |
| [ |
| runner.ensure(), |
| 'mod', |
| 'deps', |
| '--lockfile_mode=update', |
| ], |
| ) |
| |
| return [roll] |