blob: 86f69b6bb9d02714e5a97d695557cf37ec2b012b [file] [log] [blame]
Ryan Beltran1f2dd082022-04-25 18:42:32 +00001# Copyright 2022 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This script emerges packages and retrieves their lints.
6
7Currently support is provided for both general and differential linting of C++
8with Clang Tidy and Rust with Cargo Clippy for all packages within platform2.
9"""
10
11import json
12import sys
13from typing import List
14
15from chromite.lib import build_target_lib
16from chromite.lib import commandline
17from chromite.lib import cros_build_lib
Ryan Beltranb2175862022-04-28 19:55:57 +000018from chromite.lib import portage_util
Ryan Beltran5514eab2022-04-28 21:40:24 +000019from chromite.lib import workon_helper
Ryan Beltran1f2dd082022-04-25 18:42:32 +000020from chromite.lib.parser import package_info
21from chromite.service import toolchain
22from chromite.utils import file_util
23
24
Ryan Beltran5514eab2022-04-28 21:40:24 +000025def parse_packages(build_target: build_target_lib.BuildTarget,
Ryan Beltranb2175862022-04-28 19:55:57 +000026 packages: List[str]) -> List[package_info.PackageInfo]:
27 """Parse packages and insert the category if none is given.
28
29 Args:
Ryan Beltran5514eab2022-04-28 21:40:24 +000030 build_target: build_target to find ebuild for
Ryan Beltranb2175862022-04-28 19:55:57 +000031 packages: user input package names to parse
32
33 Returns:
34 A list of parsed PackageInfo objects
35 """
36 package_infos: List[package_info.PackageInfo] = []
37 for package in packages:
38 parsed = package_info.parse(package)
39 if not parsed.category:
40 # If a category is not specified, we can get it from the ebuild path.
Ryan Beltran5514eab2022-04-28 21:40:24 +000041 ebuild_path = portage_util.FindEbuildForBoardPackage(
42 package, build_target.name, build_target.root)
Ryan Beltranb2175862022-04-28 19:55:57 +000043 ebuild_data = portage_util.EBuild(ebuild_path)
44 parsed = package_info.parse(ebuild_data.package)
45 package_infos.append(parsed)
46 return package_infos
47
48
Ryan Beltran1f2dd082022-04-25 18:42:32 +000049def get_arg_parser() -> commandline.ArgumentParser:
50 """Creates an argument parser for this script."""
51 default_board = cros_build_lib.GetDefaultBoard()
52 parser = commandline.ArgumentParser(description=__doc__)
53 parser.add_argument(
54 '--differential',
55 action='store_true',
56 help='only lint lines touched by the last commit')
57 parser.add_argument(
58 '-b',
59 '--board',
60 '--build-target',
61 dest='board',
62 default=default_board,
63 required=not default_board,
64 help='The board to emerge packages for')
65 parser.add_argument(
66 '-o',
67 '--output',
68 default=sys.stdout,
69 help='File to use instead of stdout.')
70 parser.add_argument(
71 '--no-clippy',
72 dest='clippy',
73 action='store_false',
74 help='Disable cargo clippy linter.')
75 parser.add_argument(
76 '--no-tidy',
77 dest='tidy',
78 action='store_false',
79 help='Disable clang tidy linter.')
80 parser.add_argument(
81 'packages', nargs='+', help='package(s) to emerge and retrieve lints for')
82 return parser
83
84
85def parse_args(argv: List[str]):
86 """Parses arguments in argv and returns the options."""
87 parser = get_arg_parser()
88 opts = parser.parse_args(argv)
89 opts.Freeze()
90 return opts
91
92
93def main(argv: List[str]) -> None:
94 cros_build_lib.AssertInsideChroot()
95 opts = parse_args(argv)
96
Ryan Beltran5514eab2022-04-28 21:40:24 +000097 build_target = build_target_lib.BuildTarget(opts.board)
98 packages = parse_packages(build_target, opts.packages)
99 package_atoms = [x.atom for x in packages]
Ryan Beltran1f2dd082022-04-25 18:42:32 +0000100
Ryan Beltran5514eab2022-04-28 21:40:24 +0000101 with workon_helper.WorkonScope(build_target, package_atoms):
102 build_linter = toolchain.BuildLinter(packages, build_target.root,
103 opts.differential)
104 lints = build_linter.emerge_with_linting(
105 use_clippy=opts.clippy, use_tidy=opts.tidy)
Ryan Beltran1f2dd082022-04-25 18:42:32 +0000106
107 with file_util.Open(opts.output, 'w') as output_file:
108 json.dump(lints, output_file)