blob: 6d946b317fa85bfb6621eb88d148b1c1d929432f [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 Lee84bf9a22021-11-19 17:42:11 +0900143class UprevAndroidResult(NamedTuple):
144 """Results of an Android uprev."""
145 revved: bool
146 android_atom: str = None
147
148
149def uprev_android(
150 android_package: str,
151 chroot: 'chroot_lib.Chroot',
152 build_targets: Optional[List['build_target_lib.BuildTarget']] = None,
153 android_build_branch: Optional[str] = None,
154 android_version: Optional[str] = None,
155 skip_commit: bool = False) -> UprevAndroidResult:
156 """Performs an Android uprev by calling cros_mark_android_as_stable.
157
158 Args:
159 android_package: The Android package to uprev.
160 chroot: The chroot to enter.
161 build_targets: List of build targets to cleanup after uprev.
162 android_build_branch: Override the default Android branch corresponding to
163 the package.
164 android_version: Uprev to the particular version. By default the latest
165 available version is used.
166 skip_commit: Whether to skip committing the change after a successful uprev.
167
168 Returns:
169 The uprev result containing:
170 revved: Whether an uprev happened.
171 android_atom: If revved, the portage atom for the revved Android ebuild.
172 """
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700173 command = [
174 'cros_mark_android_as_stable',
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900175 f'--android_package={android_package}',
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700176 ]
Alex Klein4de25e82019-08-05 15:58:39 -0600177 if build_targets:
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900178 command.append(f'--boards={":".join(bt.name for bt in build_targets)}')
Shao-Chuan Leea4b4f302021-05-12 14:40:20 +0900179 if android_build_branch:
180 command.append(f'--android_build_branch={android_build_branch}')
Alex Klein4de25e82019-08-05 15:58:39 -0600181 if android_version:
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900182 command.append(f'--force_version={android_version}')
183 if skip_commit:
184 command.append('--skip_commit')
Alex Klein4de25e82019-08-05 15:58:39 -0600185
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700186 result = cros_build_lib.run(
187 command,
188 stdout=True,
189 enter_chroot=True,
Mike Frysinger88d96362020-02-14 19:05:45 -0500190 encoding='utf-8',
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700191 chroot_args=chroot.get_enter_args())
Alex Klein4de25e82019-08-05 15:58:39 -0600192
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900193 output = result.stdout.strip()
194 if not output:
Alex Klein4de25e82019-08-05 15:58:39 -0600195 logging.info('Found nothing to rev.')
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900196 return UprevAndroidResult(revved=False)
197
198 output = json.loads(output)
199 android_atom = output['android_atom']
Alex Klein4de25e82019-08-05 15:58:39 -0600200
201 for target in build_targets or []:
202 # Sanity check: We should always be able to merge the version of
203 # Android we just unmasked.
Shao-Chuan Lee85ba7ce2021-02-09 13:50:11 +0900204 command = [f'emerge-{target.name}', '-p', '--quiet', f'={android_atom}']
Alex Klein4de25e82019-08-05 15:58:39 -0600205 try:
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700206 cros_build_lib.run(
207 command, enter_chroot=True, chroot_args=chroot.get_enter_args())
Alex Klein4de25e82019-08-05 15:58:39 -0600208 except cros_build_lib.RunCommandError:
209 logging.error(
210 'Cannot emerge-%s =%s\nIs Android pinned to an older '
211 'version?', target, android_atom)
212 raise AndroidIsPinnedUprevError(android_atom)
213
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900214 return UprevAndroidResult(revved=True,
215 android_atom=android_atom)
Alex Klein4de25e82019-08-05 15:58:39 -0600216
217
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700218def uprev_build_targets(
219 build_targets: Optional[List['build_target_lib.BuildTarget']],
220 overlay_type: str,
221 chroot: 'chroot_lib.Chroot' = None,
222 output_dir: Optional[str] = None):
Alex Kleineb77ffa2019-05-28 14:47:44 -0600223 """Uprev the set provided build targets, or all if not specified.
224
225 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700226 build_targets: The build targets
Alex Kleineb77ffa2019-05-28 14:47:44 -0600227 whose overlays should be uprevved, empty or None for all.
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700228 overlay_type: One of the valid overlay types except None (see
Alex Kleineb77ffa2019-05-28 14:47:44 -0600229 constants.VALID_OVERLAYS).
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700230 chroot: The chroot to clean, if desired.
231 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600232 """
233 # Need a valid overlay, but exclude None.
234 assert overlay_type and overlay_type in constants.VALID_OVERLAYS
235
236 if build_targets:
237 overlays = portage_util.FindOverlaysForBoards(
238 overlay_type, boards=[t.name for t in build_targets])
239 else:
240 overlays = portage_util.FindOverlays(overlay_type)
241
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700242 return uprev_overlays(
243 overlays,
244 build_targets=build_targets,
245 chroot=chroot,
246 output_dir=output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600247
248
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700249def uprev_overlays(
250 overlays: List[str],
251 build_targets: Optional[List['build_target_lib.BuildTarget']] = None,
252 chroot: Optional['chroot_lib.Chroot'] = None,
253 output_dir: Optional[str] = None) -> List[str]:
Alex Kleineb77ffa2019-05-28 14:47:44 -0600254 """Uprev the given overlays.
255
256 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700257 overlays: The list of overlay paths.
258 build_targets: The build targets
Alex Kleineb77ffa2019-05-28 14:47:44 -0600259 to clean in |chroot|, if desired. No effect unless |chroot| is provided.
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700260 chroot: The chroot to clean, if desired.
261 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600262
263 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700264 The paths to all of the modified ebuild files. This includes the new files
265 that were added (i.e. the new versions) and all of the removed files
266 (i.e. the old versions).
Alex Kleineb77ffa2019-05-28 14:47:44 -0600267 """
268 assert overlays
269
270 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
271
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700272 uprev_manager = uprev_lib.UprevOverlayManager(
273 overlays,
274 manifest,
275 build_targets=build_targets,
276 chroot=chroot,
277 output_dir=output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600278 uprev_manager.uprev()
279
Dhanya Ganeshd03a4162021-08-25 00:21:50 +0000280 return uprev_manager.modified_ebuilds, uprev_manager.revved_packages
Alex Kleineb77ffa2019-05-28 14:47:44 -0600281
282
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700283def uprev_versioned_package(
284 package: package_info.CPV,
285 build_targets: List['build_target_lib.BuildTarget'],
286 refs: List[uprev_lib.GitRef],
287 chroot: 'chroot_lib.Chroot') -> 'uprev_lib.UprevVersionedPackageResult':
Alex Klein87531182019-08-12 15:23:37 -0600288 """Call registered uprev handler function for the package.
289
290 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700291 package: The package being uprevved.
292 build_targets: The build targets to clean on a successful uprev.
293 refs:
294 chroot: The chroot to enter for cleaning.
Alex Klein87531182019-08-12 15:23:37 -0600295
296 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700297 The result.
Alex Klein87531182019-08-12 15:23:37 -0600298 """
299 assert package
300
301 if package.cp not in _UPREV_FUNCS:
302 raise UnknownPackageError(
303 'Package "%s" does not have a registered handler.' % package.cp)
304
Andrew Lambea9a8a22019-12-12 14:03:43 -0700305 return _UPREV_FUNCS[package.cp](build_targets, refs, chroot)
Alex Klein87531182019-08-12 15:23:37 -0600306
307
Navil Perezf57ba872020-06-04 22:38:37 +0000308@uprevs_versioned_package('media-libs/virglrenderer')
309def uprev_virglrenderer(_build_targets, refs, _chroot):
310 """Updates virglrenderer ebuilds.
311
312 See: uprev_versioned_package.
313
314 Returns:
315 UprevVersionedPackageResult: The result of updating virglrenderer ebuilds.
316 """
Navil Perezf57ba872020-06-04 22:38:37 +0000317 overlay = os.path.join(constants.SOURCE_ROOT,
318 constants.CHROMIUMOS_OVERLAY_DIR)
George Engelbrechte73f2782020-06-10 14:10:46 -0600319 repo_path = os.path.join(constants.SOURCE_ROOT, 'src', 'third_party',
320 'virglrenderer')
321 manifest = git.ManifestCheckout.Cached(repo_path)
Navil Perezf57ba872020-06-04 22:38:37 +0000322
323 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
324 # TODO(crbug.com/1066242): Ebuilds for virglrenderer are currently
Jose Magana03b5a842020-08-19 12:52:59 +1000325 # denylisted. Do not force uprevs after builder is stable and ebuilds are no
326 # longer denylisted.
Navil Perezf57ba872020-06-04 22:38:37 +0000327 uprev_manager.uprev(package_list=['media-libs/virglrenderer'], force=True)
328
George Engelbrechte73f2782020-06-10 14:10:46 -0600329 updated_files = uprev_manager.modified_ebuilds
Chris McDonald38409112020-09-24 11:24:51 -0600330 result = uprev_lib.UprevVersionedPackageResult()
Navil Perezf57ba872020-06-04 22:38:37 +0000331 result.add_result(refs[0].revision, updated_files)
332 return result
333
Jose Magana03b5a842020-08-19 12:52:59 +1000334@uprevs_versioned_package('chromeos-base/drivefs')
335def uprev_drivefs(_build_targets, refs, chroot):
336 """Updates drivefs ebuilds.
337
Harvey Yang3eee06c2021-03-18 15:47:56 +0800338 DriveFS versions follow the tag format of refs/tags/drivefs_1.2.3.
Jose Magana03b5a842020-08-19 12:52:59 +1000339 See: uprev_versioned_package.
340
341 Returns:
342 UprevVersionedPackageResult: The result of updating drivefs ebuilds.
343 """
344
Ben Reiche779cf42020-12-15 03:21:31 +0000345 DRIVEFS_PATH_PREFIX = 'src/private-overlays/chromeos-overlay/chromeos-base'
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000346 result = uprev_lib.UprevVersionedPackageResult()
347 all_changed_files = []
Jose Magana03b5a842020-08-19 12:52:59 +1000348
Harvey Yang3eee06c2021-03-18 15:47:56 +0800349 DRIVEFS_REFS_PREFIX = 'refs/tags/drivefs_'
350 drivefs_version = _get_latest_version_from_refs(DRIVEFS_REFS_PREFIX, refs)
Ben Reiche779cf42020-12-15 03:21:31 +0000351 if not drivefs_version:
352 # No valid DriveFS version is identified.
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000353 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000354
Ben Reiche779cf42020-12-15 03:21:31 +0000355 logging.debug('DriveFS version determined from refs: %s', drivefs_version)
Jose Magana03b5a842020-08-19 12:52:59 +1000356
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000357 # Attempt to uprev drivefs package.
Ben Reiche779cf42020-12-15 03:21:31 +0000358 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, 'drivefs')
Jose Magana03b5a842020-08-19 12:52:59 +1000359 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(pkg_path,
Ben Reiche779cf42020-12-15 03:21:31 +0000360 drivefs_version,
Harvey Yang3eee06c2021-03-18 15:47:56 +0800361 chroot,
362 allow_downrev=False)
Jose Magana03b5a842020-08-19 12:52:59 +1000363
364 if not uprev_result:
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000365 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000366 all_changed_files.extend(uprev_result.changed_files)
367
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000368 # Attempt to uprev drivefs-ipc package.
Ben Reiche779cf42020-12-15 03:21:31 +0000369 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, 'drivefs-ipc')
Jose Magana03b5a842020-08-19 12:52:59 +1000370 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(pkg_path,
Ben Reiche779cf42020-12-15 03:21:31 +0000371 drivefs_version,
Harvey Yang3eee06c2021-03-18 15:47:56 +0800372 chroot,
373 allow_downrev=False)
Jose Magana03b5a842020-08-19 12:52:59 +1000374
375 if not uprev_result:
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000376 logging.warning(
377 'drivefs package has changed files %s but drivefs-ipc does not',
378 all_changed_files)
379 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000380
381 all_changed_files.extend(uprev_result.changed_files)
Ben Reiche779cf42020-12-15 03:21:31 +0000382 result.add_result(drivefs_version, all_changed_files)
Jose Magana03b5a842020-08-19 12:52:59 +1000383
384 return result
385
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800386@uprevs_versioned_package('chromeos-base/perfetto')
387def uprev_perfetto(_build_targets, refs, chroot):
388 """Updates Perfetto ebuilds.
389
Harvey Yang3eee06c2021-03-18 15:47:56 +0800390 Perfetto versions follow the tag format of refs/tags/v1.2.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800391 See: uprev_versioned_package.
392
393 Returns:
394 UprevVersionedPackageResult: The result of updating Perfetto ebuilds.
395 """
396 result = uprev_lib.UprevVersionedPackageResult()
397
Harvey Yang3eee06c2021-03-18 15:47:56 +0800398 PERFETTO_REFS_PREFIX = 'refs/tags/v'
399 perfetto_version = _get_latest_version_from_refs(PERFETTO_REFS_PREFIX, refs)
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800400 if not perfetto_version:
401 # No valid Perfetto version is identified.
402 return result
403
404 logging.debug('Perfetto version determined from refs: %s', perfetto_version)
405
406 # Attempt to uprev perfetto package.
407 PERFETTO_PATH = 'src/third_party/chromiumos-overlay/chromeos-base/perfetto'
408
Harvey Yang3eee06c2021-03-18 15:47:56 +0800409 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
410 PERFETTO_PATH,
411 perfetto_version,
412 chroot,
413 allow_downrev=False,
414 ref=PERFETTO_REFS_PREFIX + perfetto_version)
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800415
416 if not uprev_result:
417 return result
418
419 result.add_result(perfetto_version, uprev_result.changed_files)
420
421 return result
Navil Perezf57ba872020-06-04 22:38:37 +0000422
Yaakov Shaul395ae832019-09-09 14:45:32 -0600423@uprevs_versioned_package('afdo/kernel-profiles')
424def uprev_kernel_afdo(*_args, **_kwargs):
David Burger92485342019-09-10 17:52:45 -0600425 """Updates kernel ebuilds with versions from kernel_afdo.json.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600426
427 See: uprev_versioned_package.
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600428
429 Raises:
430 EbuildManifestError: When ebuild manifest does not complete successfuly.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600431 """
432 path = os.path.join(constants.SOURCE_ROOT, 'src', 'third_party',
433 'toolchain-utils', 'afdo_metadata', 'kernel_afdo.json')
434
David Burger92485342019-09-10 17:52:45 -0600435 with open(path, 'r') as f:
436 versions = json.load(f)
Yaakov Shaul395ae832019-09-09 14:45:32 -0600437
Chris McDonald38409112020-09-24 11:24:51 -0600438 result = uprev_lib.UprevVersionedPackageResult()
Alex Klein6edd4e62021-07-08 12:43:25 -0600439 for kernel_pkg, version_info in versions.items():
440 path = os.path.join(constants.CHROMIUMOS_OVERLAY_DIR,
441 'sys-kernel', kernel_pkg)
Yaakov Shauldd8b4112019-09-11 11:44:03 -0600442 ebuild_path = os.path.join(constants.SOURCE_ROOT, path,
Alex Klein6edd4e62021-07-08 12:43:25 -0600443 '%s-9999.ebuild' % kernel_pkg)
Yaakov Shaula187b152019-09-11 12:41:32 -0600444 chroot_ebuild_path = os.path.join(constants.CHROOT_SOURCE_ROOT, path,
Alex Klein6edd4e62021-07-08 12:43:25 -0600445 '%s-9999.ebuild' % kernel_pkg)
Yaakov Shaul730814a2019-09-10 13:58:25 -0600446 afdo_profile_version = version_info['name']
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600447 patch_ebuild_vars(ebuild_path,
448 dict(AFDO_PROFILE_VERSION=afdo_profile_version))
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600449
450 try:
Yaakov Shaul730814a2019-09-10 13:58:25 -0600451 cmd = ['ebuild', chroot_ebuild_path, 'manifest', '--force']
Mike Frysinger45602c72019-09-22 02:15:11 -0400452 cros_build_lib.run(cmd, enter_chroot=True)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600453 except cros_build_lib.RunCommandError as e:
Chris McDonald38409112020-09-24 11:24:51 -0600454 raise uprev_lib.EbuildManifestError(
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600455 'Error encountered when regenerating the manifest for ebuild: %s\n%s'
Yaakov Shaula187b152019-09-11 12:41:32 -0600456 % (chroot_ebuild_path, e), e)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600457
Yaakov Shauldd8b4112019-09-11 11:44:03 -0600458 manifest_path = os.path.join(constants.SOURCE_ROOT, path, 'Manifest')
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600459
Yaakov Shaul730814a2019-09-10 13:58:25 -0600460 result.add_result(afdo_profile_version, [ebuild_path, manifest_path])
461
462 return result
Yaakov Shaul395ae832019-09-09 14:45:32 -0600463
464
Trent Begineb624182020-07-14 10:09:45 -0600465@uprevs_versioned_package('chromeos-base/termina-dlc')
466def uprev_termina_dlc(_build_targets, _refs, chroot):
467 """Updates shared termina-dlc ebuild - chromeos-base/termina-dlc.
Trent Beginaf51f1b2020-03-09 17:35:31 -0600468
469 See: uprev_versioned_package.
470 """
Trent Begineb624182020-07-14 10:09:45 -0600471 package = 'termina-dlc'
Trent Beginaf51f1b2020-03-09 17:35:31 -0600472 package_path = os.path.join(constants.CHROMIUMOS_OVERLAY_DIR, 'chromeos-base',
473 package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000474
475 version_pin_src_path = _get_version_pin_src_path(package_path)
476 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
477
Chris McDonald38409112020-09-24 11:24:51 -0600478 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000479
480
Julio Hurtadof1befec2021-05-05 21:34:26 +0000481@uprevs_versioned_package('chromeos-base/chromeos-lacros')
482def uprev_lacros(_build_targets, refs, chroot):
483 """Updates lacros ebuilds.
484
Julio Hurtadoa994e002021-07-07 17:57:45 +0000485 Version to uprev to is gathered from the QA qualified version tracking file
486 stored in chromium/src/chrome/LACROS_QA_QUALIFIED_VERSION. Uprev is triggered
487 on modification of this file across all chromium/src branches.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000488
489 See: uprev_versioned_package.
490 """
Julio Hurtadoa994e002021-07-07 17:57:45 +0000491 result = uprev_lib.UprevVersionedPackageResult()
Julio Hurtadof1befec2021-05-05 21:34:26 +0000492 path = os.path.join(
Dennis Kempin257b74c2021-09-28 14:38:17 -0700493 constants.CHROMIUMOS_OVERLAY_DIR, 'chromeos-base', 'chromeos-lacros')
Julio Hurtadoa994e002021-07-07 17:57:45 +0000494 lacros_version = refs[0].revision
495 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(path,
496 lacros_version,
497 chroot,
498 allow_downrev=False)
499
500 if not uprev_result:
501 return result
502
503 result.add_result(lacros_version, uprev_result.changed_files)
504 return result
Julio Hurtadof1befec2021-05-05 21:34:26 +0000505
506
Patrick Meiring5897add2020-09-16 16:30:17 +1000507@uprevs_versioned_package('app-emulation/parallels-desktop')
508def uprev_parallels_desktop(_build_targets, _refs, chroot):
509 """Updates Parallels Desktop ebuild - app-emulation/parallels-desktop.
510
511 See: uprev_versioned_package
512
513 Returns:
514 UprevVersionedPackageResult: The result.
515 """
516 package = 'parallels-desktop'
517 package_path = os.path.join(constants.CHROMEOS_PARTNER_OVERLAY_DIR,
518 'app-emulation', package)
519 version_pin_src_path = _get_version_pin_src_path(package_path)
520
521 # Expect a JSON blob like the following:
522 # {
523 # "version": "1.2.3",
524 # "test_image": { "url": "...", "size": 12345678,
525 # "sha256sum": "<32 bytes of hexadecimal>" }
526 # }
527 with open(version_pin_src_path, 'r') as f:
528 pinned = json.load(f)
529
530 if 'version' not in pinned or 'test_image' not in pinned:
531 raise UprevError('VERSION-PIN for %s missing version and/or '
532 'test_image field' % package)
533
534 version = pinned['version']
535 if not isinstance(version, str):
536 raise UprevError('version in VERSION-PIN for %s not a string' % package)
537
538 # Update the ebuild.
Chris McDonald38409112020-09-24 11:24:51 -0600539 result = uprev_lib.uprev_ebuild_from_pin(package_path, version, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000540
541 # Update the VM image used for testing.
Patrick Meiring1342def2020-10-30 17:09:13 +1100542 test_image_path = ('src/platform/tast-tests-private/src/chromiumos/tast/'
543 'local/bundles/crosint/pita/data/'
544 'pluginvm_image.zip.external')
Patrick Meiring5897add2020-09-16 16:30:17 +1000545 test_image_src_path = os.path.join(constants.SOURCE_ROOT, test_image_path)
546 with open(test_image_src_path, 'w') as f:
547 json.dump(pinned['test_image'], f, indent=2)
548 result.add_result(version, [test_image_src_path])
549
550 return result
Trent Beginaf51f1b2020-03-09 17:35:31 -0600551
552
Trent Begin315d9d92019-12-03 21:55:53 -0700553@uprevs_versioned_package('chromeos-base/chromeos-dtc-vm')
Trent Beginaf51f1b2020-03-09 17:35:31 -0600554def uprev_sludge(_build_targets, _refs, chroot):
Trent Begin315d9d92019-12-03 21:55:53 -0700555 """Updates sludge VM - chromeos-base/chromeos-dtc-vm.
556
557 See: uprev_versioned_package.
558 """
559 package = 'chromeos-dtc-vm'
Trent Begind943df92020-02-25 10:30:10 -0700560 package_path = os.path.join('src', 'private-overlays',
561 'project-wilco-private', 'chromeos-base', package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000562 version_pin_src_path = _get_version_pin_src_path(package_path)
563 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Trent Begin315d9d92019-12-03 21:55:53 -0700564
Chris McDonald38409112020-09-24 11:24:51 -0600565 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Trent Begin315d9d92019-12-03 21:55:53 -0700566
567
David Riley8513c1f2021-10-14 17:07:41 -0700568@uprevs_versioned_package('chromeos-base/borealis-dlc')
569def uprev_borealis_dlc(_build_targets, _refs, chroot):
570 """Updates shared borealis-dlc ebuild - chromeos-base/borealis-dlc.
571
572 See: uprev_versioned_package.
573 """
574 package_path = os.path.join('src', 'private-overlays', 'chromeos-overlay',
575 'chromeos-base', 'borealis-dlc')
576
577 version_pin_src_path = _get_version_pin_src_path(package_path)
578 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
579
580 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
581
582
Patrick Meiring5897add2020-09-16 16:30:17 +1000583def _get_version_pin_src_path(package_path):
584 """Returns the path to the VERSION-PIN file for the given package."""
585 return os.path.join(constants.SOURCE_ROOT, package_path, 'VERSION-PIN')
586
587
Alex Klein87531182019-08-12 15:23:37 -0600588@uprevs_versioned_package(constants.CHROME_CP)
Alex Kleinf69bd802021-06-22 15:43:49 -0600589def uprev_chrome_from_ref(build_targets, refs, chroot):
Alex Klein87531182019-08-12 15:23:37 -0600590 """Uprev chrome and its related packages.
591
592 See: uprev_versioned_package.
593 """
594 # Determine the version from the refs (tags), i.e. the chrome versions are the
595 # tag names.
596 chrome_version = uprev_lib.get_chrome_version_from_refs(refs)
Chris McDonald25881af2020-05-12 03:17:53 -0600597 logging.debug('Chrome version determined from refs: %s', chrome_version)
Alex Klein87531182019-08-12 15:23:37 -0600598
Alex Klein16ea1b32021-10-01 15:48:50 -0600599 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600600
601
Alex Klein9ce3f682021-06-23 15:06:44 -0600602def revbump_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600603 build_targets: List['build_target_lib.BuildTarget'] = None,
Alex Klein9ce3f682021-06-23 15:06:44 -0600604 chroot: Optional['chroot_lib.Chroot'] = None
605) -> uprev_lib.UprevVersionedPackageResult:
Alex Kleinf69bd802021-06-22 15:43:49 -0600606 """Attempt to revbump chrome.
607
608 Revbumps are done by executing an uprev using the current stable version.
609 E.g. if chrome is on 1.2.3.4 and has a 1.2.3.4_rc-r2.ebuild, performing an
610 uprev on version 1.2.3.4 when there are applicable changes (e.g. to the 9999
611 ebuild) will result in a revbump to 1.2.3.4_rc-r3.ebuild.
612 """
613 chrome_version = uprev_lib.get_stable_chrome_version()
Alex Klein16ea1b32021-10-01 15:48:50 -0600614 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600615
616
Alex Klein9ce3f682021-06-23 15:06:44 -0600617def uprev_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600618 chrome_version: str,
619 build_targets: Optional[List['build_target_lib.BuildTarget']],
620 chroot: Optional['chroot_lib.Chroot']
Alex Klein9ce3f682021-06-23 15:06:44 -0600621) -> uprev_lib.UprevVersionedPackageResult:
622 """Attempt to uprev chrome and its related packages to the given version."""
Alex Klein87531182019-08-12 15:23:37 -0600623 uprev_manager = uprev_lib.UprevChromeManager(
624 chrome_version, build_targets=build_targets, chroot=chroot)
Chris McDonald38409112020-09-24 11:24:51 -0600625 result = uprev_lib.UprevVersionedPackageResult()
Chris McDonald25881af2020-05-12 03:17:53 -0600626 # TODO(crbug.com/1080429): Handle all possible outcomes of a Chrome uprev
627 # attempt. The expected behavior is documented in the following table:
628 #
629 # Outcome of Chrome uprev attempt:
630 # NEWER_VERSION_EXISTS:
631 # Do nothing.
632 # SAME_VERSION_EXISTS or REVISION_BUMP:
633 # Uprev followers
634 # Assert not VERSION_BUMP (any other outcome is fine)
635 # VERSION_BUMP or NEW_EBUILD_CREATED:
636 # Uprev followers
637 # Assert that Chrome & followers are at same package version
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600638
639 # Start with chrome itself so we can proceed accordingly.
640 chrome_result = uprev_manager.uprev(constants.CHROME_CP)
641 if chrome_result.newer_version_exists:
642 # Cannot use the given version (newer version already exists).
David Burger37f48672019-09-18 17:07:56 -0600643 return result
Alex Klein87531182019-08-12 15:23:37 -0600644
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600645 # Also uprev related packages.
Alex Klein87531182019-08-12 15:23:37 -0600646 for package in constants.OTHER_CHROME_PACKAGES:
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600647 follower_result = uprev_manager.uprev(package)
648 if chrome_result.stable_version and follower_result.version_bump:
649 logging.warning('%s had a version bump, but no more than a revision bump '
650 'should have been possible.', package)
Alex Klein87531182019-08-12 15:23:37 -0600651
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600652 if uprev_manager.modified_ebuilds:
653 # Record changes when we have them.
654 return result.add_result(chrome_version, uprev_manager.modified_ebuilds)
655
656 return result
Alex Klein87531182019-08-12 15:23:37 -0600657
658
Harvey Yang3eee06c2021-03-18 15:47:56 +0800659def _get_latest_version_from_refs(refs_prefix: str,
660 refs: List[uprev_lib.GitRef]) -> str:
661 """Get the latest version from refs
Ben Reiche779cf42020-12-15 03:21:31 +0000662
Ben Reiche779cf42020-12-15 03:21:31 +0000663 Versions are compared using |distutils.version.LooseVersion| and
664 the latest version is returned.
665
666 Args:
Harvey Yang3eee06c2021-03-18 15:47:56 +0800667 refs_prefix: The refs prefix of the tag format.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800668 refs: The tags to parse for the latest Perfetto version.
669
670 Returns:
671 The latest Perfetto version to use.
672 """
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800673 valid_refs = []
674 for gitiles in refs:
Harvey Yang3eee06c2021-03-18 15:47:56 +0800675 if gitiles.ref.startswith(refs_prefix):
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800676 valid_refs.append(gitiles.ref)
677
678 if not valid_refs:
679 return None
680
681 # Sort by version and take the latest version.
682 target_version_ref = sorted(valid_refs,
683 key=LooseVersion,
684 reverse=True)[0]
Harvey Yang3eee06c2021-03-18 15:47:56 +0800685 return target_version_ref.replace(refs_prefix, '')
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800686
687
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700688def _generate_platform_c_files(
689 replication_config: replication_config_pb2.ReplicationConfig,
690 chroot: 'chroot_lib.Chroot') -> List[str]:
Andrew Lamb9563a152019-12-04 11:42:18 -0700691 """Generates platform C files from a platform JSON payload.
692
693 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700694 replication_config: A ReplicationConfig that has already been run. If it
695 produced a build_config.json file, that file will be used to generate
696 platform C files. Otherwise, nothing will be generated.
697 chroot: The chroot to use to generate.
Andrew Lamb9563a152019-12-04 11:42:18 -0700698
699 Returns:
700 A list of generated files.
701 """
702 # Generate the platform C files from the build config. Note that it would be
703 # more intuitive to generate the platform C files from the platform config;
704 # however, cros_config_schema does not allow this, because the platform config
705 # payload is not always valid input. For example, if a property is both
706 # 'required' and 'build-only', it will fail schema validation. Thus, use the
707 # build config, and use '-f' to filter.
708 build_config_path = [
709 rule.destination_path
710 for rule in replication_config.file_replication_rules
711 if rule.destination_path.endswith('build_config.json')
712 ]
713
714 if not build_config_path:
715 logging.info(
Alex Kleinad6b48a2020-01-08 16:57:41 -0700716 'No build_config.json found, will not generate platform C files. '
717 'Replication config: %s', replication_config)
Andrew Lamb9563a152019-12-04 11:42:18 -0700718 return []
719
720 if len(build_config_path) > 1:
Alex Kleinad6b48a2020-01-08 16:57:41 -0700721 raise ValueError('Expected at most one build_config.json destination path. '
722 'Replication config: %s' % replication_config)
Andrew Lamb9563a152019-12-04 11:42:18 -0700723
724 build_config_path = build_config_path[0]
725
726 # Paths to the build_config.json and dir to output C files to, in the
727 # chroot.
728 build_config_chroot_path = os.path.join(constants.CHROOT_SOURCE_ROOT,
729 build_config_path)
730 generated_output_chroot_dir = os.path.join(constants.CHROOT_SOURCE_ROOT,
731 os.path.dirname(build_config_path))
732
733 command = [
734 'cros_config_schema', '-m', build_config_chroot_path, '-g',
735 generated_output_chroot_dir, '-f', '"TRUE"'
736 ]
737
738 cros_build_lib.run(
739 command, enter_chroot=True, chroot_args=chroot.get_enter_args())
740
741 # A relative (to the source root) path to the generated C files.
742 generated_output_dir = os.path.dirname(build_config_path)
743 generated_files = []
744 expected_c_files = ['config.c', 'ec_config.c', 'ec_config.h']
745 for f in expected_c_files:
746 if os.path.exists(
747 os.path.join(constants.SOURCE_ROOT, generated_output_dir, f)):
748 generated_files.append(os.path.join(generated_output_dir, f))
749
750 if len(expected_c_files) != len(generated_files):
751 raise GeneratedCrosConfigFilesError(expected_c_files, generated_files)
752
753 return generated_files
754
755
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700756def _get_private_overlay_package_root(ref: uprev_lib.GitRef, package: str):
Andrew Lambe836f222019-12-09 12:27:38 -0700757 """Returns the absolute path to the root of a given private overlay.
758
759 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700760 ref: GitRef for the private overlay.
761 package: Path to the package in the overlay.
Andrew Lambe836f222019-12-09 12:27:38 -0700762 """
763 # There might be a cleaner way to map from package -> path within the source
764 # tree. For now, just use string patterns.
Andrew Lamb4aa09912020-01-08 13:55:56 -0700765 private_overlay_ref_pattern = r'/chromeos\/overlays\/overlay-([\w-]+)-private'
Andrew Lambe836f222019-12-09 12:27:38 -0700766 match = re.match(private_overlay_ref_pattern, ref.path)
767 if not match:
768 raise ValueError('ref.path must match the pattern: %s. Actual ref: %s' %
769 (private_overlay_ref_pattern, ref))
770
771 overlay = match.group(1)
772
773 return os.path.join(constants.SOURCE_ROOT,
774 'src/private-overlays/overlay-%s-private' % overlay,
775 package)
776
777
Andrew Lambea9a8a22019-12-12 14:03:43 -0700778@uprevs_versioned_package('chromeos-base/chromeos-config-bsp')
779def replicate_private_config(_build_targets, refs, chroot):
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700780 """Replicate a private cros_config change to the corresponding public config.
781
Alex Kleinad6b48a2020-01-08 16:57:41 -0700782 See uprev_versioned_package for args
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700783 """
Andrew Lambea9a8a22019-12-12 14:03:43 -0700784 package = 'chromeos-base/chromeos-config-bsp'
785
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700786 if len(refs) != 1:
787 raise ValueError('Expected exactly one ref, actual %s' % refs)
788
789 # Expect a replication_config.jsonpb in the package root.
Andrew Lambe836f222019-12-09 12:27:38 -0700790 package_root = _get_private_overlay_package_root(refs[0], package)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700791 replication_config_path = os.path.join(package_root,
792 'replication_config.jsonpb')
793
794 try:
795 replication_config = json_format.Parse(
796 osutils.ReadFile(replication_config_path),
797 replication_config_pb2.ReplicationConfig())
798 except IOError:
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700799 raise ValueError(
800 'Expected ReplicationConfig missing at %s' % replication_config_path)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700801
802 replication_lib.Replicate(replication_config)
803
804 modified_files = [
805 rule.destination_path
806 for rule in replication_config.file_replication_rules
807 ]
808
Andrew Lamb9563a152019-12-04 11:42:18 -0700809 # The generated platform C files are not easily filtered by replication rules,
810 # i.e. JSON / proto filtering can be described by a FieldMask, arbitrary C
811 # files cannot. Therefore, replicate and filter the JSON payloads, and then
812 # generate filtered C files from the JSON payload.
813 modified_files.extend(_generate_platform_c_files(replication_config, chroot))
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700814
815 # Use the private repo's commit hash as the new version.
816 new_private_version = refs[0].revision
817
Andrew Lamb988f4da2019-12-10 10:16:43 -0700818 # modified_files should contain only relative paths at this point, but the
819 # returned UprevVersionedPackageResult must contain only absolute paths.
820 for i, modified_file in enumerate(modified_files):
821 assert not os.path.isabs(modified_file)
822 modified_files[i] = os.path.join(constants.SOURCE_ROOT, modified_file)
823
Chris McDonald38409112020-09-24 11:24:51 -0600824 return uprev_lib.UprevVersionedPackageResult().add_result(
825 new_private_version, modified_files)
Andrew Lamb2bde9e42019-11-04 13:24:09 -0700826
827
Dennis Kempinef05f2b2021-09-08 16:36:49 -0700828@uprevs_versioned_package('chromeos-base/crosvm')
829def uprev_crosvm(_build_targets, refs, _chroot):
830 """Updates crosvm ebuilds to latest revision
831
832 crosvm is not versioned. We are updating to the latest commit on the main
833 branch.
834
835 See: uprev_versioned_package.
836
837 Returns:
838 UprevVersionedPackageResult: The result of updating crosvm ebuilds.
839 """
840 overlay = os.path.join(constants.SOURCE_ROOT,
841 constants.CHROMIUMOS_OVERLAY_DIR)
842 repo_path = os.path.join(constants.SOURCE_ROOT, 'src', 'crosvm')
843 manifest = git.ManifestCheckout.Cached(repo_path)
844
845 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
Dennis Kempin257b74c2021-09-28 14:38:17 -0700846 uprev_manager.uprev(
847 package_list=[
848 'chromeos-base/crosvm',
849 'dev-rust/assertions',
850 'dev-rust/cros_async',
851 'dev-rust/cros_fuzz',
852 'dev-rust/data_model',
853 'dev-rust/enumn',
854 'dev-rust/io_uring',
855 'dev-rust/p9',
856 'dev-rust/sync',
857 'dev-rust/sys_util',
858 'dev-rust/tempfile',
859 'media-sound/audio_streams',
860 ],
861 force=True
862 )
Dennis Kempinef05f2b2021-09-08 16:36:49 -0700863
864 updated_files = uprev_manager.modified_ebuilds
865 result = uprev_lib.UprevVersionedPackageResult()
866 result.add_result(refs[0].revision, updated_files)
867 return result
868
869
Alex Klein5caab872021-09-10 11:44:37 -0600870def get_best_visible(
871 atom: str,
872 build_target: Optional['build_target_lib.BuildTarget'] = None
873) -> package_info.PackageInfo:
Alex Kleinbbef2b32019-08-27 10:38:50 -0600874 """Returns the best visible CPV for the given atom.
875
876 Args:
Alex Klein5caab872021-09-10 11:44:37 -0600877 atom: The atom to look up.
878 build_target: The build target whose sysroot should be searched, or the SDK
879 if not provided.
Alex Kleinad6b48a2020-01-08 16:57:41 -0700880
881 Returns:
Alex Klein5caab872021-09-10 11:44:37 -0600882 The best visible package, or None if none are visible.
Alex Kleinbbef2b32019-08-27 10:38:50 -0600883 """
David Burger1e0fe232019-07-01 14:52:07 -0600884 assert atom
Alex Kleinbbef2b32019-08-27 10:38:50 -0600885
Alex Klein5caab872021-09-10 11:44:37 -0600886 return portage_util.PortageqBestVisible(
887 atom,
888 board=build_target.name if build_target else None,
889 sysroot=build_target.root if build_target else None)
Alex Kleinda39c6d2019-09-16 14:36:36 -0600890
891
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700892def has_prebuilt(
893 atom: str,
894 build_target: 'build_target_lib.BuildTarget' = None,
895 useflags: Union[Iterable[str], str] = None) -> bool:
Alex Kleinda39c6d2019-09-16 14:36:36 -0600896 """Check if a prebuilt exists.
897
898 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700899 atom: The package whose prebuilt is being queried.
900 build_target: The build target whose sysroot should be searched, or the
901 SDK if not provided.
Alex Klein149fd3b2019-12-16 16:01:05 -0700902 useflags: Any additional USE flags that should be set. May be a string
903 of properly formatted USE flags, or an iterable of individual flags.
Alex Kleinad6b48a2020-01-08 16:57:41 -0700904
905 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700906 True if there is an available prebuilt, False otherwise.
Alex Kleinda39c6d2019-09-16 14:36:36 -0600907 """
908 assert atom
909
910 board = build_target.name if build_target else None
Alex Klein149fd3b2019-12-16 16:01:05 -0700911 extra_env = None
912 if useflags:
913 new_flags = useflags
Mike Frysingercfecd6b2020-12-14 23:54:05 -0500914 if not isinstance(useflags, str):
Alex Klein149fd3b2019-12-16 16:01:05 -0700915 new_flags = ' '.join(useflags)
916
917 existing = os.environ.get('USE', '')
918 final_flags = '%s %s' % (existing, new_flags)
919 extra_env = {'USE': final_flags.strip()}
920 return portage_util.HasPrebuilt(atom, board=board, extra_env=extra_env)
Alex Klein36b117f2019-09-30 15:13:46 -0600921
922
David Burger0f9dd4e2019-10-08 12:33:42 -0600923def builds(atom, build_target, packages=None):
Alex Klein36b117f2019-09-30 15:13:46 -0600924 """Check if |build_target| builds |atom| (has it in its depgraph)."""
925 cros_build_lib.AssertInsideChroot()
926
Alex Kleind8cd4c62020-09-14 13:37:47 -0600927 pkgs = tuple(packages) if packages else None
LaMont Jones4cbecba2020-05-12 11:54:27 -0600928 # TODO(crbug/1081828): Receive and use sysroot.
929 graph, _sdk_graph = dependency.GetBuildDependency(
Alex Kleind8cd4c62020-09-14 13:37:47 -0600930 build_target.root, build_target.name, pkgs)
Alex Klein36b117f2019-09-30 15:13:46 -0600931 return any(atom in package for package in graph['package_deps'])
Michael Mortensenb70e8a82019-10-10 18:43:41 -0600932
933
Alex Klein6becabc2020-09-11 14:03:05 -0600934def needs_chrome_source(
935 build_target: 'build_target_lib.BuildTarget',
936 compile_source=False,
937 packages: Optional[List[package_info.PackageInfo]] = None,
938 useflags=None):
939 """Check if the chrome source is needed.
940
941 The chrome source is needed if the build target builds chrome or any of its
942 follower packages, and can't use a prebuilt for them either because it's not
943 available, or because we can't use prebuilts because it must build from
944 source.
945 """
946 cros_build_lib.AssertInsideChroot()
947
948 # Check if it builds chrome and/or a follower package.
Alex Kleina8052162021-02-03 14:28:22 -0700949 graph = depgraph.get_sysroot_dependency_graph(build_target.root, packages)
Alex Klein6becabc2020-09-11 14:03:05 -0600950 builds_chrome = constants.CHROME_CP in graph
951 builds_follower = {
952 pkg: pkg in graph for pkg in constants.OTHER_CHROME_PACKAGES
953 }
954
Alex Klein9ce3f682021-06-23 15:06:44 -0600955 local_uprev = builds_chrome and revbump_chrome([build_target])
956
Alex Klein6becabc2020-09-11 14:03:05 -0600957 # When we are compiling source set False since we do not use prebuilts.
958 # When not compiling from source, start with True, i.e. we have every prebuilt
959 # we've checked for up to this point.
960 has_chrome_prebuilt = not compile_source
961 has_follower_prebuilts = not compile_source
962 # Save packages that need prebuilts for reporting.
963 pkgs_needing_prebuilts = []
964 if compile_source:
965 # Need everything.
966 pkgs_needing_prebuilts.append(constants.CHROME_CP)
967 pkgs_needing_prebuilts.extend(
968 [pkg for pkg, builds_pkg in builds_follower.items() if builds_pkg])
969 else:
970 # Check chrome itself.
971 if builds_chrome:
972 has_chrome_prebuilt = has_prebuilt(
973 constants.CHROME_CP, build_target=build_target, useflags=useflags)
974 if not has_chrome_prebuilt:
975 pkgs_needing_prebuilts.append(constants.CHROME_CP)
976 # Check follower packages.
977 for pkg, builds_pkg in builds_follower.items():
978 if not builds_pkg:
979 continue
980 prebuilt = has_prebuilt(pkg, build_target=build_target, useflags=useflags)
981 has_follower_prebuilts &= prebuilt
982 if not prebuilt:
983 pkgs_needing_prebuilts.append(pkg)
984 # Postcondition: has_chrome_prebuilt and has_follower_prebuilts now correctly
985 # reflect whether we actually have the corresponding prebuilts for the build.
986
987 needs_chrome = builds_chrome and not has_chrome_prebuilt
988 needs_follower = any(builds_follower.values()) and not has_follower_prebuilts
989
990 return NeedsChromeSourceResult(
Sergey Frolov26ff97b2021-08-14 00:02:11 +0000991 needs_chrome_source=needs_chrome or needs_follower,
Alex Klein6becabc2020-09-11 14:03:05 -0600992 builds_chrome=builds_chrome,
993 packages=[package_info.parse(p) for p in pkgs_needing_prebuilts],
994 missing_chrome_prebuilt=not has_chrome_prebuilt,
Alex Klein9ce3f682021-06-23 15:06:44 -0600995 missing_follower_prebuilt=not has_follower_prebuilts,
996 local_uprev=local_uprev,
997 )
Alex Klein6becabc2020-09-11 14:03:05 -0600998
999
Alex Klein68a28712021-11-08 11:08:30 -07001000class TargetVersions(NamedTuple):
1001 """Data class for the info that makes up the "target versions"."""
1002 android_version: str
1003 android_branch: str
1004 android_target: str
1005 chrome_version: str
1006 platform_version: str
1007 milestone_version: str
1008 full_version: str
1009
1010
1011def get_target_versions(
1012 build_target: 'build_target_lib.BuildTarget',
1013 packages: List[package_info.PackageInfo] = None
1014) -> TargetVersions:
1015 """Aggregate version info for a few key packages and the OS as a whole."""
1016 # Android version.
1017 android_version = determine_android_version(build_target.name)
1018 logging.info('Found android version: %s', android_version)
1019 # Android branch version.
1020 android_branch = determine_android_branch(build_target.name)
1021 logging.info('Found android branch version: %s', android_branch)
1022 # Android target version.
1023 android_target = determine_android_target(build_target.name)
1024 logging.info('Found android target version: %s', android_target)
1025
1026 # TODO(crbug/1019770): Investigate cases where builds_chrome is true but
1027 # chrome_version is None.
1028
1029 builds_chrome = builds(constants.CHROME_CP, build_target, packages=packages)
1030 chrome_version = None
1031 if builds_chrome:
1032 # Chrome version fetch.
1033 chrome_version = determine_chrome_version(build_target)
1034 logging.info('Found chrome version: %s', chrome_version)
1035
1036 # The ChromeOS version info.
1037 platform_version = determine_platform_version()
1038 milestone_version = determine_milestone_version()
1039 full_version = determine_full_version()
1040
1041 return TargetVersions(android_version, android_branch, android_target,
1042 chrome_version, platform_version, milestone_version,
1043 full_version)
1044
1045
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001046def determine_chrome_version(
1047 build_target: 'build_target_lib.BuildTarget') -> Optional[str]:
Michael Mortensenc2615b72019-10-15 08:12:24 -06001048 """Returns the current Chrome version for the board (or in buildroot).
1049
1050 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001051 build_target: The board build target.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001052
1053 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001054 The chrome version if available.
Michael Mortensenc2615b72019-10-15 08:12:24 -06001055 """
Michael Mortensen9fe740c2019-10-29 14:42:48 -06001056 # TODO(crbug/1019770): Long term we should not need the try/catch here once
1057 # the builds function above only returns True for chrome when
1058 # determine_chrome_version will succeed.
1059 try:
Alex Klein5caab872021-09-10 11:44:37 -06001060 pkg_info = portage_util.PortageqBestVisible(
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001061 constants.CHROME_CP, build_target.name, cwd=constants.SOURCE_ROOT)
Michael Mortensen9fe740c2019-10-29 14:42:48 -06001062 except cros_build_lib.RunCommandError as e:
1063 # Return None because portage failed when trying to determine the chrome
1064 # version.
1065 logging.warning('Caught exception in determine_chrome_package: %s', e)
1066 return None
Michael Mortensenc2615b72019-10-15 08:12:24 -06001067 # Something like 78.0.3877.4_rc -> 78.0.3877.4
Alex Klein5caab872021-09-10 11:44:37 -06001068 return pkg_info.version.partition('_')[0]
Michael Mortensenc2615b72019-10-15 08:12:24 -06001069
1070
Alex Klein68a28712021-11-08 11:08:30 -07001071@functools.lru_cache()
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001072def determine_android_package(board: str) -> Optional[str]:
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001073 """Returns the active Android container package in use by the board.
1074
1075 Args:
1076 board: The board name this is specific to.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001077
1078 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001079 The android package string if there is one.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001080 """
Michael Mortensene0f4b542019-10-24 15:30:23 -06001081 try:
1082 packages = portage_util.GetPackageDependencies(board, 'virtual/target-os')
Michael Mortensene0f4b542019-10-24 15:30:23 -06001083 except cros_build_lib.RunCommandError as e:
1084 # Return None because a command (likely portage) failed when trying to
1085 # determine the package.
1086 logging.warning('Caught exception in determine_android_package: %s', e)
1087 return None
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001088
Alex Kleinad6b48a2020-01-08 16:57:41 -07001089 # We assume there is only one Android package in the depgraph.
1090 for package in packages:
Mike Frysingerfcca49e2021-03-17 01:09:20 -04001091 if (package.startswith('chromeos-base/android-container-') or
1092 package.startswith('chromeos-base/android-vm-')):
Alex Kleinad6b48a2020-01-08 16:57:41 -07001093 return package
1094 return None
1095
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001096
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001097def determine_android_version(board: str, package: str = None):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001098 """Determine the current Android version in buildroot now and return it.
1099
1100 This uses the typical portage logic to determine which version of Android
1101 is active right now in the buildroot.
1102
1103 Args:
Mike Frysingerb53f1822021-03-05 00:44:50 -05001104 board: The board name this is specific to.
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001105 package: The Android package, if already computed.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001106
1107 Returns:
Mike Frysingerb53f1822021-03-05 00:44:50 -05001108 The Android build ID of the container for the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001109
1110 Raises:
1111 NoAndroidVersionError: if no unique Android version can be determined.
1112 """
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001113 if not package:
1114 package = determine_android_package(board)
Mike Frysingerb53f1822021-03-05 00:44:50 -05001115 if not package:
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001116 return None
Mike Frysingerb53f1822021-03-05 00:44:50 -05001117 cpv = package_info.SplitCPV(package)
1118 if not cpv:
1119 raise NoAndroidVersionError(
1120 'Android version could not be determined for %s' % board)
1121 return cpv.version_no_rev
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001122
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001123
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001124def determine_android_branch(board, package=None):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001125 """Returns the Android branch in use by the active container ebuild."""
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001126 if not package:
1127 package = determine_android_package(board)
1128 if not package:
Michael Mortensenedf76532019-10-16 14:22:37 -06001129 return None
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001130 ebuild_path = portage_util.FindEbuildForBoardPackage(package, board)
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001131 # We assume all targets pull from the same branch and that we always
Federico 'Morg' Pareschicd9165a2020-05-29 09:45:55 +09001132 # have at least one of the following targets.
Shao-Chuan Lee73bba612020-06-17 11:47:04 +09001133 targets = constants.ANDROID_ALL_BUILD_TARGETS
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001134 ebuild_content = osutils.SourceEnvironment(ebuild_path, targets)
1135 for target in targets:
1136 if target in ebuild_content:
1137 branch = re.search(r'(.*?)-linux-', ebuild_content[target])
1138 if branch is not None:
1139 return branch.group(1)
1140 raise NoAndroidBranchError(
1141 'Android branch could not be determined for %s (ebuild empty?)' % board)
1142
1143
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001144def determine_android_target(board, package=None):
Michael Mortensen14960d02019-10-18 07:53:59 -06001145 """Returns the Android target in use by the active container ebuild."""
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001146 if not package:
1147 package = determine_android_package(board)
1148 if not package:
Michael Mortensenedf76532019-10-16 14:22:37 -06001149 return None
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001150 if package.startswith('chromeos-base/android-vm-'):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001151 return 'bertha'
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001152 elif package.startswith('chromeos-base/android-container-'):
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001153 return 'cheets'
1154
1155 raise NoAndroidTargetError(
1156 'Android Target cannot be determined for the package: %s' %
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001157 package)
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001158
1159
1160def determine_platform_version():
1161 """Returns the platform version from the source root."""
Michael Mortensen009cb662019-10-21 11:38:43 -06001162 # Platform version is something like '12575.0.0'.
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001163 version = manifest_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1164 return version.VersionString()
Michael Mortensen009cb662019-10-21 11:38:43 -06001165
1166
1167def determine_milestone_version():
1168 """Returns the platform version from the source root."""
1169 # Milestone version is something like '79'.
1170 version = manifest_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1171 return version.chrome_branch
1172
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001173
Michael Mortensen009cb662019-10-21 11:38:43 -06001174def determine_full_version():
1175 """Returns the full version from the source root."""
1176 # Full version is something like 'R79-12575.0.0'.
1177 milestone_version = determine_milestone_version()
1178 platform_version = determine_platform_version()
1179 full_version = ('R%s-%s' % (milestone_version, platform_version))
1180 return full_version
Michael Mortensen71ef5682020-05-07 14:29:24 -06001181
1182
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001183def find_fingerprints(
1184 build_target: 'build_target_lib.BuildTarget') -> List[str]:
Michael Mortensende716a12020-05-15 11:27:00 -06001185 """Returns a list of fingerprints for this build.
1186
1187 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001188 build_target: The build target.
Michael Mortensende716a12020-05-15 11:27:00 -06001189
1190 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001191 List of fingerprint strings.
Michael Mortensende716a12020-05-15 11:27:00 -06001192 """
1193 cros_build_lib.AssertInsideChroot()
1194 fp_file = 'cheets-fingerprint.txt'
1195 fp_path = os.path.join(
1196 image_lib.GetLatestImageLink(build_target.name),
1197 fp_file)
1198 if not os.path.isfile(fp_path):
1199 logging.info('Fingerprint file not found: %s', fp_path)
Michael Mortensend81d81e2020-06-09 14:20:59 -06001200 return []
Michael Mortensende716a12020-05-15 11:27:00 -06001201 logging.info('Reading fingerprint file: %s', fp_path)
1202 fingerprints = osutils.ReadFile(fp_path).splitlines()
1203 return fingerprints
1204
1205
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001206def get_all_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen59e30872020-05-18 14:12:49 -06001207 """Extract firmware version for all models present.
1208
1209 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001210 build_target: The build target.
Michael Mortensen59e30872020-05-18 14:12:49 -06001211
1212 Returns:
1213 A dict of FirmwareVersions namedtuple instances by model.
1214 Each element will be populated based on whether it was present in the
1215 command output.
1216 """
1217 cros_build_lib.AssertInsideChroot()
1218 result = {}
1219 # Note that example output for _get_firmware_version_cmd_result is available
1220 # in the packages_unittest.py for testing get_all_firmware_versions.
1221 cmd_result = _get_firmware_version_cmd_result(build_target)
1222
1223 # There is a blank line between the version info for each model.
1224 firmware_version_payloads = cmd_result.split('\n\n')
1225 for firmware_version_payload in firmware_version_payloads:
1226 if 'BIOS' in firmware_version_payload:
1227 firmware_version = _find_firmware_versions(firmware_version_payload)
1228 result[firmware_version.model] = firmware_version
1229 return result
1230
1231
Michael Mortensen71ef5682020-05-07 14:29:24 -06001232FirmwareVersions = collections.namedtuple(
1233 'FirmwareVersions', ['model', 'main', 'main_rw', 'ec', 'ec_rw'])
1234
1235
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001236def get_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen71ef5682020-05-07 14:29:24 -06001237 """Extract version information from the firmware updater, if one exists.
1238
1239 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001240 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001241
1242 Returns:
1243 A FirmwareVersions namedtuple instance.
1244 Each element will either be set to the string output by the firmware
1245 updater shellball, or None if there is no firmware updater.
1246 """
1247 cros_build_lib.AssertInsideChroot()
1248 cmd_result = _get_firmware_version_cmd_result(build_target)
1249 if cmd_result:
1250 return _find_firmware_versions(cmd_result)
1251 else:
1252 return FirmwareVersions(None, None, None, None, None)
1253
1254
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001255def _get_firmware_version_cmd_result(
1256 build_target: 'build_target_lib.BuildTarget'):
Michael Mortensen71ef5682020-05-07 14:29:24 -06001257 """Gets the raw result output of the firmware updater version command.
1258
1259 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001260 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001261
1262 Returns:
1263 Command execution result.
1264 """
1265 updater = os.path.join(build_target.root,
1266 'usr/sbin/chromeos-firmwareupdate')
1267 logging.info('Calling updater %s', updater)
1268 # Call the updater using the chroot-based path.
1269 return cros_build_lib.run([updater, '-V'],
1270 capture_output=True, log_output=True,
1271 encoding='utf-8').stdout
1272
1273
1274def _find_firmware_versions(cmd_output):
1275 """Finds firmware version output via regex matches against the cmd_output.
1276
1277 Args:
1278 cmd_output: The raw output to search against.
1279
1280 Returns:
1281 FirmwareVersions namedtuple with results.
1282 Each element will either be set to the string output by the firmware
1283 updater shellball, or None if there is no match.
1284 """
1285
1286 # Sometimes a firmware bundle includes a special combination of RO+RW
1287 # firmware. In this case, the RW firmware version is indicated with a "(RW)
1288 # version" field. In other cases, the "(RW) version" field is not present.
1289 # Therefore, search for the "(RW)" fields first and if they aren't present,
1290 # fallback to the other format. e.g. just "BIOS version:".
1291 # TODO(mmortensen): Use JSON once the firmware updater supports it.
1292 main = None
1293 main_rw = None
1294 ec = None
1295 ec_rw = None
1296 model = None
1297
1298 match = re.search(r'BIOS version:\s*(?P<version>.*)', cmd_output)
1299 if match:
1300 main = match.group('version')
1301
1302 match = re.search(r'BIOS \(RW\) version:\s*(?P<version>.*)', cmd_output)
1303 if match:
1304 main_rw = match.group('version')
1305
1306 match = re.search(r'EC version:\s*(?P<version>.*)', cmd_output)
1307 if match:
1308 ec = match.group('version')
1309
1310 match = re.search(r'EC \(RW\) version:\s*(?P<version>.*)', cmd_output)
1311 if match:
1312 ec_rw = match.group('version')
1313
1314 match = re.search(r'Model:\s*(?P<model>.*)', cmd_output)
1315 if match:
1316 model = match.group('model')
1317
1318 return FirmwareVersions(model, main, main_rw, ec, ec_rw)
Michael Mortensena4af79e2020-05-06 16:18:48 -06001319
1320
1321MainEcFirmwareVersions = collections.namedtuple(
1322 'MainEcFirmwareVersions', ['main_fw_version', 'ec_fw_version'])
1323
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001324def determine_firmware_versions(build_target: 'build_target_lib.BuildTarget'):
Michael Mortensena4af79e2020-05-06 16:18:48 -06001325 """Returns a namedtuple with main and ec firmware versions.
1326
1327 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001328 build_target: The build target.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001329
1330 Returns:
1331 MainEcFirmwareVersions namedtuple with results.
1332 """
1333 fw_versions = get_firmware_versions(build_target)
1334 main_fw_version = fw_versions.main_rw or fw_versions.main
1335 ec_fw_version = fw_versions.ec_rw or fw_versions.ec
1336
1337 return MainEcFirmwareVersions(main_fw_version, ec_fw_version)
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001338
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001339def determine_kernel_version(
1340 build_target: 'build_target_lib.BuildTarget') -> Optional[str]:
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001341 """Returns a string containing the kernel version for this build target.
1342
1343 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001344 build_target: The build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001345
1346 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001347 The kernel versions, or None.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001348 """
1349 try:
1350 packages = portage_util.GetPackageDependencies(build_target.name,
1351 'virtual/linux-sources')
1352 except cros_build_lib.RunCommandError as e:
1353 logging.warning('Unable to get package list for metadata: %s', e)
1354 return None
1355 for package in packages:
1356 if package.startswith('sys-kernel/chromeos-kernel-'):
Alex Klein18a60af2020-06-11 12:08:47 -06001357 kernel_version = package_info.SplitCPV(package).version
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001358 logging.info('Found active kernel version: %s', kernel_version)
1359 return kernel_version
1360 return None
Michael Mortensen125bb012020-05-21 14:02:10 -06001361
1362
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001363def get_models(
1364 build_target: 'build_target_lib.BuildTarget',
1365 log_output: bool = True) -> Optional[List[str]]:
Michael Mortensen125bb012020-05-21 14:02:10 -06001366 """Obtain a list of models supported by a unified board.
1367
1368 This ignored whitelabel models since GoldenEye has no specific support for
1369 these at present.
1370
1371 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001372 build_target: The build target.
Michael Mortensen125bb012020-05-21 14:02:10 -06001373 log_output: Whether to log the output of the cros_config_host invocation.
1374
1375 Returns:
1376 A list of models supported by this board, if it is a unified build; None,
1377 if it is not a unified build.
1378 """
1379 return _run_cros_config_host(build_target, ['list-models'],
1380 log_output=log_output)
1381
1382
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001383def get_key_id(
1384 build_target: 'build_target_lib.BuildTarget',
1385 model: str) -> Optional[str]:
Michael Mortensen359c1f32020-05-28 19:35:42 -06001386 """Obtain the key_id for a model within the build_target.
1387
1388 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001389 build_target: The build target.
1390 model: The model name
Michael Mortensen359c1f32020-05-28 19:35:42 -06001391
1392 Returns:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001393 A key_id or None.
Michael Mortensen359c1f32020-05-28 19:35:42 -06001394 """
1395 model_arg = '--model=' + model
1396 key_id_list = _run_cros_config_host(
1397 build_target,
1398 [model_arg, 'get', '/firmware-signing', 'key-id'])
1399 key_id = None
1400 if len(key_id_list) == 1:
1401 key_id = key_id_list[0]
1402 return key_id
1403
1404
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001405def _run_cros_config_host(
1406 build_target: 'build_target_lib.BuildTarget',
1407 args: List[str],
1408 log_output: bool = True) -> Optional[List[str]]:
Michael Mortensen125bb012020-05-21 14:02:10 -06001409 """Run the cros_config_host tool.
1410
1411 Args:
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001412 build_target: The build target.
Michael Mortensen125bb012020-05-21 14:02:10 -06001413 args: List of arguments to pass.
1414 log_output: Whether to log the output of the cros_config_host.
1415
1416 Returns:
1417 Output of the tool
1418 """
1419 cros_build_lib.AssertInsideChroot()
1420 tool = '/usr/bin/cros_config_host'
1421 if not os.path.isfile(tool):
1422 return None
1423
1424 config_fname = build_target.full_path(
1425 'usr/share/chromeos-config/yaml/config.yaml')
1426
1427 result = cros_build_lib.run(
1428 [tool, '-c', config_fname] + args,
1429 capture_output=True,
1430 encoding='utf-8',
1431 log_output=log_output,
1432 check=False)
1433 if result.returncode:
1434 # Show the output for debugging purposes.
1435 if 'No such file or directory' not in result.error:
1436 logging.error('cros_config_host failed: %s\n', result.error)
1437 return None
1438 return result.output.strip().splitlines()