blob: e6af589e47004fd9a19897d87f170f4163feda91 [file] [log] [blame]
#!/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())