blob: 30d1622f99b08f297ab08e4ee2dadab514d31cb3 [file] [log] [blame]
Alex Kleineb77ffa2019-05-28 14:47:44 -06001# Copyright 2019 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"""Package utility functionality."""
6
Yaakov Shaul730814a2019-09-10 13:58:25 -06007import collections
Ben Reiche779cf42020-12-15 03:21:31 +00008from distutils.version import LooseVersion
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -06009import fileinput
Alex Klein87531182019-08-12 15:23:37 -060010import functools
Yaakov Shaul395ae832019-09-09 14:45:32 -060011import json
Chris McDonaldf7c03d42021-07-21 11:54:26 -060012import logging
Evan Hernandezb51f1522019-08-15 11:29:40 -060013import os
Michael Mortensenb70e8a82019-10-10 18:43:41 -060014import re
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -060015import sys
Alex Klein68a28712021-11-08 11:08:30 -070016from typing import Iterable, List, NamedTuple, Optional, TYPE_CHECKING, Union
Alex Klein87531182019-08-12 15:23:37 -060017
Mike Frysinger2c024062021-05-22 15:43:22 -040018from chromite.third_party.google.protobuf import json_format
Yaakov Shaul730814a2019-09-10 13:58:25 -060019
Andrew Lamb2bde9e42019-11-04 13:24:09 -070020from chromite.api.gen.config import replication_config_pb2
Michael Mortensen9fdb14b2019-10-17 11:17:30 -060021from chromite.cbuildbot import manifest_version
Alex Kleineb77ffa2019-05-28 14:47:44 -060022from chromite.lib import constants
Evan Hernandezb51f1522019-08-15 11:29:40 -060023from chromite.lib import cros_build_lib
Alex Kleineb77ffa2019-05-28 14:47:44 -060024from chromite.lib import git
Michael Mortensende716a12020-05-15 11:27:00 -060025from chromite.lib import image_lib
Michael Mortensenb70e8a82019-10-10 18:43:41 -060026from chromite.lib import osutils
Alex Kleineb77ffa2019-05-28 14:47:44 -060027from chromite.lib import portage_util
Andrew Lamb2bde9e42019-11-04 13:24:09 -070028from chromite.lib import replication_lib
Alex Kleind6195b62019-08-06 16:01:16 -060029from chromite.lib import uprev_lib
Alex Klein18a60af2020-06-11 12:08:47 -060030from chromite.lib.parser import package_info
Alex Kleineb77ffa2019-05-28 14:47:44 -060031
Alex Klein5caab872021-09-10 11:44:37 -060032if TYPE_CHECKING:
33 from chromite.lib import build_target_lib
Alex Klein16ea1b32021-10-01 15:48:50 -060034 from chromite.lib import chroot_lib
Chris McDonaldf7c03d42021-07-21 11:54:26 -060035
Alex Klein36b117f2019-09-30 15:13:46 -060036if cros_build_lib.IsInsideChroot():
Alex Klein6becabc2020-09-11 14:03:05 -060037 from chromite.lib import depgraph
Alex Klein36b117f2019-09-30 15:13:46 -060038 from chromite.service import dependency
39
Alex Klein87531182019-08-12 15:23:37 -060040# Registered handlers for uprevving versioned packages.
41_UPREV_FUNCS = {}
42
Alex Kleineb77ffa2019-05-28 14:47:44 -060043
44class Error(Exception):
45 """Module's base error class."""
46
47
Alex Klein4de25e82019-08-05 15:58:39 -060048class UnknownPackageError(Error):
49 """Uprev attempted for a package without a registered handler."""
50
51
Alex Kleineb77ffa2019-05-28 14:47:44 -060052class UprevError(Error):
53 """An error occurred while uprevving packages."""
54
55
Michael Mortensenb70e8a82019-10-10 18:43:41 -060056class NoAndroidVersionError(Error):
57 """An error occurred while trying to determine the android version."""
58
59
60class NoAndroidBranchError(Error):
61 """An error occurred while trying to determine the android branch."""
62
63
64class NoAndroidTargetError(Error):
65 """An error occurred while trying to determine the android target."""
66
67
Alex Klein4de25e82019-08-05 15:58:39 -060068class AndroidIsPinnedUprevError(UprevError):
69 """Raised when we try to uprev while Android is pinned."""
70
71 def __init__(self, new_android_atom):
72 """Initialize a AndroidIsPinnedUprevError.
73
74 Args:
75 new_android_atom: The Android atom that we failed to
76 uprev to, due to Android being pinned.
77 """
78 assert new_android_atom
79 msg = ('Failed up uprev to Android version %s as Android was pinned.' %
80 new_android_atom)
Jae Hoon Kimad176b82021-07-26 19:29:29 +000081 super().__init__(msg)
Alex Klein4de25e82019-08-05 15:58:39 -060082 self.new_android_atom = new_android_atom
Alex Klein87531182019-08-12 15:23:37 -060083
84
Andrew Lamb9563a152019-12-04 11:42:18 -070085class GeneratedCrosConfigFilesError(Error):
86 """Error when cros_config_schema does not produce expected files"""
87
88 def __init__(self, expected_files, found_files):
89 msg = ('Expected to find generated C files: %s. Actually found: %s' %
90 (expected_files, found_files))
Jae Hoon Kimad176b82021-07-26 19:29:29 +000091 super().__init__(msg)
Andrew Lamb9563a152019-12-04 11:42:18 -070092
Alex Klein7a3a7dd2020-01-08 16:44:38 -070093
Alex Klein6becabc2020-09-11 14:03:05 -060094NeedsChromeSourceResult = collections.namedtuple('NeedsChromeSourceResult', (
95 'needs_chrome_source',
96 'builds_chrome',
97 'packages',
98 'missing_chrome_prebuilt',
99 'missing_follower_prebuilt',
Alex Klein9ce3f682021-06-23 15:06:44 -0600100 'local_uprev',
Alex Klein6becabc2020-09-11 14:03:05 -0600101))
102
103
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600104def patch_ebuild_vars(ebuild_path, variables):
105 """Updates variables in ebuild.
106
107 Use this function rather than portage_util.EBuild.UpdateEBuild when you
108 want to preserve the variable position and quotes within the ebuild.
109
110 Args:
111 ebuild_path: The path of the ebuild.
112 variables: Dictionary of variables to update in ebuild.
113 """
114 try:
115 for line in fileinput.input(ebuild_path, inplace=1):
116 varname, eq, _ = line.partition('=')
117 if eq == '=' and varname.strip() in variables:
118 value = variables[varname]
119 sys.stdout.write('%s="%s"\n' % (varname, value))
120 else:
121 sys.stdout.write(line)
122 finally:
123 fileinput.close()
124
125
Alex Klein87531182019-08-12 15:23:37 -0600126def uprevs_versioned_package(package):
127 """Decorator to register package uprev handlers."""
128 assert package
129
130 def register(func):
131 """Registers |func| as a handler for |package|."""
132 _UPREV_FUNCS[package] = func
133
134 @functools.wraps(func)
135 def pass_through(*args, **kwargs):
136 return func(*args, **kwargs)
137
138 return pass_through
139
140 return register
141
142
Shao-Chuan Leeb6a2cb62021-02-19 14:18:59 +0900143def uprev_android(android_package,
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700144 chroot,
145 build_targets=None,
Shao-Chuan Leea4b4f302021-05-12 14:40:20 +0900146 android_build_branch=None,
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900147 android_version=None,
148 skip_commit=False):
Alex Klein4de25e82019-08-05 15:58:39 -0600149 """Returns the portage atom for the revved Android ebuild - see man emerge."""
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700150 command = [
151 'cros_mark_android_as_stable',
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900152 f'--android_package={android_package}',
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700153 ]
Alex Klein4de25e82019-08-05 15:58:39 -0600154 if build_targets:
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900155 command.append(f'--boards={":".join(bt.name for bt in build_targets)}')
Shao-Chuan Leea4b4f302021-05-12 14:40:20 +0900156 if android_build_branch:
157 command.append(f'--android_build_branch={android_build_branch}')
Alex Klein4de25e82019-08-05 15:58:39 -0600158 if android_version:
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900159 command.append(f'--force_version={android_version}')
160 if skip_commit:
161 command.append('--skip_commit')
Alex Klein4de25e82019-08-05 15:58:39 -0600162
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700163 result = cros_build_lib.run(
164 command,
165 stdout=True,
166 enter_chroot=True,
Mike Frysinger88d96362020-02-14 19:05:45 -0500167 encoding='utf-8',
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700168 chroot_args=chroot.get_enter_args())
Alex Klein4de25e82019-08-05 15:58:39 -0600169
Mike Frysinger88d96362020-02-14 19:05:45 -0500170 portage_atom_string = result.stdout.strip()
171 android_atom = None
172 if portage_atom_string:
173 android_atom = portage_atom_string.splitlines()[-1].partition('=')[-1]
Alex Klein4de25e82019-08-05 15:58:39 -0600174 if not android_atom:
175 logging.info('Found nothing to rev.')
176 return None
177
178 for target in build_targets or []:
179 # Sanity check: We should always be able to merge the version of
180 # Android we just unmasked.
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900181 command = [f'emerge-{target.name}', '-p', '--quiet', f'={android_atom}']
Alex Klein4de25e82019-08-05 15:58:39 -0600182 try:
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700183 cros_build_lib.run(
184 command, enter_chroot=True, chroot_args=chroot.get_enter_args())
Alex Klein4de25e82019-08-05 15:58:39 -0600185 except cros_build_lib.RunCommandError:
186 logging.error(
187 'Cannot emerge-%s =%s\nIs Android pinned to an older '
188 'version?', target, android_atom)
189 raise AndroidIsPinnedUprevError(android_atom)
190
191 return android_atom
192
193
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700194def uprev_build_targets(
195 build_targets: Optional[List['build_target_lib.BuildTarget']],
196 overlay_type: str,
197 chroot: 'chroot_lib.Chroot' = None,
198 output_dir: Optional[str] = None):
Alex Kleineb77ffa2019-05-28 14:47:44 -0600199 """Uprev the set provided build targets, or all if not specified.
200
201 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700202 build_targets: The build targets
Alex Kleineb77ffa2019-05-28 14:47:44 -0600203 whose overlays should be uprevved, empty or None for all.
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700204 overlay_type: One of the valid overlay types except None (see
Alex Kleineb77ffa2019-05-28 14:47:44 -0600205 constants.VALID_OVERLAYS).
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700206 chroot: The chroot to clean, if desired.
207 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600208 """
209 # Need a valid overlay, but exclude None.
210 assert overlay_type and overlay_type in constants.VALID_OVERLAYS
211
212 if build_targets:
213 overlays = portage_util.FindOverlaysForBoards(
214 overlay_type, boards=[t.name for t in build_targets])
215 else:
216 overlays = portage_util.FindOverlays(overlay_type)
217
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700218 return uprev_overlays(
219 overlays,
220 build_targets=build_targets,
221 chroot=chroot,
222 output_dir=output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600223
224
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700225def uprev_overlays(
226 overlays: List[str],
227 build_targets: Optional[List['build_target_lib.BuildTarget']] = None,
228 chroot: Optional['chroot_lib.Chroot'] = None,
229 output_dir: Optional[str] = None) -> List[str]:
Alex Kleineb77ffa2019-05-28 14:47:44 -0600230 """Uprev the given overlays.
231
232 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700233 overlays: The list of overlay paths.
234 build_targets: The build targets
Alex Kleineb77ffa2019-05-28 14:47:44 -0600235 to clean in |chroot|, if desired. No effect unless |chroot| is provided.
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700236 chroot: The chroot to clean, if desired.
237 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600238
239 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700240 The paths to all of the modified ebuild files. This includes the new files
241 that were added (i.e. the new versions) and all of the removed files
242 (i.e. the old versions).
Alex Kleineb77ffa2019-05-28 14:47:44 -0600243 """
244 assert overlays
245
246 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
247
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700248 uprev_manager = uprev_lib.UprevOverlayManager(
249 overlays,
250 manifest,
251 build_targets=build_targets,
252 chroot=chroot,
253 output_dir=output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600254 uprev_manager.uprev()
255
Dhanya Ganeshd03a4162021-08-25 00:21:50 +0000256 return uprev_manager.modified_ebuilds, uprev_manager.revved_packages
Alex Kleineb77ffa2019-05-28 14:47:44 -0600257
258
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700259def uprev_versioned_package(
260 package: package_info.CPV,
261 build_targets: List['build_target_lib.BuildTarget'],
262 refs: List[uprev_lib.GitRef],
263 chroot: 'chroot_lib.Chroot') -> 'uprev_lib.UprevVersionedPackageResult':
Alex Klein87531182019-08-12 15:23:37 -0600264 """Call registered uprev handler function for the package.
265
266 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700267 package: The package being uprevved.
268 build_targets: The build targets to clean on a successful uprev.
269 refs:
270 chroot: The chroot to enter for cleaning.
Alex Klein87531182019-08-12 15:23:37 -0600271
272 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700273 The result.
Alex Klein87531182019-08-12 15:23:37 -0600274 """
275 assert package
276
277 if package.cp not in _UPREV_FUNCS:
278 raise UnknownPackageError(
279 'Package "%s" does not have a registered handler.' % package.cp)
280
Andrew Lambea9a8a22019-12-12 14:03:43 -0700281 return _UPREV_FUNCS[package.cp](build_targets, refs, chroot)
Alex Klein87531182019-08-12 15:23:37 -0600282
283
Navil Perezf57ba872020-06-04 22:38:37 +0000284@uprevs_versioned_package('media-libs/virglrenderer')
285def uprev_virglrenderer(_build_targets, refs, _chroot):
286 """Updates virglrenderer ebuilds.
287
288 See: uprev_versioned_package.
289
290 Returns:
291 UprevVersionedPackageResult: The result of updating virglrenderer ebuilds.
292 """
Navil Perezf57ba872020-06-04 22:38:37 +0000293 overlay = os.path.join(constants.SOURCE_ROOT,
294 constants.CHROMIUMOS_OVERLAY_DIR)
George Engelbrechte73f2782020-06-10 14:10:46 -0600295 repo_path = os.path.join(constants.SOURCE_ROOT, 'src', 'third_party',
296 'virglrenderer')
297 manifest = git.ManifestCheckout.Cached(repo_path)
Navil Perezf57ba872020-06-04 22:38:37 +0000298
299 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
300 # TODO(crbug.com/1066242): Ebuilds for virglrenderer are currently
Jose Magana03b5a842020-08-19 12:52:59 +1000301 # denylisted. Do not force uprevs after builder is stable and ebuilds are no
302 # longer denylisted.
Navil Perezf57ba872020-06-04 22:38:37 +0000303 uprev_manager.uprev(package_list=['media-libs/virglrenderer'], force=True)
304
George Engelbrechte73f2782020-06-10 14:10:46 -0600305 updated_files = uprev_manager.modified_ebuilds
Chris McDonald38409112020-09-24 11:24:51 -0600306 result = uprev_lib.UprevVersionedPackageResult()
Navil Perezf57ba872020-06-04 22:38:37 +0000307 result.add_result(refs[0].revision, updated_files)
308 return result
309
Jose Magana03b5a842020-08-19 12:52:59 +1000310@uprevs_versioned_package('chromeos-base/drivefs')
311def uprev_drivefs(_build_targets, refs, chroot):
312 """Updates drivefs ebuilds.
313
Harvey Yang3eee06c2021-03-18 15:47:56 +0800314 DriveFS versions follow the tag format of refs/tags/drivefs_1.2.3.
Jose Magana03b5a842020-08-19 12:52:59 +1000315 See: uprev_versioned_package.
316
317 Returns:
318 UprevVersionedPackageResult: The result of updating drivefs ebuilds.
319 """
320
Ben Reiche779cf42020-12-15 03:21:31 +0000321 DRIVEFS_PATH_PREFIX = 'src/private-overlays/chromeos-overlay/chromeos-base'
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000322 result = uprev_lib.UprevVersionedPackageResult()
323 all_changed_files = []
Jose Magana03b5a842020-08-19 12:52:59 +1000324
Harvey Yang3eee06c2021-03-18 15:47:56 +0800325 DRIVEFS_REFS_PREFIX = 'refs/tags/drivefs_'
326 drivefs_version = _get_latest_version_from_refs(DRIVEFS_REFS_PREFIX, refs)
Ben Reiche779cf42020-12-15 03:21:31 +0000327 if not drivefs_version:
328 # No valid DriveFS version is identified.
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000329 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000330
Ben Reiche779cf42020-12-15 03:21:31 +0000331 logging.debug('DriveFS version determined from refs: %s', drivefs_version)
Jose Magana03b5a842020-08-19 12:52:59 +1000332
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000333 # Attempt to uprev drivefs package.
Ben Reiche779cf42020-12-15 03:21:31 +0000334 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, 'drivefs')
Jose Magana03b5a842020-08-19 12:52:59 +1000335 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(pkg_path,
Ben Reiche779cf42020-12-15 03:21:31 +0000336 drivefs_version,
Harvey Yang3eee06c2021-03-18 15:47:56 +0800337 chroot,
338 allow_downrev=False)
Jose Magana03b5a842020-08-19 12:52:59 +1000339
340 if not uprev_result:
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000341 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000342 all_changed_files.extend(uprev_result.changed_files)
343
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000344 # Attempt to uprev drivefs-ipc package.
Ben Reiche779cf42020-12-15 03:21:31 +0000345 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, 'drivefs-ipc')
Jose Magana03b5a842020-08-19 12:52:59 +1000346 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(pkg_path,
Ben Reiche779cf42020-12-15 03:21:31 +0000347 drivefs_version,
Harvey Yang3eee06c2021-03-18 15:47:56 +0800348 chroot,
349 allow_downrev=False)
Jose Magana03b5a842020-08-19 12:52:59 +1000350
351 if not uprev_result:
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000352 logging.warning(
353 'drivefs package has changed files %s but drivefs-ipc does not',
354 all_changed_files)
355 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000356
357 all_changed_files.extend(uprev_result.changed_files)
Ben Reiche779cf42020-12-15 03:21:31 +0000358 result.add_result(drivefs_version, all_changed_files)
Jose Magana03b5a842020-08-19 12:52:59 +1000359
360 return result
361
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800362@uprevs_versioned_package('chromeos-base/perfetto')
363def uprev_perfetto(_build_targets, refs, chroot):
364 """Updates Perfetto ebuilds.
365
Harvey Yang3eee06c2021-03-18 15:47:56 +0800366 Perfetto versions follow the tag format of refs/tags/v1.2.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800367 See: uprev_versioned_package.
368
369 Returns:
370 UprevVersionedPackageResult: The result of updating Perfetto ebuilds.
371 """
372 result = uprev_lib.UprevVersionedPackageResult()
373
Harvey Yang3eee06c2021-03-18 15:47:56 +0800374 PERFETTO_REFS_PREFIX = 'refs/tags/v'
375 perfetto_version = _get_latest_version_from_refs(PERFETTO_REFS_PREFIX, refs)
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800376 if not perfetto_version:
377 # No valid Perfetto version is identified.
378 return result
379
380 logging.debug('Perfetto version determined from refs: %s', perfetto_version)
381
382 # Attempt to uprev perfetto package.
383 PERFETTO_PATH = 'src/third_party/chromiumos-overlay/chromeos-base/perfetto'
384
Harvey Yang3eee06c2021-03-18 15:47:56 +0800385 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
386 PERFETTO_PATH,
387 perfetto_version,
388 chroot,
389 allow_downrev=False,
390 ref=PERFETTO_REFS_PREFIX + perfetto_version)
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800391
392 if not uprev_result:
393 return result
394
395 result.add_result(perfetto_version, uprev_result.changed_files)
396
397 return result
Navil Perezf57ba872020-06-04 22:38:37 +0000398
Yaakov Shaul395ae832019-09-09 14:45:32 -0600399@uprevs_versioned_package('afdo/kernel-profiles')
400def uprev_kernel_afdo(*_args, **_kwargs):
David Burger92485342019-09-10 17:52:45 -0600401 """Updates kernel ebuilds with versions from kernel_afdo.json.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600402
403 See: uprev_versioned_package.
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600404
405 Raises:
406 EbuildManifestError: When ebuild manifest does not complete successfuly.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600407 """
408 path = os.path.join(constants.SOURCE_ROOT, 'src', 'third_party',
409 'toolchain-utils', 'afdo_metadata', 'kernel_afdo.json')
410
David Burger92485342019-09-10 17:52:45 -0600411 with open(path, 'r') as f:
412 versions = json.load(f)
Yaakov Shaul395ae832019-09-09 14:45:32 -0600413
Chris McDonald38409112020-09-24 11:24:51 -0600414 result = uprev_lib.UprevVersionedPackageResult()
Alex Klein6edd4e62021-07-08 12:43:25 -0600415 for kernel_pkg, version_info in versions.items():
416 path = os.path.join(constants.CHROMIUMOS_OVERLAY_DIR,
417 'sys-kernel', kernel_pkg)
Yaakov Shauldd8b4112019-09-11 11:44:03 -0600418 ebuild_path = os.path.join(constants.SOURCE_ROOT, path,
Alex Klein6edd4e62021-07-08 12:43:25 -0600419 '%s-9999.ebuild' % kernel_pkg)
Yaakov Shaula187b152019-09-11 12:41:32 -0600420 chroot_ebuild_path = os.path.join(constants.CHROOT_SOURCE_ROOT, path,
Alex Klein6edd4e62021-07-08 12:43:25 -0600421 '%s-9999.ebuild' % kernel_pkg)
Yaakov Shaul730814a2019-09-10 13:58:25 -0600422 afdo_profile_version = version_info['name']
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600423 patch_ebuild_vars(ebuild_path,
424 dict(AFDO_PROFILE_VERSION=afdo_profile_version))
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600425
426 try:
Yaakov Shaul730814a2019-09-10 13:58:25 -0600427 cmd = ['ebuild', chroot_ebuild_path, 'manifest', '--force']
Mike Frysinger45602c72019-09-22 02:15:11 -0400428 cros_build_lib.run(cmd, enter_chroot=True)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600429 except cros_build_lib.RunCommandError as e:
Chris McDonald38409112020-09-24 11:24:51 -0600430 raise uprev_lib.EbuildManifestError(
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600431 'Error encountered when regenerating the manifest for ebuild: %s\n%s'
Yaakov Shaula187b152019-09-11 12:41:32 -0600432 % (chroot_ebuild_path, e), e)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600433
Yaakov Shauldd8b4112019-09-11 11:44:03 -0600434 manifest_path = os.path.join(constants.SOURCE_ROOT, path, 'Manifest')
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600435
Yaakov Shaul730814a2019-09-10 13:58:25 -0600436 result.add_result(afdo_profile_version, [ebuild_path, manifest_path])
437
438 return result
Yaakov Shaul395ae832019-09-09 14:45:32 -0600439
440
Trent Begineb624182020-07-14 10:09:45 -0600441@uprevs_versioned_package('chromeos-base/termina-dlc')
442def uprev_termina_dlc(_build_targets, _refs, chroot):
443 """Updates shared termina-dlc ebuild - chromeos-base/termina-dlc.
Trent Beginaf51f1b2020-03-09 17:35:31 -0600444
445 See: uprev_versioned_package.
446 """
Trent Begineb624182020-07-14 10:09:45 -0600447 package = 'termina-dlc'
Trent Beginaf51f1b2020-03-09 17:35:31 -0600448 package_path = os.path.join(constants.CHROMIUMOS_OVERLAY_DIR, 'chromeos-base',
449 package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000450
451 version_pin_src_path = _get_version_pin_src_path(package_path)
452 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
453
Chris McDonald38409112020-09-24 11:24:51 -0600454 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000455
456
Julio Hurtadof1befec2021-05-05 21:34:26 +0000457@uprevs_versioned_package('chromeos-base/chromeos-lacros')
458def uprev_lacros(_build_targets, refs, chroot):
459 """Updates lacros ebuilds.
460
Julio Hurtadoa994e002021-07-07 17:57:45 +0000461 Version to uprev to is gathered from the QA qualified version tracking file
462 stored in chromium/src/chrome/LACROS_QA_QUALIFIED_VERSION. Uprev is triggered
463 on modification of this file across all chromium/src branches.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000464
465 See: uprev_versioned_package.
466 """
Julio Hurtadoa994e002021-07-07 17:57:45 +0000467 result = uprev_lib.UprevVersionedPackageResult()
Julio Hurtadof1befec2021-05-05 21:34:26 +0000468 path = os.path.join(
Dennis Kempin257b74c2021-09-28 14:38:17 -0700469 constants.CHROMIUMOS_OVERLAY_DIR, 'chromeos-base', 'chromeos-lacros')
Julio Hurtadoa994e002021-07-07 17:57:45 +0000470 lacros_version = refs[0].revision
471 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(path,
472 lacros_version,
473 chroot,
474 allow_downrev=False)
475
476 if not uprev_result:
477 return result
478
479 result.add_result(lacros_version, uprev_result.changed_files)
480 return result
Julio Hurtadof1befec2021-05-05 21:34:26 +0000481
482
Patrick Meiring5897add2020-09-16 16:30:17 +1000483@uprevs_versioned_package('app-emulation/parallels-desktop')
484def uprev_parallels_desktop(_build_targets, _refs, chroot):
485 """Updates Parallels Desktop ebuild - app-emulation/parallels-desktop.
486
487 See: uprev_versioned_package
488
489 Returns:
490 UprevVersionedPackageResult: The result.
491 """
492 package = 'parallels-desktop'
493 package_path = os.path.join(constants.CHROMEOS_PARTNER_OVERLAY_DIR,
494 'app-emulation', package)
495 version_pin_src_path = _get_version_pin_src_path(package_path)
496
497 # Expect a JSON blob like the following:
498 # {
499 # "version": "1.2.3",
500 # "test_image": { "url": "...", "size": 12345678,
501 # "sha256sum": "<32 bytes of hexadecimal>" }
502 # }
503 with open(version_pin_src_path, 'r') as f:
504 pinned = json.load(f)
505
506 if 'version' not in pinned or 'test_image' not in pinned:
507 raise UprevError('VERSION-PIN for %s missing version and/or '
508 'test_image field' % package)
509
510 version = pinned['version']
511 if not isinstance(version, str):
512 raise UprevError('version in VERSION-PIN for %s not a string' % package)
513
514 # Update the ebuild.
Chris McDonald38409112020-09-24 11:24:51 -0600515 result = uprev_lib.uprev_ebuild_from_pin(package_path, version, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000516
517 # Update the VM image used for testing.
Patrick Meiring1342def2020-10-30 17:09:13 +1100518 test_image_path = ('src/platform/tast-tests-private/src/chromiumos/tast/'
519 'local/bundles/crosint/pita/data/'
520 'pluginvm_image.zip.external')
Patrick Meiring5897add2020-09-16 16:30:17 +1000521 test_image_src_path = os.path.join(constants.SOURCE_ROOT, test_image_path)
522 with open(test_image_src_path, 'w') as f:
523 json.dump(pinned['test_image'], f, indent=2)
524 result.add_result(version, [test_image_src_path])
525
526 return result
Trent Beginaf51f1b2020-03-09 17:35:31 -0600527
528
Trent Begin315d9d92019-12-03 21:55:53 -0700529@uprevs_versioned_package('chromeos-base/chromeos-dtc-vm')
Trent Beginaf51f1b2020-03-09 17:35:31 -0600530def uprev_sludge(_build_targets, _refs, chroot):
Trent Begin315d9d92019-12-03 21:55:53 -0700531 """Updates sludge VM - chromeos-base/chromeos-dtc-vm.
532
533 See: uprev_versioned_package.
534 """
535 package = 'chromeos-dtc-vm'
Trent Begind943df92020-02-25 10:30:10 -0700536 package_path = os.path.join('src', 'private-overlays',
537 'project-wilco-private', 'chromeos-base', package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000538 version_pin_src_path = _get_version_pin_src_path(package_path)
539 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Trent Begin315d9d92019-12-03 21:55:53 -0700540
Chris McDonald38409112020-09-24 11:24:51 -0600541 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Trent Begin315d9d92019-12-03 21:55:53 -0700542
543
David Riley8513c1f2021-10-14 17:07:41 -0700544@uprevs_versioned_package('chromeos-base/borealis-dlc')
545def uprev_borealis_dlc(_build_targets, _refs, chroot):
546 """Updates shared borealis-dlc ebuild - chromeos-base/borealis-dlc.
547
548 See: uprev_versioned_package.
549 """
550 package_path = os.path.join('src', 'private-overlays', 'chromeos-overlay',
551 'chromeos-base', 'borealis-dlc')
552
553 version_pin_src_path = _get_version_pin_src_path(package_path)
554 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
555
556 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
557
558
Patrick Meiring5897add2020-09-16 16:30:17 +1000559def _get_version_pin_src_path(package_path):
560 """Returns the path to the VERSION-PIN file for the given package."""
561 return os.path.join(constants.SOURCE_ROOT, package_path, 'VERSION-PIN')
562
563
Alex Klein87531182019-08-12 15:23:37 -0600564@uprevs_versioned_package(constants.CHROME_CP)
Alex Kleinf69bd802021-06-22 15:43:49 -0600565def uprev_chrome_from_ref(build_targets, refs, chroot):
Alex Klein87531182019-08-12 15:23:37 -0600566 """Uprev chrome and its related packages.
567
568 See: uprev_versioned_package.
569 """
570 # Determine the version from the refs (tags), i.e. the chrome versions are the
571 # tag names.
572 chrome_version = uprev_lib.get_chrome_version_from_refs(refs)
Chris McDonald25881af2020-05-12 03:17:53 -0600573 logging.debug('Chrome version determined from refs: %s', chrome_version)
Alex Klein87531182019-08-12 15:23:37 -0600574
Alex Klein16ea1b32021-10-01 15:48:50 -0600575 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600576
577
Alex Klein9ce3f682021-06-23 15:06:44 -0600578def revbump_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600579 build_targets: List['build_target_lib.BuildTarget'] = None,
Alex Klein9ce3f682021-06-23 15:06:44 -0600580 chroot: Optional['chroot_lib.Chroot'] = None
581) -> uprev_lib.UprevVersionedPackageResult:
Alex Kleinf69bd802021-06-22 15:43:49 -0600582 """Attempt to revbump chrome.
583
584 Revbumps are done by executing an uprev using the current stable version.
585 E.g. if chrome is on 1.2.3.4 and has a 1.2.3.4_rc-r2.ebuild, performing an
586 uprev on version 1.2.3.4 when there are applicable changes (e.g. to the 9999
587 ebuild) will result in a revbump to 1.2.3.4_rc-r3.ebuild.
588 """
589 chrome_version = uprev_lib.get_stable_chrome_version()
Alex Klein16ea1b32021-10-01 15:48:50 -0600590 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600591
592
Alex Klein9ce3f682021-06-23 15:06:44 -0600593def uprev_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600594 chrome_version: str,
595 build_targets: Optional[List['build_target_lib.BuildTarget']],
596 chroot: Optional['chroot_lib.Chroot']
Alex Klein9ce3f682021-06-23 15:06:44 -0600597) -> uprev_lib.UprevVersionedPackageResult:
598 """Attempt to uprev chrome and its related packages to the given version."""
Alex Klein87531182019-08-12 15:23:37 -0600599 uprev_manager = uprev_lib.UprevChromeManager(
600 chrome_version, build_targets=build_targets, chroot=chroot)
Chris McDonald38409112020-09-24 11:24:51 -0600601 result = uprev_lib.UprevVersionedPackageResult()
Chris McDonald25881af2020-05-12 03:17:53 -0600602 # TODO(crbug.com/1080429): Handle all possible outcomes of a Chrome uprev
603 # attempt. The expected behavior is documented in the following table:
604 #
605 # Outcome of Chrome uprev attempt:
606 # NEWER_VERSION_EXISTS:
607 # Do nothing.
608 # SAME_VERSION_EXISTS or REVISION_BUMP:
609 # Uprev followers
610 # Assert not VERSION_BUMP (any other outcome is fine)
611 # VERSION_BUMP or NEW_EBUILD_CREATED:
612 # Uprev followers
613 # Assert that Chrome & followers are at same package version
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600614
615 # Start with chrome itself so we can proceed accordingly.
616 chrome_result = uprev_manager.uprev(constants.CHROME_CP)
617 if chrome_result.newer_version_exists:
618 # Cannot use the given version (newer version already exists).
David Burger37f48672019-09-18 17:07:56 -0600619 return result
Alex Klein87531182019-08-12 15:23:37 -0600620
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600621 # Also uprev related packages.
Alex Klein87531182019-08-12 15:23:37 -0600622 for package in constants.OTHER_CHROME_PACKAGES:
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600623 follower_result = uprev_manager.uprev(package)
624 if chrome_result.stable_version and follower_result.version_bump:
625 logging.warning('%s had a version bump, but no more than a revision bump '
626 'should have been possible.', package)
Alex Klein87531182019-08-12 15:23:37 -0600627
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600628 if uprev_manager.modified_ebuilds:
629 # Record changes when we have them.
630 return result.add_result(chrome_version, uprev_manager.modified_ebuilds)
631
632 return result
Alex Klein87531182019-08-12 15:23:37 -0600633
634
Harvey Yang3eee06c2021-03-18 15:47:56 +0800635def _get_latest_version_from_refs(refs_prefix: str,
636 refs: List[uprev_lib.GitRef]) -> str:
637 """Get the latest version from refs
Ben Reiche779cf42020-12-15 03:21:31 +0000638
Ben Reiche779cf42020-12-15 03:21:31 +0000639 Versions are compared using |distutils.version.LooseVersion| and
640 the latest version is returned.
641
642 Args:
Harvey Yang3eee06c2021-03-18 15:47:56 +0800643 refs_prefix: The refs prefix of the tag format.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800644 refs: The tags to parse for the latest Perfetto version.
645
646 Returns:
647 The latest Perfetto version to use.
648 """
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800649 valid_refs = []
650 for gitiles in refs:
Harvey Yang3eee06c2021-03-18 15:47:56 +0800651 if gitiles.ref.startswith(refs_prefix):
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800652 valid_refs.append(gitiles.ref)
653
654 if not valid_refs:
655 return None
656
657 # Sort by version and take the latest version.
658 target_version_ref = sorted(valid_refs,
659 key=LooseVersion,
660 reverse=True)[0]
Harvey Yang3eee06c2021-03-18 15:47:56 +0800661 return target_version_ref.replace(refs_prefix, '')
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800662
663
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700664def _generate_platform_c_files(
665 replication_config: replication_config_pb2.ReplicationConfig,
666 chroot: 'chroot_lib.Chroot') -> List[str]:
Andrew Lamb9563a152019-12-04 11:42:18 -0700667 """Generates platform C files from a platform JSON payload.
668
669 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700670 replication_config: A ReplicationConfig that has already been run. If it
671 produced a build_config.json file, that file will be used to generate
672 platform C files. Otherwise, nothing will be generated.
673 chroot: The chroot to use to generate.
Andrew Lamb9563a152019-12-04 11:42:18 -0700674
675 Returns:
676 A list of generated files.
677 """
678 # Generate the platform C files from the build config. Note that it would be
679 # more intuitive to generate the platform C files from the platform config;
680 # however, cros_config_schema does not allow this, because the platform config
681 # payload is not always valid input. For example, if a property is both
682 # 'required' and 'build-only', it will fail schema validation. Thus, use the
683 # build config, and use '-f' to filter.
684 build_config_path = [
685 rule.destination_path
686 for rule in replication_config.file_replication_rules
687 if rule.destination_path.endswith('build_config.json')
688 ]
689
690 if not build_config_path:
691 logging.info(
Alex Kleinad6b48a2020-01-08 16:57:41 -0700692 'No build_config.json found, will not generate platform C files. '
693 'Replication config: %s', replication_config)
Andrew Lamb9563a152019-12-04 11:42:18 -0700694 return []
695
696 if len(build_config_path) > 1:
Alex Kleinad6b48a2020-01-08 16:57:41 -0700697 raise ValueError('Expected at most one build_config.json destination path. '
698 'Replication config: %s' % replication_config)
Andrew Lamb9563a152019-12-04 11:42:18 -0700699
700 build_config_path = build_config_path[0]
701
702 # Paths to the build_config.json and dir to output C files to, in the
703 # chroot.
704 build_config_chroot_path = os.path.join(constants.CHROOT_SOURCE_ROOT,
705 build_config_path)
706 generated_output_chroot_dir = os.path.join(constants.CHROOT_SOURCE_ROOT,
707 os.path.dirname(build_config_path))
708
709 command = [
710 'cros_config_schema', '-m', build_config_chroot_path, '-g',
711 generated_output_chroot_dir, '-f', '"TRUE"'
712 ]
713
714 cros_build_lib.run(
715 command, enter_chroot=True, chroot_args=chroot.get_enter_args())
716
717 # A relative (to the source root) path to the generated C files.
718 generated_output_dir = os.path.dirname(build_config_path)
719 generated_files = []
720 expected_c_files = ['config.c', 'ec_config.c', 'ec_config.h']
721 for f in expected_c_files:
722 if os.path.exists(
723 os.path.join(constants.SOURCE_ROOT, generated_output_dir, f)):
724 generated_files.append(os.path.join(generated_output_dir, f))
725
726 if len(expected_c_files) != len(generated_files):
727 raise GeneratedCrosConfigFilesError(expected_c_files, generated_files)
728
729 return generated_files
730
731
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700732def _get_private_overlay_package_root(ref: uprev_lib.GitRef, package: str):
Andrew Lambe836f222019-12-09 12:27:38 -0700733 """Returns the absolute path to the root of a given private overlay.
734
735 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700736 ref: GitRef for the private overlay.
737 package: Path to the package in the overlay.
Andrew Lambe836f222019-12-09 12:27:38 -0700738 """
739 # There might be a cleaner way to map from package -> path within the source
740 # tree. For now, just use string patterns.
Andrew Lamb4aa09912020-01-08 13:55:56 -0700741 private_overlay_ref_pattern = r'/chromeos\/overlays\/overlay-([\w-]+)-private'
Andrew Lambe836f222019-12-09 12:27:38 -0700742 match = re.match(private_overlay_ref_pattern, ref.path)
743 if not match:
744 raise ValueError('ref.path must match the pattern: %s. Actual ref: %s' %
745 (private_overlay_ref_pattern, ref))
746
747 overlay = match.group(1)
748
749 return os.path.join(constants.SOURCE_ROOT,
750 'src/private-overlays/overlay-%s-private' % overlay,
751 package)
752
753
Andrew Lambea9a8a22019-12-12 14:03:43 -0700754@uprevs_versioned_package('chromeos-base/chromeos-config-bsp')
755def replicate_private_config(_build_targets, refs, chroot):
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700756 """Replicate a private cros_config change to the corresponding public config.
757
Alex Kleinad6b48a2020-01-08 16:57:41 -0700758 See uprev_versioned_package for args
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700759 """
Andrew Lambea9a8a22019-12-12 14:03:43 -0700760 package = 'chromeos-base/chromeos-config-bsp'
761
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700762 if len(refs) != 1:
763 raise ValueError('Expected exactly one ref, actual %s' % refs)
764
765 # Expect a replication_config.jsonpb in the package root.
Andrew Lambe836f222019-12-09 12:27:38 -0700766 package_root = _get_private_overlay_package_root(refs[0], package)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700767 replication_config_path = os.path.join(package_root,
768 'replication_config.jsonpb')
769
770 try:
771 replication_config = json_format.Parse(
772 osutils.ReadFile(replication_config_path),
773 replication_config_pb2.ReplicationConfig())
774 except IOError:
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700775 raise ValueError(
776 'Expected ReplicationConfig missing at %s' % replication_config_path)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700777
778 replication_lib.Replicate(replication_config)
779
780 modified_files = [
781 rule.destination_path
782 for rule in replication_config.file_replication_rules
783 ]
784
Andrew Lamb9563a152019-12-04 11:42:18 -0700785 # The generated platform C files are not easily filtered by replication rules,
786 # i.e. JSON / proto filtering can be described by a FieldMask, arbitrary C
787 # files cannot. Therefore, replicate and filter the JSON payloads, and then
788 # generate filtered C files from the JSON payload.
789 modified_files.extend(_generate_platform_c_files(replication_config, chroot))
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700790
791 # Use the private repo's commit hash as the new version.
792 new_private_version = refs[0].revision
793
Andrew Lamb988f4da2019-12-10 10:16:43 -0700794 # modified_files should contain only relative paths at this point, but the
795 # returned UprevVersionedPackageResult must contain only absolute paths.
796 for i, modified_file in enumerate(modified_files):
797 assert not os.path.isabs(modified_file)
798 modified_files[i] = os.path.join(constants.SOURCE_ROOT, modified_file)
799
Chris McDonald38409112020-09-24 11:24:51 -0600800 return uprev_lib.UprevVersionedPackageResult().add_result(
801 new_private_version, modified_files)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700802
803
Dennis Kempinef05f2b2021-09-08 16:36:49 -0700804@uprevs_versioned_package('chromeos-base/crosvm')
805def uprev_crosvm(_build_targets, refs, _chroot):
806 """Updates crosvm ebuilds to latest revision
807
808 crosvm is not versioned. We are updating to the latest commit on the main
809 branch.
810
811 See: uprev_versioned_package.
812
813 Returns:
814 UprevVersionedPackageResult: The result of updating crosvm ebuilds.
815 """
816 overlay = os.path.join(constants.SOURCE_ROOT,
817 constants.CHROMIUMOS_OVERLAY_DIR)
818 repo_path = os.path.join(constants.SOURCE_ROOT, 'src', 'crosvm')
819 manifest = git.ManifestCheckout.Cached(repo_path)
820
821 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
Dennis Kempin257b74c2021-09-28 14:38:17 -0700822 uprev_manager.uprev(
823 package_list=[
824 'chromeos-base/crosvm',
825 'dev-rust/assertions',
826 'dev-rust/cros_async',
827 'dev-rust/cros_fuzz',
828 'dev-rust/data_model',
829 'dev-rust/enumn',
830 'dev-rust/io_uring',
831 'dev-rust/p9',
832 'dev-rust/sync',
833 'dev-rust/sys_util',
834 'dev-rust/tempfile',
835 'media-sound/audio_streams',
836 ],
837 force=True
838 )
Dennis Kempinef05f2b2021-09-08 16:36:49 -0700839
840 updated_files = uprev_manager.modified_ebuilds
841 result = uprev_lib.UprevVersionedPackageResult()
842 result.add_result(refs[0].revision, updated_files)
843 return result
844
845
Alex Klein5caab872021-09-10 11:44:37 -0600846def get_best_visible(
847 atom: str,
848 build_target: Optional['build_target_lib.BuildTarget'] = None
849) -> package_info.PackageInfo:
Alex Kleinbbef2b32019-08-27 10:38:50 -0600850 """Returns the best visible CPV for the given atom.
851
852 Args:
Alex Klein5caab872021-09-10 11:44:37 -0600853 atom: The atom to look up.
854 build_target: The build target whose sysroot should be searched, or the SDK
855 if not provided.
Alex Kleinad6b48a2020-01-08 16:57:41 -0700856
857 Returns:
Alex Klein5caab872021-09-10 11:44:37 -0600858 The best visible package, or None if none are visible.
Alex Kleinbbef2b32019-08-27 10:38:50 -0600859 """
David Burger1e0fe232019-07-01 14:52:07 -0600860 assert atom
Alex Kleinbbef2b32019-08-27 10:38:50 -0600861
Alex Klein5caab872021-09-10 11:44:37 -0600862 return portage_util.PortageqBestVisible(
863 atom,
864 board=build_target.name if build_target else None,
865 sysroot=build_target.root if build_target else None)
Alex Kleinda39c6d2019-09-16 14:36:36 -0600866
867
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700868def has_prebuilt(
869 atom: str,
870 build_target: 'build_target_lib.BuildTarget' = None,
871 useflags: Union[Iterable[str], str] = None) -> bool:
Alex Kleinda39c6d2019-09-16 14:36:36 -0600872 """Check if a prebuilt exists.
873
874 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700875 atom: The package whose prebuilt is being queried.
876 build_target: The build target whose sysroot should be searched, or the
877 SDK if not provided.
Alex Klein149fd3b2019-12-16 16:01:05 -0700878 useflags: Any additional USE flags that should be set. May be a string
879 of properly formatted USE flags, or an iterable of individual flags.
Alex Kleinad6b48a2020-01-08 16:57:41 -0700880
881 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700882 True if there is an available prebuilt, False otherwise.
Alex Kleinda39c6d2019-09-16 14:36:36 -0600883 """
884 assert atom
885
886 board = build_target.name if build_target else None
Alex Klein149fd3b2019-12-16 16:01:05 -0700887 extra_env = None
888 if useflags:
889 new_flags = useflags
Mike Frysingercfecd6b2020-12-14 23:54:05 -0500890 if not isinstance(useflags, str):
Alex Klein149fd3b2019-12-16 16:01:05 -0700891 new_flags = ' '.join(useflags)
892
893 existing = os.environ.get('USE', '')
894 final_flags = '%s %s' % (existing, new_flags)
895 extra_env = {'USE': final_flags.strip()}
896 return portage_util.HasPrebuilt(atom, board=board, extra_env=extra_env)
Alex Klein36b117f2019-09-30 15:13:46 -0600897
898
David Burger0f9dd4e2019-10-08 12:33:42 -0600899def builds(atom, build_target, packages=None):
Alex Klein36b117f2019-09-30 15:13:46 -0600900 """Check if |build_target| builds |atom| (has it in its depgraph)."""
901 cros_build_lib.AssertInsideChroot()
902
Alex Kleind8cd4c62020-09-14 13:37:47 -0600903 pkgs = tuple(packages) if packages else None
LaMont Jones4cbecba2020-05-12 11:54:27 -0600904 # TODO(crbug/1081828): Receive and use sysroot.
905 graph, _sdk_graph = dependency.GetBuildDependency(
Alex Kleind8cd4c62020-09-14 13:37:47 -0600906 build_target.root, build_target.name, pkgs)
Alex Klein36b117f2019-09-30 15:13:46 -0600907 return any(atom in package for package in graph['package_deps'])
Michael Mortensenb70e8a82019-10-10 18:43:41 -0600908
909
Alex Klein6becabc2020-09-11 14:03:05 -0600910def needs_chrome_source(
911 build_target: 'build_target_lib.BuildTarget',
912 compile_source=False,
913 packages: Optional[List[package_info.PackageInfo]] = None,
914 useflags=None):
915 """Check if the chrome source is needed.
916
917 The chrome source is needed if the build target builds chrome or any of its
918 follower packages, and can't use a prebuilt for them either because it's not
919 available, or because we can't use prebuilts because it must build from
920 source.
921 """
922 cros_build_lib.AssertInsideChroot()
923
924 # Check if it builds chrome and/or a follower package.
Alex Kleina8052162021-02-03 14:28:22 -0700925 graph = depgraph.get_sysroot_dependency_graph(build_target.root, packages)
Alex Klein6becabc2020-09-11 14:03:05 -0600926 builds_chrome = constants.CHROME_CP in graph
927 builds_follower = {
928 pkg: pkg in graph for pkg in constants.OTHER_CHROME_PACKAGES
929 }
930
Alex Klein9ce3f682021-06-23 15:06:44 -0600931 local_uprev = builds_chrome and revbump_chrome([build_target])
932
Alex Klein6becabc2020-09-11 14:03:05 -0600933 # When we are compiling source set False since we do not use prebuilts.
934 # When not compiling from source, start with True, i.e. we have every prebuilt
935 # we've checked for up to this point.
936 has_chrome_prebuilt = not compile_source
937 has_follower_prebuilts = not compile_source
938 # Save packages that need prebuilts for reporting.
939 pkgs_needing_prebuilts = []
940 if compile_source:
941 # Need everything.
942 pkgs_needing_prebuilts.append(constants.CHROME_CP)
943 pkgs_needing_prebuilts.extend(
944 [pkg for pkg, builds_pkg in builds_follower.items() if builds_pkg])
945 else:
946 # Check chrome itself.
947 if builds_chrome:
948 has_chrome_prebuilt = has_prebuilt(
949 constants.CHROME_CP, build_target=build_target, useflags=useflags)
950 if not has_chrome_prebuilt:
951 pkgs_needing_prebuilts.append(constants.CHROME_CP)
952 # Check follower packages.
953 for pkg, builds_pkg in builds_follower.items():
954 if not builds_pkg:
955 continue
956 prebuilt = has_prebuilt(pkg, build_target=build_target, useflags=useflags)
957 has_follower_prebuilts &= prebuilt
958 if not prebuilt:
959 pkgs_needing_prebuilts.append(pkg)
960 # Postcondition: has_chrome_prebuilt and has_follower_prebuilts now correctly
961 # reflect whether we actually have the corresponding prebuilts for the build.
962
963 needs_chrome = builds_chrome and not has_chrome_prebuilt
964 needs_follower = any(builds_follower.values()) and not has_follower_prebuilts
965
966 return NeedsChromeSourceResult(
Sergey Frolov26ff97b2021-08-14 00:02:11 +0000967 needs_chrome_source=needs_chrome or needs_follower,
Alex Klein6becabc2020-09-11 14:03:05 -0600968 builds_chrome=builds_chrome,
969 packages=[package_info.parse(p) for p in pkgs_needing_prebuilts],
970 missing_chrome_prebuilt=not has_chrome_prebuilt,
Alex Klein9ce3f682021-06-23 15:06:44 -0600971 missing_follower_prebuilt=not has_follower_prebuilts,
972 local_uprev=local_uprev,
973 )
Alex Klein6becabc2020-09-11 14:03:05 -0600974
975
Alex Klein68a28712021-11-08 11:08:30 -0700976class TargetVersions(NamedTuple):
977 """Data class for the info that makes up the "target versions"."""
978 android_version: str
979 android_branch: str
980 android_target: str
981 chrome_version: str
982 platform_version: str
983 milestone_version: str
984 full_version: str
985
986
987def get_target_versions(
988 build_target: 'build_target_lib.BuildTarget',
989 packages: List[package_info.PackageInfo] = None
990) -> TargetVersions:
991 """Aggregate version info for a few key packages and the OS as a whole."""
992 # Android version.
993 android_version = determine_android_version(build_target.name)
994 logging.info('Found android version: %s', android_version)
995 # Android branch version.
996 android_branch = determine_android_branch(build_target.name)
997 logging.info('Found android branch version: %s', android_branch)
998 # Android target version.
999 android_target = determine_android_target(build_target.name)
1000 logging.info('Found android target version: %s', android_target)
1001
1002 # TODO(crbug/1019770): Investigate cases where builds_chrome is true but
1003 # chrome_version is None.
1004
1005 builds_chrome = builds(constants.CHROME_CP, build_target, packages=packages)
1006 chrome_version = None
1007 if builds_chrome:
1008 # Chrome version fetch.
1009 chrome_version = determine_chrome_version(build_target)
1010 logging.info('Found chrome version: %s', chrome_version)
1011
1012 # The ChromeOS version info.
1013 platform_version = determine_platform_version()
1014 milestone_version = determine_milestone_version()
1015 full_version = determine_full_version()
1016
1017 return TargetVersions(android_version, android_branch, android_target,
1018 chrome_version, platform_version, milestone_version,
1019 full_version)
1020
1021
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001022def determine_chrome_version(
1023 build_target: 'build_target_lib.BuildTarget') -> Optional[str]:
Michael Mortensenc2615b72019-10-15 08:12:24 -06001024 """Returns the current Chrome version for the board (or in buildroot).
1025
1026 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001027 build_target: The board build target.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001028
1029 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001030 The chrome version if available.
Michael Mortensenc2615b72019-10-15 08:12:24 -06001031 """
Michael Mortensen9fe740c2019-10-29 14:42:48 -06001032 # TODO(crbug/1019770): Long term we should not need the try/catch here once
1033 # the builds function above only returns True for chrome when
1034 # determine_chrome_version will succeed.
1035 try:
Alex Klein5caab872021-09-10 11:44:37 -06001036 pkg_info = portage_util.PortageqBestVisible(
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001037 constants.CHROME_CP, build_target.name, cwd=constants.SOURCE_ROOT)
Michael Mortensen9fe740c2019-10-29 14:42:48 -06001038 except cros_build_lib.RunCommandError as e:
1039 # Return None because portage failed when trying to determine the chrome
1040 # version.
1041 logging.warning('Caught exception in determine_chrome_package: %s', e)
1042 return None
Michael Mortensenc2615b72019-10-15 08:12:24 -06001043 # Something like 78.0.3877.4_rc -> 78.0.3877.4
Alex Klein5caab872021-09-10 11:44:37 -06001044 return pkg_info.version.partition('_')[0]
Michael Mortensenc2615b72019-10-15 08:12:24 -06001045
1046
Alex Klein68a28712021-11-08 11:08:30 -07001047@functools.lru_cache()
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001048def determine_android_package(board: str) -> Optional[str]:
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001049 """Returns the active Android container package in use by the board.
1050
1051 Args:
1052 board: The board name this is specific to.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001053
1054 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001055 The android package string if there is one.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001056 """
Michael Mortensene0f4b542019-10-24 15:30:23 -06001057 try:
1058 packages = portage_util.GetPackageDependencies(board, 'virtual/target-os')
Michael Mortensene0f4b542019-10-24 15:30:23 -06001059 except cros_build_lib.RunCommandError as e:
1060 # Return None because a command (likely portage) failed when trying to
1061 # determine the package.
1062 logging.warning('Caught exception in determine_android_package: %s', e)
1063 return None
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001064
Alex Kleinad6b48a2020-01-08 16:57:41 -07001065 # We assume there is only one Android package in the depgraph.
1066 for package in packages:
Mike Frysingerfcca49e2021-03-17 01:09:20 -04001067 if (package.startswith('chromeos-base/android-container-') or
1068 package.startswith('chromeos-base/android-vm-')):
Alex Kleinad6b48a2020-01-08 16:57:41 -07001069 return package
1070 return None
1071
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001072
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001073def determine_android_version(board: str, package: str = None):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001074 """Determine the current Android version in buildroot now and return it.
1075
1076 This uses the typical portage logic to determine which version of Android
1077 is active right now in the buildroot.
1078
1079 Args:
Mike Frysingerb53f1822021-03-05 00:44:50 -05001080 board: The board name this is specific to.
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001081 package: The Android package, if already computed.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001082
1083 Returns:
Mike Frysingerb53f1822021-03-05 00:44:50 -05001084 The Android build ID of the container for the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001085
1086 Raises:
1087 NoAndroidVersionError: if no unique Android version can be determined.
1088 """
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001089 if not package:
1090 package = determine_android_package(board)
Mike Frysingerb53f1822021-03-05 00:44:50 -05001091 if not package:
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001092 return None
Mike Frysingerb53f1822021-03-05 00:44:50 -05001093 cpv = package_info.SplitCPV(package)
1094 if not cpv:
1095 raise NoAndroidVersionError(
1096 'Android version could not be determined for %s' % board)
1097 return cpv.version_no_rev
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001098
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001099
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001100def determine_android_branch(board, package=None):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001101 """Returns the Android branch in use by the active container ebuild."""
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001102 if not package:
1103 package = determine_android_package(board)
1104 if not package:
Michael Mortensenedf76532019-10-16 14:22:37 -06001105 return None
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001106 ebuild_path = portage_util.FindEbuildForBoardPackage(package, board)
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001107 # We assume all targets pull from the same branch and that we always
Federico 'Morg' Pareschicd9165a2020-05-29 09:45:55 +09001108 # have at least one of the following targets.
Shao-Chuan Lee73bba612020-06-17 11:47:04 +09001109 targets = constants.ANDROID_ALL_BUILD_TARGETS
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001110 ebuild_content = osutils.SourceEnvironment(ebuild_path, targets)
1111 for target in targets:
1112 if target in ebuild_content:
1113 branch = re.search(r'(.*?)-linux-', ebuild_content[target])
1114 if branch is not None:
1115 return branch.group(1)
1116 raise NoAndroidBranchError(
1117 'Android branch could not be determined for %s (ebuild empty?)' % board)
1118
1119
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001120def determine_android_target(board, package=None):
Michael Mortensen14960d02019-10-18 07:53:59 -06001121 """Returns the Android target in use by the active container ebuild."""
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001122 if not package:
1123 package = determine_android_package(board)
1124 if not package:
Michael Mortensenedf76532019-10-16 14:22:37 -06001125 return None
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001126 if package.startswith('chromeos-base/android-vm-'):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001127 return 'bertha'
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001128 elif package.startswith('chromeos-base/android-container-'):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001129 return 'cheets'
1130
1131 raise NoAndroidTargetError(
1132 'Android Target cannot be determined for the package: %s' %
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001133 package)
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001134
1135
1136def determine_platform_version():
1137 """Returns the platform version from the source root."""
Michael Mortensen009cb662019-10-21 11:38:43 -06001138 # Platform version is something like '12575.0.0'.
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001139 version = manifest_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1140 return version.VersionString()
Michael Mortensen009cb662019-10-21 11:38:43 -06001141
1142
1143def determine_milestone_version():
1144 """Returns the platform version from the source root."""
1145 # Milestone version is something like '79'.
1146 version = manifest_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1147 return version.chrome_branch
1148
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001149
Michael Mortensen009cb662019-10-21 11:38:43 -06001150def determine_full_version():
1151 """Returns the full version from the source root."""
1152 # Full version is something like 'R79-12575.0.0'.
1153 milestone_version = determine_milestone_version()
1154 platform_version = determine_platform_version()
1155 full_version = ('R%s-%s' % (milestone_version, platform_version))
1156 return full_version
Michael Mortensen71ef5682020-05-07 14:29:24 -06001157
1158
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001159def find_fingerprints(
1160 build_target: 'build_target_lib.BuildTarget') -> List[str]:
Michael Mortensende716a12020-05-15 11:27:00 -06001161 """Returns a list of fingerprints for this build.
1162
1163 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001164 build_target: The build target.
Michael Mortensende716a12020-05-15 11:27:00 -06001165
1166 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001167 List of fingerprint strings.
Michael Mortensende716a12020-05-15 11:27:00 -06001168 """
1169 cros_build_lib.AssertInsideChroot()
1170 fp_file = 'cheets-fingerprint.txt'
1171 fp_path = os.path.join(
1172 image_lib.GetLatestImageLink(build_target.name),
1173 fp_file)
1174 if not os.path.isfile(fp_path):
1175 logging.info('Fingerprint file not found: %s', fp_path)
Michael Mortensend81d81e2020-06-09 14:20:59 -06001176 return []
Michael Mortensende716a12020-05-15 11:27:00 -06001177 logging.info('Reading fingerprint file: %s', fp_path)
1178 fingerprints = osutils.ReadFile(fp_path).splitlines()
1179 return fingerprints
1180
1181
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001182def get_all_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen59e30872020-05-18 14:12:49 -06001183 """Extract firmware version for all models present.
1184
1185 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001186 build_target: The build target.
Michael Mortensen59e30872020-05-18 14:12:49 -06001187
1188 Returns:
1189 A dict of FirmwareVersions namedtuple instances by model.
1190 Each element will be populated based on whether it was present in the
1191 command output.
1192 """
1193 cros_build_lib.AssertInsideChroot()
1194 result = {}
1195 # Note that example output for _get_firmware_version_cmd_result is available
1196 # in the packages_unittest.py for testing get_all_firmware_versions.
1197 cmd_result = _get_firmware_version_cmd_result(build_target)
1198
1199 # There is a blank line between the version info for each model.
1200 firmware_version_payloads = cmd_result.split('\n\n')
1201 for firmware_version_payload in firmware_version_payloads:
1202 if 'BIOS' in firmware_version_payload:
1203 firmware_version = _find_firmware_versions(firmware_version_payload)
1204 result[firmware_version.model] = firmware_version
1205 return result
1206
1207
Michael Mortensen71ef5682020-05-07 14:29:24 -06001208FirmwareVersions = collections.namedtuple(
1209 'FirmwareVersions', ['model', 'main', 'main_rw', 'ec', 'ec_rw'])
1210
1211
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001212def get_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen71ef5682020-05-07 14:29:24 -06001213 """Extract version information from the firmware updater, if one exists.
1214
1215 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001216 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001217
1218 Returns:
1219 A FirmwareVersions namedtuple instance.
1220 Each element will either be set to the string output by the firmware
1221 updater shellball, or None if there is no firmware updater.
1222 """
1223 cros_build_lib.AssertInsideChroot()
1224 cmd_result = _get_firmware_version_cmd_result(build_target)
1225 if cmd_result:
1226 return _find_firmware_versions(cmd_result)
1227 else:
1228 return FirmwareVersions(None, None, None, None, None)
1229
1230
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001231def _get_firmware_version_cmd_result(
1232 build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen71ef5682020-05-07 14:29:24 -06001233 """Gets the raw result output of the firmware updater version command.
1234
1235 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001236 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001237
1238 Returns:
1239 Command execution result.
1240 """
1241 updater = os.path.join(build_target.root,
1242 'usr/sbin/chromeos-firmwareupdate')
1243 logging.info('Calling updater %s', updater)
1244 # Call the updater using the chroot-based path.
1245 return cros_build_lib.run([updater, '-V'],
1246 capture_output=True, log_output=True,
1247 encoding='utf-8').stdout
1248
1249
1250def _find_firmware_versions(cmd_output):
1251 """Finds firmware version output via regex matches against the cmd_output.
1252
1253 Args:
1254 cmd_output: The raw output to search against.
1255
1256 Returns:
1257 FirmwareVersions namedtuple with results.
1258 Each element will either be set to the string output by the firmware
1259 updater shellball, or None if there is no match.
1260 """
1261
1262 # Sometimes a firmware bundle includes a special combination of RO+RW
1263 # firmware. In this case, the RW firmware version is indicated with a "(RW)
1264 # version" field. In other cases, the "(RW) version" field is not present.
1265 # Therefore, search for the "(RW)" fields first and if they aren't present,
1266 # fallback to the other format. e.g. just "BIOS version:".
1267 # TODO(mmortensen): Use JSON once the firmware updater supports it.
1268 main = None
1269 main_rw = None
1270 ec = None
1271 ec_rw = None
1272 model = None
1273
1274 match = re.search(r'BIOS version:\s*(?P<version>.*)', cmd_output)
1275 if match:
1276 main = match.group('version')
1277
1278 match = re.search(r'BIOS \(RW\) version:\s*(?P<version>.*)', cmd_output)
1279 if match:
1280 main_rw = match.group('version')
1281
1282 match = re.search(r'EC version:\s*(?P<version>.*)', cmd_output)
1283 if match:
1284 ec = match.group('version')
1285
1286 match = re.search(r'EC \(RW\) version:\s*(?P<version>.*)', cmd_output)
1287 if match:
1288 ec_rw = match.group('version')
1289
1290 match = re.search(r'Model:\s*(?P<model>.*)', cmd_output)
1291 if match:
1292 model = match.group('model')
1293
1294 return FirmwareVersions(model, main, main_rw, ec, ec_rw)
Michael Mortensena4af79e2020-05-06 16:18:48 -06001295
1296
1297MainEcFirmwareVersions = collections.namedtuple(
1298 'MainEcFirmwareVersions', ['main_fw_version', 'ec_fw_version'])
1299
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001300def determine_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensena4af79e2020-05-06 16:18:48 -06001301 """Returns a namedtuple with main and ec firmware versions.
1302
1303 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001304 build_target: The build target.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001305
1306 Returns:
1307 MainEcFirmwareVersions namedtuple with results.
1308 """
1309 fw_versions = get_firmware_versions(build_target)
1310 main_fw_version = fw_versions.main_rw or fw_versions.main
1311 ec_fw_version = fw_versions.ec_rw or fw_versions.ec
1312
1313 return MainEcFirmwareVersions(main_fw_version, ec_fw_version)
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001314
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001315def determine_kernel_version(
1316 build_target: 'build_target_lib.BuildTarget') -> Optional[str]:
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001317 """Returns a string containing the kernel version for this build target.
1318
1319 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001320 build_target: The build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001321
1322 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001323 The kernel versions, or None.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001324 """
1325 try:
1326 packages = portage_util.GetPackageDependencies(build_target.name,
1327 'virtual/linux-sources')
1328 except cros_build_lib.RunCommandError as e:
1329 logging.warning('Unable to get package list for metadata: %s', e)
1330 return None
1331 for package in packages:
1332 if package.startswith('sys-kernel/chromeos-kernel-'):
Alex Klein18a60af2020-06-11 12:08:47 -06001333 kernel_version = package_info.SplitCPV(package).version
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001334 logging.info('Found active kernel version: %s', kernel_version)
1335 return kernel_version
1336 return None
Michael Mortensen125bb012020-05-21 14:02:10 -06001337
1338
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001339def get_models(
1340 build_target: 'build_target_lib.BuildTarget',
1341 log_output: bool = True) -> Optional[List[str]]:
Michael Mortensen125bb012020-05-21 14:02:10 -06001342 """Obtain a list of models supported by a unified board.
1343
1344 This ignored whitelabel models since GoldenEye has no specific support for
1345 these at present.
1346
1347 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001348 build_target: The build target.
Michael Mortensen125bb012020-05-21 14:02:10 -06001349 log_output: Whether to log the output of the cros_config_host invocation.
1350
1351 Returns:
1352 A list of models supported by this board, if it is a unified build; None,
1353 if it is not a unified build.
1354 """
1355 return _run_cros_config_host(build_target, ['list-models'],
1356 log_output=log_output)
1357
1358
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001359def get_key_id(
1360 build_target: 'build_target_lib.BuildTarget',
1361 model: str) -> Optional[str]:
Michael Mortensen359c1f32020-05-28 19:35:42 -06001362 """Obtain the key_id for a model within the build_target.
1363
1364 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001365 build_target: The build target.
1366 model: The model name
Michael Mortensen359c1f32020-05-28 19:35:42 -06001367
1368 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001369 A key_id or None.
Michael Mortensen359c1f32020-05-28 19:35:42 -06001370 """
1371 model_arg = '--model=' + model
1372 key_id_list = _run_cros_config_host(
1373 build_target,
1374 [model_arg, 'get', '/firmware-signing', 'key-id'])
1375 key_id = None
1376 if len(key_id_list) == 1:
1377 key_id = key_id_list[0]
1378 return key_id
1379
1380
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001381def _run_cros_config_host(
1382 build_target: 'build_target_lib.BuildTarget',
1383 args: List[str],
1384 log_output: bool = True) -> Optional[List[str]]:
Michael Mortensen125bb012020-05-21 14:02:10 -06001385 """Run the cros_config_host tool.
1386
1387 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001388 build_target: The build target.
Michael Mortensen125bb012020-05-21 14:02:10 -06001389 args: List of arguments to pass.
1390 log_output: Whether to log the output of the cros_config_host.
1391
1392 Returns:
1393 Output of the tool
1394 """
1395 cros_build_lib.AssertInsideChroot()
1396 tool = '/usr/bin/cros_config_host'
1397 if not os.path.isfile(tool):
1398 return None
1399
1400 config_fname = build_target.full_path(
1401 'usr/share/chromeos-config/yaml/config.yaml')
1402
1403 result = cros_build_lib.run(
1404 [tool, '-c', config_fname] + args,
1405 capture_output=True,
1406 encoding='utf-8',
1407 log_output=log_output,
1408 check=False)
1409 if result.returncode:
1410 # Show the output for debugging purposes.
1411 if 'No such file or directory' not in result.error:
1412 logging.error('cros_config_host failed: %s\n', result.error)
1413 return None
1414 return result.output.strip().splitlines()