blob: eedc35dd920e0443d88ab3f2710e632d65e50434 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Linter for various OWNERS files."""
import logging
from pathlib import Path
_HACK_VAR_TO_DISABLE_ISORT = "hack"
# pylint: disable=wrong-import-position
import chromite_init # pylint: disable=unused-import
from chromite.lib import commandline
from chromite.lib import git
TOP_DIR = Path(__file__).resolve().parent.parent
def GetActiveProjects():
"""Return the list of active projects."""
# Look at all the paths (files & dirs) in the top of the git repo. This way
# we ignore local directories devs created that aren't actually committed.
cmd = ["ls-tree", "--name-only", "-z", "HEAD"]
result = git.RunGit(TOP_DIR, cmd)
# Split the output on NULs to avoid whitespace/etc... issues.
paths = result.stdout.split("\0")
# ls-tree -z includes a trailing NUL on all entries, not just seperation,
# so filter it out if found (in case ls-tree behavior changes on us).
for path in [Path(x) for x in paths if x]:
if (TOP_DIR / path).is_dir():
yield path
def CheckSubdirs():
"""Check the subdir OWNERS files exist."""
ret = 0
for proj in GetActiveProjects():
path = TOP_DIR / proj / "OWNERS"
if not path.exists():
logging.error('*** Project "%s" needs an OWNERS file', proj)
ret = 1
continue
data = path.read_text()
for i, line in enumerate(data.splitlines(), start=1):
if line.strip().startswith("set noparent"):
logging.error(
'*** %s:%i: Do not use "noparent" in top level projects',
path,
i,
)
ret = 1
if line.strip() != line:
logging.error(
"*** %s:%i: Trim leading/trailing whitespace", path, i
)
ret = 1
if not data:
logging.error("*** %s: File is empty", path)
ret = 1
if not data.endswith("\n"):
logging.error("*** %s: Missing trailing newline", path)
ret = 1
if data.startswith("\n"):
logging.error("*** %s: Trim leading blanklines", path)
ret = 1
if data.endswith("\n\n"):
logging.error("*** %s: Trim trailing blanklines", path)
ret = 1
return ret
def GetParser():
"""Return an argument parser."""
parser = commandline.ArgumentParser(description=__doc__)
return parser
def main(argv):
"""The main func!"""
parser = GetParser()
opts = parser.parse_args(argv)
opts.Freeze()
return CheckSubdirs()
if __name__ == "__main__":
commandline.ScriptWrapperMain(lambda _: main)