blob: a546d9a357e4901d509ea51d03f573d9b4731ef2 [file] [log] [blame]
Alex Kleineb77ffa2019-05-28 14:47:44 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Package utility functionality."""
7
8from __future__ import print_function
9
Alex Klein87531182019-08-12 15:23:37 -060010import functools
Evan Hernandezb51f1522019-08-15 11:29:40 -060011import os
Alex Klein87531182019-08-12 15:23:37 -060012
Alex Kleineb77ffa2019-05-28 14:47:44 -060013from chromite.lib import constants
Evan Hernandezb51f1522019-08-15 11:29:40 -060014from chromite.lib import cros_build_lib
Alex Klein4de25e82019-08-05 15:58:39 -060015from chromite.lib import cros_logging as logging
Alex Kleineb77ffa2019-05-28 14:47:44 -060016from chromite.lib import git
Evan Hernandezb51f1522019-08-15 11:29:40 -060017from chromite.lib import osutils
Alex Kleineb77ffa2019-05-28 14:47:44 -060018from chromite.lib import portage_util
Alex Kleind6195b62019-08-06 16:01:16 -060019from chromite.lib import uprev_lib
Alex Kleineb77ffa2019-05-28 14:47:44 -060020
Alex Klein87531182019-08-12 15:23:37 -060021# Registered handlers for uprevving versioned packages.
22_UPREV_FUNCS = {}
23
Alex Kleineb77ffa2019-05-28 14:47:44 -060024
25class Error(Exception):
26 """Module's base error class."""
27
28
Alex Klein4de25e82019-08-05 15:58:39 -060029class UnknownPackageError(Error):
30 """Uprev attempted for a package without a registered handler."""
31
32
Alex Kleineb77ffa2019-05-28 14:47:44 -060033class UprevError(Error):
34 """An error occurred while uprevving packages."""
35
36
Alex Klein4de25e82019-08-05 15:58:39 -060037class AndroidIsPinnedUprevError(UprevError):
38 """Raised when we try to uprev while Android is pinned."""
39
40 def __init__(self, new_android_atom):
41 """Initialize a AndroidIsPinnedUprevError.
42
43 Args:
44 new_android_atom: The Android atom that we failed to
45 uprev to, due to Android being pinned.
46 """
47 assert new_android_atom
48 msg = ('Failed up uprev to Android version %s as Android was pinned.' %
49 new_android_atom)
50 super(AndroidIsPinnedUprevError, self).__init__(msg)
51 self.new_android_atom = new_android_atom
Alex Klein87531182019-08-12 15:23:37 -060052
53
54def uprevs_versioned_package(package):
55 """Decorator to register package uprev handlers."""
56 assert package
57
58 def register(func):
59 """Registers |func| as a handler for |package|."""
60 _UPREV_FUNCS[package] = func
61
62 @functools.wraps(func)
63 def pass_through(*args, **kwargs):
64 return func(*args, **kwargs)
65
66 return pass_through
67
68 return register
69
70
Alex Klein4de25e82019-08-05 15:58:39 -060071def uprev_android(tracking_branch, android_package, android_build_branch,
72 chroot, build_targets=None, android_version=None,
73 android_gts_build_branch=None):
74 """Returns the portage atom for the revved Android ebuild - see man emerge."""
75 command = ['cros_mark_android_as_stable',
76 '--tracking_branch=%s' % tracking_branch,
77 '--android_package=%s' % android_package,
78 '--android_build_branch=%s' % android_build_branch]
79 if build_targets:
80 command.append('--boards=%s' % ':'.join(bt.name for bt in build_targets))
81 if android_version:
82 command.append('--force_version=%s' % android_version)
83 if android_gts_build_branch:
84 command.append('--android_gts_build_branch=%s' % android_gts_build_branch)
85
86 result = cros_build_lib.RunCommand(command, redirect_stdout=True,
87 enter_chroot=True,
88 chroot_args=chroot.get_enter_args())
89
90 android_atom = _parse_android_atom(result)
91 if not android_atom:
92 logging.info('Found nothing to rev.')
93 return None
94
95 for target in build_targets or []:
96 # Sanity check: We should always be able to merge the version of
97 # Android we just unmasked.
98 command = ['emerge-%s' % target.name, '-p', '--quiet',
99 '=%s' % android_atom]
100 try:
101 cros_build_lib.RunCommand(command, enter_chroot=True,
102 chroot_args=chroot.get_enter_args())
103 except cros_build_lib.RunCommandError:
104 logging.error(
105 'Cannot emerge-%s =%s\nIs Android pinned to an older '
106 'version?', target, android_atom)
107 raise AndroidIsPinnedUprevError(android_atom)
108
109 return android_atom
110
111
112def _parse_android_atom(result):
113 """Helper to parse the atom from the cros_mark_android_as_stable output.
114
115 This function is largely just intended to make testing easier.
116
117 Args:
118 result (cros_build_lib.CommandResult): The cros_mark_android_as_stable
119 command result.
120 """
121 portage_atom_string = result.output.strip()
122
123 android_atom = None
124 if portage_atom_string:
125 android_atom = portage_atom_string.splitlines()[-1].partition('=')[-1]
126
127 return android_atom
128
129
Alex Kleineb77ffa2019-05-28 14:47:44 -0600130def uprev_build_targets(build_targets, overlay_type, chroot=None,
131 output_dir=None):
132 """Uprev the set provided build targets, or all if not specified.
133
134 Args:
135 build_targets (list[build_target_util.BuildTarget]|None): The build targets
136 whose overlays should be uprevved, empty or None for all.
137 overlay_type (str): One of the valid overlay types except None (see
138 constants.VALID_OVERLAYS).
139 chroot (chroot_lib.Chroot|None): The chroot to clean, if desired.
140 output_dir (str|None): The path to optionally dump result files.
141 """
142 # Need a valid overlay, but exclude None.
143 assert overlay_type and overlay_type in constants.VALID_OVERLAYS
144
145 if build_targets:
146 overlays = portage_util.FindOverlaysForBoards(
147 overlay_type, boards=[t.name for t in build_targets])
148 else:
149 overlays = portage_util.FindOverlays(overlay_type)
150
151 return uprev_overlays(overlays, build_targets=build_targets, chroot=chroot,
152 output_dir=output_dir)
153
154
155def uprev_overlays(overlays, build_targets=None, chroot=None, output_dir=None):
156 """Uprev the given overlays.
157
158 Args:
159 overlays (list[str]): The list of overlay paths.
160 build_targets (list[build_target_util.BuildTarget]|None): The build targets
161 to clean in |chroot|, if desired. No effect unless |chroot| is provided.
162 chroot (chroot_lib.Chroot|None): The chroot to clean, if desired.
163 output_dir (str|None): The path to optionally dump result files.
164
165 Returns:
166 list[str] - The paths to all of the modified ebuild files. This includes the
167 new files that were added (i.e. the new versions) and all of the removed
168 files (i.e. the old versions).
169 """
170 assert overlays
171
172 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
173
Alex Kleind6195b62019-08-06 16:01:16 -0600174 uprev_manager = uprev_lib.UprevOverlayManager(overlays, manifest,
175 build_targets=build_targets,
176 chroot=chroot,
177 output_dir=output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600178 uprev_manager.uprev()
179
180 return uprev_manager.modified_ebuilds
181
182
Alex Klein87531182019-08-12 15:23:37 -0600183def uprev_versioned_package(package, build_targets, refs, chroot):
184 """Call registered uprev handler function for the package.
185
186 Args:
187 package (portage_util.CPV): The package being uprevved.
188 build_targets (list[build_target_util.BuildTarget]): The build targets to
189 clean on a successful uprev.
190 refs (list[uprev_lib.GitRef]):
191 chroot (chroot_lib.Chroot): The chroot to enter for cleaning.
192
193 Returns:
194 list[str]: The list of modified ebuilds.
195 """
196 assert package
197
198 if package.cp not in _UPREV_FUNCS:
199 raise UnknownPackageError(
200 'Package "%s" does not have a registered handler.' % package.cp)
201
202 return _UPREV_FUNCS[package.cp](build_targets, refs, chroot)
203
204
Evan Hernandezb51f1522019-08-15 11:29:40 -0600205# TODO(evanhernandez): Remove this. Only a quick hack for testing.
206@uprevs_versioned_package('sample/sample')
207def uprev_sample(*_args, **_kwargs):
208 """Mimics an uprev by changing files in sandbox repos.
209
210 See: uprev_versioned_package.
211 """
212 paths = [
213 os.path.join(constants.SOURCE_ROOT, 'infra/dummies', repo, 'sample.txt')
214 for repo in ('general-sandbox', 'merge-sandbox')
215 ]
216
217 for path in paths:
218 osutils.WriteFile(path, cros_build_lib.GetRandomString())
219
220 return paths
221
222
Alex Klein87531182019-08-12 15:23:37 -0600223@uprevs_versioned_package(constants.CHROME_CP)
224def uprev_chrome(build_targets, refs, chroot):
225 """Uprev chrome and its related packages.
226
227 See: uprev_versioned_package.
228 """
229 # Determine the version from the refs (tags), i.e. the chrome versions are the
230 # tag names.
231 chrome_version = uprev_lib.get_chrome_version_from_refs(refs)
232
233 uprev_manager = uprev_lib.UprevChromeManager(
234 chrome_version, build_targets=build_targets, chroot=chroot)
235 # Start with chrome itself, as we can't do anything else unless chrome
236 # uprevs successfully.
237 if not uprev_manager.uprev(constants.CHROME_CP):
238 return []
239
240 # With a successful chrome rev, also uprev related packages.
241 for package in constants.OTHER_CHROME_PACKAGES:
242 uprev_manager.uprev(package)
243
244 return uprev_manager.modified_ebuilds
245
246
David Burger1e0fe232019-07-01 14:52:07 -0600247def get_best_visible(atom):
248 """Returns the best visible CPV for the given atom."""
249 assert atom
250 return portage_util.PortageqBestVisible(atom)