blob: c63bbc2fd2cf69cd13281fce0ef9af531e4894bf [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 Beltran1f2dd082022-04-25 18:42:32 +000019from chromite.lib.parser import package_info
20from chromite.service import toolchain
21from chromite.utils import file_util
22
23
Ryan Beltranb2175862022-04-28 19:55:57 +000024def parse_packages(board: str,
25 packages: List[str]) -> List[package_info.PackageInfo]:
26 """Parse packages and insert the category if none is given.
27
28 Args:
29 board: board for sysroot (used with equery to detect categories if needed)
30 packages: user input package names to parse
31
32 Returns:
33 A list of parsed PackageInfo objects
34 """
35 package_infos: List[package_info.PackageInfo] = []
36 for package in packages:
37 parsed = package_info.parse(package)
38 if not parsed.category:
39 # If a category is not specified, we can get it from the ebuild path.
40 ebuild_path = portage_util.FindEbuildForBoardPackage(package, board)
41 ebuild_data = portage_util.EBuild(ebuild_path)
42 parsed = package_info.parse(ebuild_data.package)
43 package_infos.append(parsed)
44 return package_infos
45
46
Ryan Beltran1f2dd082022-04-25 18:42:32 +000047def get_arg_parser() -> commandline.ArgumentParser:
48 """Creates an argument parser for this script."""
49 default_board = cros_build_lib.GetDefaultBoard()
50 parser = commandline.ArgumentParser(description=__doc__)
51 parser.add_argument(
52 '--differential',
53 action='store_true',
54 help='only lint lines touched by the last commit')
55 parser.add_argument(
56 '-b',
57 '--board',
58 '--build-target',
59 dest='board',
60 default=default_board,
61 required=not default_board,
62 help='The board to emerge packages for')
63 parser.add_argument(
64 '-o',
65 '--output',
66 default=sys.stdout,
67 help='File to use instead of stdout.')
68 parser.add_argument(
69 '--no-clippy',
70 dest='clippy',
71 action='store_false',
72 help='Disable cargo clippy linter.')
73 parser.add_argument(
74 '--no-tidy',
75 dest='tidy',
76 action='store_false',
77 help='Disable clang tidy linter.')
78 parser.add_argument(
79 'packages', nargs='+', help='package(s) to emerge and retrieve lints for')
80 return parser
81
82
83def parse_args(argv: List[str]):
84 """Parses arguments in argv and returns the options."""
85 parser = get_arg_parser()
86 opts = parser.parse_args(argv)
87 opts.Freeze()
88 return opts
89
90
91def main(argv: List[str]) -> None:
92 cros_build_lib.AssertInsideChroot()
93 opts = parse_args(argv)
94
Ryan Beltranb2175862022-04-28 19:55:57 +000095 packages = parse_packages(opts.board, opts.packages)
Ryan Beltran1f2dd082022-04-25 18:42:32 +000096 sysroot = build_target_lib.get_default_sysroot_path(opts.board)
97
98 build_linter = toolchain.BuildLinter(packages, sysroot, opts.differential)
99 lints = build_linter.emerge_with_linting(
100 use_clippy=opts.clippy, use_tidy=opts.tidy)
101
102 with file_util.Open(opts.output, 'w') as output_file:
103 json.dump(lints, output_file)