| #!/usr/bin/env python3 |
| # Copyright 2021 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # pylint: disable=missing-docstring |
| |
| """Creates Chromium Metadata files. |
| |
| See https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md. |
| """ |
| |
| import argparse |
| import logging |
| import os |
| import subprocess |
| import sys |
| import pathlib |
| |
| from chromite.lib import cros_build_lib |
| from chromite.lib import gerrit |
| from chromite.lib import git |
| |
| METADATA_FILE_NAME = 'DIR_METADATA' |
| |
| METADATA_TEMPLATE = """\ |
| # Metadata information for this directory. |
| # |
| # For more information on DIR_METADATA files, see: |
| # https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md |
| # |
| # For the schema of this file, see Metadata message: |
| # https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto |
| |
| buganizer { |
| component_id: FIXME |
| } |
| buganizer_public { |
| component_id: FIXME |
| } |
| team_email: "YOUR_TEAM@google.com" |
| """ |
| |
| COMMIT_MSG_TEMPLATE = """ |
| {COMPONENT}{DELIM}Add Chromium Metadata file |
| |
| BUG=b:172930457 |
| TEST=none |
| """ |
| |
| GERRIT_COMMENT = """ |
| This is an automated CL. Please replace the buganizer component (public \ |
| and private) and team email with the correct values. A team email is \ |
| encouraged, but if there isn't one, you can remove that field. |
| """ |
| |
| GERRIT_HASHTAG = '#chromium_metadata_b/172930457' |
| |
| |
| def find_git_dir(): |
| cmd = ['git', 'rev-parse', '--git-dir'] |
| ret = cros_build_lib.run(cmd, stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
| return ret.stdout.decode().strip() |
| |
| |
| def create_cl(git_repo, sub_dir, reviewers): |
| branch = '172930457-' + sub_dir.as_posix().replace('.', '') |
| if git.MatchBranchName(git_repo.as_posix(), branch): |
| logging.debug('branch already exists; skipping') |
| return |
| |
| remote = git.GetTrackingBranchViaManifest(git_repo, for_push=True) |
| |
| git.CreateBranch(git_repo=git_repo, |
| branch=branch, |
| branch_point=remote.ref) |
| |
| metadata_file_path = os.path.join(git_repo, sub_dir, METADATA_FILE_NAME) |
| with open(metadata_file_path, 'w') as f: |
| f.write(METADATA_TEMPLATE) |
| |
| git.AddPath(metadata_file_path) |
| |
| delim = ': ' |
| if sub_dir == pathlib.Path('.'): |
| sub_dir = '' |
| delim = '' |
| |
| commit_msg = COMMIT_MSG_TEMPLATE.format(COMPONENT=sub_dir, DELIM=delim) |
| git.Commit(git_repo, commit_msg) |
| upload = input( |
| f'Would you like to upload {metadata_file_path}? [y/n]') |
| if upload == 'y': |
| git.UploadCL(git_repo=git_repo, remote=remote.remote, |
| branch=remote.ref.split('/')[-1], |
| reviewers=reviewers) |
| |
| git_rev = git.GetGitRepoRevision(git_repo) |
| gerrit_helper = gerrit.GetGerritHelper(remote=remote.remote) |
| gerrit_patch = gerrit_helper.QuerySingleRecord(git_rev) |
| gerrit_helper.SetReview(gerrit_patch, GERRIT_COMMENT) |
| gerrit_helper.SetHashtags(gerrit_patch, add=[GERRIT_HASHTAG], remove=[]) |
| |
| |
| def extract_owners(owners_file: pathlib.Path): |
| owners = [] |
| with open(owners_file) as f: |
| for line in f.readlines(): |
| line = line.strip() |
| if line and (not line.startswith('#') |
| and not line.startswith('include') |
| and not line.startswith('*')): |
| owners.append(line) |
| |
| return owners |
| |
| |
| def find_owners_files(git_repo): |
| logging.debug('searching %s', git_repo) |
| files = [] |
| for f in pathlib.Path(git_repo).rglob('OWNERS'): |
| files.append(f) |
| return files |
| |
| |
| def create_metadata_files(root_dir: pathlib.Path): |
| owners_files = find_owners_files(root_dir) |
| for file_path in owners_files: |
| if os.path.exists(file_path.joinpath(METADATA_FILE_NAME)): |
| logging.debug('skipping existing file: %s', file_path) |
| continue |
| logging.debug('file_path: %s', file_path) |
| owners = extract_owners(file_path) |
| dir_name = file_path.parent.relative_to(root_dir) |
| create_cl(sub_dir=dir_name, git_repo=root_dir, reviewers=owners) |
| |
| |
| def chromium_metadata(): |
| try: |
| git_dir = find_git_dir() |
| logging.debug(git_dir) |
| git_repo = git.GetGitGitdir(git_dir) |
| create_metadata_files(pathlib.Path(git_repo).parent) |
| except cros_build_lib.RunCommandError: |
| logging.error('Must be run in a git repo.') |
| sys.exit(1) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| |
| log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] |
| parser.add_argument( |
| '--log_level', '-l', |
| choices=log_level_choices, |
| default='INFO' |
| ) |
| |
| args = parser.parse_args() |
| logging.basicConfig(level=args.log_level) |
| |
| chromium_metadata() |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |