blob: c16ab75f903bcf8ea1411f66cd8c29a97b06c29c [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Aviv Keshetb1238c32013-04-01 11:42:13 -07002# Copyright (c) 2013 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
Mike Frysingerad8c6ca2014-02-03 11:28:45 -05006"""Fast alternative to `emerge-$BOARD autotest-all`
Aviv Keshetb1238c32013-04-01 11:42:13 -07007
Aviv Keshetb1238c32013-04-01 11:42:13 -07008Simple script to be run inside the chroot. Used as a fast approximation of
9emerge-$board autotest-all, by simply rsync'ing changes from trunk to sysroot.
10"""
11
Mike Frysinger383367e2014-09-16 15:06:17 -040012from __future__ import print_function
13
Aviv Keshete7b20192013-04-24 14:05:53 -070014import argparse
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070015import glob
Aviv Keshetb1238c32013-04-01 11:42:13 -070016import os
Aviv Keshet787ffcd2013-04-08 15:14:56 -070017import re
Aviv Keshetb1238c32013-04-01 11:42:13 -070018import sys
Aviv Keshet787ffcd2013-04-08 15:14:56 -070019from collections import namedtuple
20
Aviv Keshetb7519e12016-10-04 00:50:00 -070021from chromite.lib import constants
Aviv Keshetb1238c32013-04-01 11:42:13 -070022from chromite.lib import cros_build_lib
Ralph Nathan91874ca2015-03-19 13:29:41 -070023from chromite.lib import cros_logging as logging
Aviv Keshetb1238c32013-04-01 11:42:13 -070024from chromite.lib import git
Aviv Keshet557e6882013-04-25 13:26:09 -070025from chromite.lib import osutils
Alex Deymo075c2292014-09-04 18:31:50 -070026from chromite.lib import portage_util
Aviv Keshetb1238c32013-04-01 11:42:13 -070027
Aviv Keshet940c17f2013-04-11 18:41:42 -070028if cros_build_lib.IsInsideChroot():
Mike Frysinger27e21b72018-07-12 14:20:21 -040029 # pylint: disable=import-error
Aviv Keshet940c17f2013-04-11 18:41:42 -070030 import portage
31
Mike Frysingere65f3752014-12-08 00:46:39 -050032
Mike Frysinger2c9d0612020-02-19 02:52:41 -050033assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
34
35
Aviv Keshetb1238c32013-04-01 11:42:13 -070036INCLUDE_PATTERNS_FILENAME = 'autotest-quickmerge-includepatterns'
37AUTOTEST_PROJECT_NAME = 'chromiumos/third_party/autotest'
Aviv Keshet5f3cf722013-05-09 17:35:25 -070038AUTOTEST_EBUILD = 'chromeos-base/autotest'
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070039DOWNGRADE_EBUILDS = ['chromeos-base/autotest']
Aviv Keshet787ffcd2013-04-08 15:14:56 -070040
Aviv Keshetc73cfc32013-06-14 16:18:53 -070041IGNORE_SUBDIRS = ['ExternalSource',
42 'logs',
43 'results',
44 'site-packages']
45
Aviv Keshet787ffcd2013-04-08 15:14:56 -070046# Data structure describing a single rsync filesystem change.
47#
48# change_description: An 11 character string, the rsync change description
49# for the particular file.
50# absolute_path: The absolute path of the created or modified file.
51ItemizedChange = namedtuple('ItemizedChange', ['change_description',
52 'absolute_path'])
53
Aviv Keshet787ffcd2013-04-08 15:14:56 -070054# Data structure describing the rsync new/modified files or directories.
55#
56# new_files: A list of ItemizedChange objects for new files.
57# modified_files: A list of ItemizedChange objects for modified files.
58# new_directories: A list of ItemizedChange objects for new directories.
59ItemizedChangeReport = namedtuple('ItemizedChangeReport',
60 ['new_files', 'modified_files',
61 'new_directories'])
62
Mike Frysingere65f3752014-12-08 00:46:39 -050063
Aviv Keshet84bdfc52013-06-04 13:19:38 -070064class PortagePackageAPIError(Exception):
65 """Exception thrown when unable to retrieve a portage package API."""
66
Aviv Keshet787ffcd2013-04-08 15:14:56 -070067
Aviv Keshet75d65962013-04-17 16:15:23 -070068def GetStalePackageNames(change_list, autotest_sysroot):
Aviv Keshete7b20192013-04-24 14:05:53 -070069 """Given a rsync change report, returns the names of stale test packages.
Aviv Keshet75d65962013-04-17 16:15:23 -070070
71 This function pulls out test package names for client-side tests, stored
72 within the client/site_tests directory tree, that had any files added or
73 modified and for whom any existing bzipped test packages may now be stale.
74
Mike Frysinger02e1e072013-11-10 22:11:34 -050075 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -070076 change_list: A list of ItemizedChange objects corresponding to changed
77 or modified files.
78 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -070079 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -070080
81 Returns:
82 A list of test package names, eg ['factory_Leds', 'login_UserPolicyKeys'].
83 May contain duplicate entries if multiple files within a test directory
84 were modified.
85 """
86 exp = os.path.abspath(autotest_sysroot) + r'/client/site_tests/(.*?)/.*'
87 matches = [re.match(exp, change.absolute_path) for change in change_list]
88 return [match.group(1) for match in matches if match]
89
90
Aviv Keshet787ffcd2013-04-08 15:14:56 -070091def ItemizeChangesFromRsyncOutput(rsync_output, destination_path):
92 """Convert the output of an rsync with `-i` to a ItemizedChangeReport object.
93
Mike Frysinger02e1e072013-11-10 22:11:34 -050094 Args:
Aviv Keshet787ffcd2013-04-08 15:14:56 -070095 rsync_output: String stdout of rsync command that was run with `-i` option.
96 destination_path: String absolute path of the destination directory for the
97 rsync operations. This argument is necessary because
98 rsync's output only gives the relative path of
99 touched/added files.
100
101 Returns:
102 ItemizedChangeReport object giving the absolute paths of files that were
103 created or modified by rsync.
104 """
105 modified_matches = re.findall(r'([.>]f[^+]{9}) (.*)', rsync_output)
106 new_matches = re.findall(r'(>f\+{9}) (.*)', rsync_output)
107 new_symlink_matches = re.findall(r'(cL\+{9}) (.*) -> .*', rsync_output)
108 new_dir_matches = re.findall(r'(cd\+{9}) (.*)', rsync_output)
109
110 absolute_modified = [ItemizedChange(c, os.path.join(destination_path, f))
111 for (c, f) in modified_matches]
112
113 # Note: new symlinks are treated as new files.
114 absolute_new = [ItemizedChange(c, os.path.join(destination_path, f))
115 for (c, f) in new_matches + new_symlink_matches]
116
117 absolute_new_dir = [ItemizedChange(c, os.path.join(destination_path, f))
118 for (c, f) in new_dir_matches]
119
120 return ItemizedChangeReport(new_files=absolute_new,
121 modified_files=absolute_modified,
122 new_directories=absolute_new_dir)
123
124
Aviv Keshete00caeb2013-04-17 14:03:25 -0700125def GetPackageAPI(portage_root, package_cp):
Aviv Keshete7b20192013-04-24 14:05:53 -0700126 """Gets portage API handles for the given package.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700127
Mike Frysinger02e1e072013-11-10 22:11:34 -0500128 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700129 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500130 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700131
132 Returns:
133 Returns (package, vartree) tuple, where
134 package is of type portage.dbapi.vartree.dblink
135 vartree is of type portage.dbapi.vartree.vartree
Aviv Keshet940c17f2013-04-11 18:41:42 -0700136 """
137 if portage_root is None:
Mike Frysingere65f3752014-12-08 00:46:39 -0500138 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700139 portage_root = portage.root
Aviv Keshet940c17f2013-04-11 18:41:42 -0700140 # Ensure that portage_root ends with trailing slash.
141 portage_root = os.path.join(portage_root, '')
142
Aviv Keshete7b20192013-04-24 14:05:53 -0700143 # Create a vartree object corresponding to portage_root.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700144 trees = portage.create_trees(portage_root, portage_root)
145 vartree = trees[portage_root]['vartree']
146
Aviv Keshete7b20192013-04-24 14:05:53 -0700147 # List the matching installed packages in cpv format.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700148 matching_packages = vartree.dbapi.cp_list(package_cp)
149
150 if not matching_packages:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700151 raise PortagePackageAPIError('No matching package for %s in portage_root '
152 '%s' % (package_cp, portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700153
154 if len(matching_packages) > 1:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700155 raise PortagePackageAPIError('Too many matching packages for %s in '
156 'portage_root %s' % (package_cp,
157 portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700158
Aviv Keshete7b20192013-04-24 14:05:53 -0700159 # Convert string match to package dblink.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700160 package_cpv = matching_packages[0]
Alex Deymo075c2292014-09-04 18:31:50 -0700161 package_split = portage_util.SplitCPV(package_cpv)
Mike Frysingere65f3752014-12-08 00:46:39 -0500162 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700163 package = portage.dblink(package_split.category,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700164 package_split.pv, settings=vartree.settings,
165 vartree=vartree)
166
Aviv Keshete00caeb2013-04-17 14:03:25 -0700167 return package, vartree
168
169
170def DowngradePackageVersion(portage_root, package_cp,
171 downgrade_to_version='0'):
Aviv Keshete7b20192013-04-24 14:05:53 -0700172 """Downgrade the specified portage package version.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700173
Mike Frysinger02e1e072013-11-10 22:11:34 -0500174 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700175 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500176 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700177 downgrade_to_version: String version to downgrade to. Default: '0'
178
179 Returns:
Aviv Keshet557e6882013-04-25 13:26:09 -0700180 True on success. False on failure (nonzero return code from `mv` command).
Aviv Keshete00caeb2013-04-17 14:03:25 -0700181 """
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700182 try:
183 package, _ = GetPackageAPI(portage_root, package_cp)
184 except PortagePackageAPIError:
185 # Unable to fetch a corresponding portage package API for this
186 # package_cp (either no such package, or name ambigious and matches).
187 # So, just fail out.
188 return False
Aviv Keshete00caeb2013-04-17 14:03:25 -0700189
190 source_directory = package.dbdir
191 destination_path = os.path.join(
192 package.dbroot, package_cp + '-' + downgrade_to_version)
193 if os.path.abspath(source_directory) == os.path.abspath(destination_path):
Aviv Keshet557e6882013-04-25 13:26:09 -0700194 return True
Aviv Keshete00caeb2013-04-17 14:03:25 -0700195 command = ['mv', source_directory, destination_path]
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500196 code = cros_build_lib.sudo_run(command, check=False).returncode
Aviv Keshet557e6882013-04-25 13:26:09 -0700197 return code == 0
Aviv Keshete00caeb2013-04-17 14:03:25 -0700198
199
Aviv Keshete7b20192013-04-24 14:05:53 -0700200def UpdatePackageContents(change_report, package_cp, portage_root=None):
201 """Add newly created files/directors to package contents.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700202
203 Given an ItemizedChangeReport, add the newly created files and directories
204 to the CONTENTS of an installed portage package, such that these files are
205 considered owned by that package.
206
Mike Frysinger02e1e072013-11-10 22:11:34 -0500207 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700208 change_report: ItemizedChangeReport object for the changes to be
209 made to the package.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700210 package_cp: A string similar to 'chromeos-base/autotest-tests' giving
211 the package category and name of the package to be altered.
212 portage_root: Portage root path, corresponding to the board that
213 we are working on. Defaults to '/'
214 """
215 package, vartree = GetPackageAPI(portage_root, package_cp)
216
Aviv Keshete7b20192013-04-24 14:05:53 -0700217 # Append new contents to package contents dictionary.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700218 contents = package.getcontents().copy()
219 for _, filename in change_report.new_files:
220 contents.setdefault(filename, (u'obj', '0', '0'))
221 for _, dirname in change_report.new_directories:
Aviv Keshete7b20192013-04-24 14:05:53 -0700222 # Strip trailing slashes if present.
223 contents.setdefault(dirname.rstrip('/'), (u'dir',))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700224
Aviv Keshete7b20192013-04-24 14:05:53 -0700225 # Write new contents dictionary to file.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700226 vartree.dbapi.writeContentsToContentsFile(package, contents)
227
228
Aviv Keshet19276752013-05-16 11:12:23 -0700229def RemoveBzipPackages(autotest_sysroot):
230 """Remove all bzipped test/dep/profiler packages from sysroot autotest.
Aviv Keshet75d65962013-04-17 16:15:23 -0700231
Mike Frysinger02e1e072013-11-10 22:11:34 -0500232 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700233 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700234 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700235 """
Aviv Keshet19276752013-05-16 11:12:23 -0700236 osutils.RmDir(os.path.join(autotest_sysroot, 'packages'),
Mike Frysingere65f3752014-12-08 00:46:39 -0500237 ignore_missing=True)
Aviv Keshet19276752013-05-16 11:12:23 -0700238 osutils.SafeUnlink(os.path.join(autotest_sysroot, 'packages.checksum'))
Aviv Keshet75d65962013-04-17 16:15:23 -0700239
240
Aviv Keshetb1238c32013-04-01 11:42:13 -0700241def RsyncQuickmerge(source_path, sysroot_autotest_path,
242 include_pattern_file=None, pretend=False,
Aviv Keshet60968ec2013-04-11 18:44:14 -0700243 overwrite=False):
Aviv Keshetb1238c32013-04-01 11:42:13 -0700244 """Run rsync quickmerge command, with specified arguments.
Aviv Keshete7b20192013-04-24 14:05:53 -0700245
Aviv Keshetb1238c32013-04-01 11:42:13 -0700246 Command will take form `rsync -a [options] --exclude=**.pyc
247 --exclude=**.pyo
Don Garrett25f309a2014-03-19 14:02:12 -0700248 [optional --include-from include_pattern_file]
Aviv Keshetb1238c32013-04-01 11:42:13 -0700249 --exclude=* [source_path] [sysroot_autotest_path]`
250
Mike Frysinger02e1e072013-11-10 22:11:34 -0500251 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700252 source_path: Directory to rsync from.
253 sysroot_autotest_path: Directory to rsync too.
254 include_pattern_file: Optional pattern of files to include in rsync.
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500255 pretend: True to use the '-n' option to rsync, to perform dry run.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700256 overwrite: True to omit '-u' option, overwrite all files in sysroot,
257 not just older files.
Aviv Keshet557e6882013-04-25 13:26:09 -0700258
259 Returns:
260 The cros_build_lib.CommandResult object resulting from the rsync command.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700261 """
262 command = ['rsync', '-a']
263
Prathmesh Prabhu137266a2014-02-11 20:02:18 -0800264 # For existing files, preserve destination permissions. This ensures that
265 # existing files end up with the file permissions set by the ebuilds.
266 # If this script copies over a file that does not exist in the destination
267 # tree, it will set the least restrictive permissions allowed in the
268 # destination tree. This could happen if the file copied is not installed by
269 # *any* ebuild, or if the ebuild that installs the file was never emerged.
270 command += ['--no-p', '--chmod=ugo=rwX']
271
Aviv Keshetb1238c32013-04-01 11:42:13 -0700272 if pretend:
273 command += ['-n']
274
275 if not overwrite:
276 command += ['-u']
277
Aviv Keshet60968ec2013-04-11 18:44:14 -0700278 command += ['-i']
Aviv Keshetb1238c32013-04-01 11:42:13 -0700279
280 command += ['--exclude=**.pyc']
281 command += ['--exclude=**.pyo']
282
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700283 # Exclude files with a specific substring in their name, because
284 # they create an ambiguous itemized report. (see unit test file for details)
285 command += ['--exclude=** -> *']
286
Aviv Keshetb1238c32013-04-01 11:42:13 -0700287 if include_pattern_file:
288 command += ['--include-from=%s' % include_pattern_file]
289
290 command += ['--exclude=*']
291
Po-Hsien Wang745ac352018-04-13 12:25:41 -0700292 # Some tests use symlinks. Follow these.
293 command += ['-L']
294
Aviv Keshetb1238c32013-04-01 11:42:13 -0700295 command += [source_path, sysroot_autotest_path]
296
Mike Frysinger13858562020-02-25 16:07:55 -0500297 return cros_build_lib.sudo_run(command, stdout=True, encoding='utf-8')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700298
299
300def ParseArguments(argv):
301 """Parse command line arguments
302
Mike Frysinger02e1e072013-11-10 22:11:34 -0500303 Returns:
304 parsed arguments.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700305 """
306 parser = argparse.ArgumentParser(description='Perform a fast approximation '
307 'to emerge-$board autotest-all, by '
308 'rsyncing source tree to sysroot.')
309
Aviv Keshet0a366a02013-07-18 10:52:04 -0700310 default_board = cros_build_lib.GetDefaultBoard()
311 parser.add_argument('--board', metavar='BOARD', default=default_board,
312 help='Board to perform quickmerge for. Default: ' +
313 (default_board or 'Not configured.'))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700314 parser.add_argument('--pretend', action='store_true',
315 help='Dry run only, do not modify sysroot autotest.')
316 parser.add_argument('--overwrite', action='store_true',
317 help='Overwrite existing files even if newer.')
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700318 parser.add_argument('--force', action='store_true',
Simran Basi8fc88992015-04-21 17:15:23 -0700319 help=argparse.SUPPRESS)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700320
Aviv Keshet474469d2013-07-22 12:54:52 -0700321 # Used only if test_that is calling autotest_quickmerge and has detected that
322 # the sysroot autotest path is still in usr/local/autotest (ie the build
323 # pre-dates https://chromium-review.googlesource.com/#/c/62880/ )
324 parser.add_argument('--legacy_path', action='store_true',
325 help=argparse.SUPPRESS)
326
Aviv Keshetb1238c32013-04-01 11:42:13 -0700327 return parser.parse_args(argv)
328
329
330def main(argv):
331 cros_build_lib.AssertInsideChroot()
332
333 args = ParseArguments(argv)
334
Aviv Keshete7b20192013-04-24 14:05:53 -0700335 if os.geteuid() != 0:
Aviv Keshet940c17f2013-04-11 18:41:42 -0700336 try:
Mike Frysinger45602c72019-09-22 02:15:11 -0400337 cros_build_lib.sudo_run([sys.executable] + sys.argv)
Aviv Keshet940c17f2013-04-11 18:41:42 -0700338 except cros_build_lib.RunCommandError:
339 return 1
340 return 0
341
Aviv Keshetb1238c32013-04-01 11:42:13 -0700342 if not args.board:
Mike Frysinger383367e2014-09-16 15:06:17 -0400343 print('No board specified. Aborting.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700344 return 1
345
346 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
David Jamese3b06062013-11-09 18:52:02 -0800347 checkout = manifest.FindCheckout(AUTOTEST_PROJECT_NAME)
Simran Basi348fccc2015-04-28 12:39:01 -0700348 brillo_autotest_src_path = os.path.join(checkout.GetPath(absolute=True), '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700349
350 script_path = os.path.dirname(__file__)
351 include_pattern_file = os.path.join(script_path, INCLUDE_PATTERNS_FILENAME)
352
353 # TODO: Determine the following string programatically.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700354 sysroot_path = os.path.join('/build', args.board, '')
Aviv Keshet474469d2013-07-22 12:54:52 -0700355 sysroot_autotest_path = os.path.join(sysroot_path,
356 constants.AUTOTEST_BUILD_PATH, '')
357 if args.legacy_path:
358 sysroot_autotest_path = os.path.join(sysroot_path, 'usr/local/autotest',
359 '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700360
Simran Basi348fccc2015-04-28 12:39:01 -0700361 # Generate the list of source paths to copy.
362 src_paths = {os.path.abspath(brillo_autotest_src_path)}
363 for quickmerge_file in glob.glob(os.path.join(sysroot_autotest_path,
364 'quickmerge', '*', '*')):
365 try:
366 path = osutils.ReadFile(quickmerge_file).strip()
367 if path and os.path.exists(path):
368 src_paths.add(os.path.abspath(path))
369 except IOError:
370 logging.error('Could not quickmerge for project: %s',
371 os.path.basename(quickmerge_file))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700372
Simran Basi348fccc2015-04-28 12:39:01 -0700373 num_new_files = 0
374 num_modified_files = 0
375 for src_path in src_paths:
376 rsync_output = RsyncQuickmerge(src_path +'/', sysroot_autotest_path,
377 include_pattern_file, args.pretend,
378 args.overwrite)
Aviv Keshete00caeb2013-04-17 14:03:25 -0700379
Simran Basi348fccc2015-04-28 12:39:01 -0700380 if args.verbose:
381 logging.info(rsync_output.output)
382 change_report = ItemizeChangesFromRsyncOutput(rsync_output.output,
383 sysroot_autotest_path)
384 num_new_files = num_new_files + len(change_report.new_files)
385 num_modified_files = num_modified_files + len(change_report.modified_files)
386 if not args.pretend:
387 logging.info('Updating portage database.')
388 UpdatePackageContents(change_report, AUTOTEST_EBUILD, sysroot_path)
Aviv Keshet60968ec2013-04-11 18:44:14 -0700389
Aviv Keshet940c17f2013-04-11 18:41:42 -0700390 if not args.pretend:
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700391 for logfile in glob.glob(os.path.join(sysroot_autotest_path, 'packages',
392 '*.log')):
393 try:
394 # Open file in a try-except block, for atomicity, instead of
395 # doing existence check.
396 with open(logfile, 'r') as f:
397 package_cp = f.readline().strip()
398 DOWNGRADE_EBUILDS.append(package_cp)
399 except IOError:
400 pass
401
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700402 for ebuild in DOWNGRADE_EBUILDS:
Aviv Keshet557e6882013-04-25 13:26:09 -0700403 if not DowngradePackageVersion(sysroot_path, ebuild):
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700404 logging.warning('Unable to downgrade package %s version number.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700405 ebuild)
Aviv Keshet19276752013-05-16 11:12:23 -0700406 RemoveBzipPackages(sysroot_autotest_path)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700407
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700408 sentinel_filename = os.path.join(sysroot_autotest_path,
409 '.quickmerge_sentinel')
Mike Frysinger45602c72019-09-22 02:15:11 -0400410 cros_build_lib.run(['touch', sentinel_filename])
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700411
Aviv Keshet940c17f2013-04-11 18:41:42 -0700412 if args.pretend:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700413 logging.info('The following message is pretend only. No filesystem '
Aviv Keshete7b20192013-04-24 14:05:53 -0700414 'changes made.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700415 logging.info('Quickmerge complete. Created or modified %s files.',
Simran Basi348fccc2015-04-28 12:39:01 -0700416 num_new_files + num_modified_files)
Aviv Keshete00caeb2013-04-17 14:03:25 -0700417
418 return 0