blob: ec32a16223ff3a96bfda872eb554c6fea94df765 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2021 The ChromiumOS Authors
# 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 pathlib
import subprocess
import sys
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())