blob: 850f3a4c281b370da3c7016e8b305a4512226e54 [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
Alex Klein727e3202020-05-29 11:13:55 -060021from chromite.lib import commandline
Aviv Keshetb7519e12016-10-04 00:50:00 -070022from chromite.lib import constants
Aviv Keshetb1238c32013-04-01 11:42:13 -070023from chromite.lib import cros_build_lib
Ralph Nathan91874ca2015-03-19 13:29:41 -070024from chromite.lib import cros_logging as logging
Aviv Keshetb1238c32013-04-01 11:42:13 -070025from chromite.lib import git
Aviv Keshet557e6882013-04-25 13:26:09 -070026from chromite.lib import osutils
Alex Klein18a60af2020-06-11 12:08:47 -060027from chromite.lib.parser import package_info
Aviv Keshetb1238c32013-04-01 11:42:13 -070028
Aviv Keshet940c17f2013-04-11 18:41:42 -070029if cros_build_lib.IsInsideChroot():
Mike Frysinger27e21b72018-07-12 14:20:21 -040030 # pylint: disable=import-error
Aviv Keshet940c17f2013-04-11 18:41:42 -070031 import portage
32
Mike Frysingere65f3752014-12-08 00:46:39 -050033
Mike Frysinger2c9d0612020-02-19 02:52:41 -050034assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
35
36
Aviv Keshetb1238c32013-04-01 11:42:13 -070037INCLUDE_PATTERNS_FILENAME = 'autotest-quickmerge-includepatterns'
38AUTOTEST_PROJECT_NAME = 'chromiumos/third_party/autotest'
Aviv Keshet5f3cf722013-05-09 17:35:25 -070039AUTOTEST_EBUILD = 'chromeos-base/autotest'
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070040DOWNGRADE_EBUILDS = ['chromeos-base/autotest']
Aviv Keshet787ffcd2013-04-08 15:14:56 -070041
Aviv Keshetc73cfc32013-06-14 16:18:53 -070042IGNORE_SUBDIRS = ['ExternalSource',
43 'logs',
44 'results',
45 'site-packages']
46
Aviv Keshet787ffcd2013-04-08 15:14:56 -070047# Data structure describing a single rsync filesystem change.
48#
49# change_description: An 11 character string, the rsync change description
50# for the particular file.
51# absolute_path: The absolute path of the created or modified file.
52ItemizedChange = namedtuple('ItemizedChange', ['change_description',
53 'absolute_path'])
54
Aviv Keshet787ffcd2013-04-08 15:14:56 -070055# Data structure describing the rsync new/modified files or directories.
56#
57# new_files: A list of ItemizedChange objects for new files.
58# modified_files: A list of ItemizedChange objects for modified files.
59# new_directories: A list of ItemizedChange objects for new directories.
60ItemizedChangeReport = namedtuple('ItemizedChangeReport',
61 ['new_files', 'modified_files',
62 'new_directories'])
63
Mike Frysingere65f3752014-12-08 00:46:39 -050064
Aviv Keshet84bdfc52013-06-04 13:19:38 -070065class PortagePackageAPIError(Exception):
66 """Exception thrown when unable to retrieve a portage package API."""
67
Aviv Keshet787ffcd2013-04-08 15:14:56 -070068
Aviv Keshet75d65962013-04-17 16:15:23 -070069def GetStalePackageNames(change_list, autotest_sysroot):
Aviv Keshete7b20192013-04-24 14:05:53 -070070 """Given a rsync change report, returns the names of stale test packages.
Aviv Keshet75d65962013-04-17 16:15:23 -070071
72 This function pulls out test package names for client-side tests, stored
73 within the client/site_tests directory tree, that had any files added or
74 modified and for whom any existing bzipped test packages may now be stale.
75
Mike Frysinger02e1e072013-11-10 22:11:34 -050076 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -070077 change_list: A list of ItemizedChange objects corresponding to changed
78 or modified files.
79 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -070080 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -070081
82 Returns:
83 A list of test package names, eg ['factory_Leds', 'login_UserPolicyKeys'].
84 May contain duplicate entries if multiple files within a test directory
85 were modified.
86 """
87 exp = os.path.abspath(autotest_sysroot) + r'/client/site_tests/(.*?)/.*'
88 matches = [re.match(exp, change.absolute_path) for change in change_list]
89 return [match.group(1) for match in matches if match]
90
91
Aviv Keshet787ffcd2013-04-08 15:14:56 -070092def ItemizeChangesFromRsyncOutput(rsync_output, destination_path):
93 """Convert the output of an rsync with `-i` to a ItemizedChangeReport object.
94
Mike Frysinger02e1e072013-11-10 22:11:34 -050095 Args:
Aviv Keshet787ffcd2013-04-08 15:14:56 -070096 rsync_output: String stdout of rsync command that was run with `-i` option.
97 destination_path: String absolute path of the destination directory for the
98 rsync operations. This argument is necessary because
99 rsync's output only gives the relative path of
100 touched/added files.
101
102 Returns:
103 ItemizedChangeReport object giving the absolute paths of files that were
104 created or modified by rsync.
105 """
106 modified_matches = re.findall(r'([.>]f[^+]{9}) (.*)', rsync_output)
107 new_matches = re.findall(r'(>f\+{9}) (.*)', rsync_output)
108 new_symlink_matches = re.findall(r'(cL\+{9}) (.*) -> .*', rsync_output)
109 new_dir_matches = re.findall(r'(cd\+{9}) (.*)', rsync_output)
110
111 absolute_modified = [ItemizedChange(c, os.path.join(destination_path, f))
112 for (c, f) in modified_matches]
113
114 # Note: new symlinks are treated as new files.
115 absolute_new = [ItemizedChange(c, os.path.join(destination_path, f))
116 for (c, f) in new_matches + new_symlink_matches]
117
118 absolute_new_dir = [ItemizedChange(c, os.path.join(destination_path, f))
119 for (c, f) in new_dir_matches]
120
121 return ItemizedChangeReport(new_files=absolute_new,
122 modified_files=absolute_modified,
123 new_directories=absolute_new_dir)
124
125
Aviv Keshete00caeb2013-04-17 14:03:25 -0700126def GetPackageAPI(portage_root, package_cp):
Aviv Keshete7b20192013-04-24 14:05:53 -0700127 """Gets portage API handles for the given package.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700128
Mike Frysinger02e1e072013-11-10 22:11:34 -0500129 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700130 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500131 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700132
133 Returns:
134 Returns (package, vartree) tuple, where
135 package is of type portage.dbapi.vartree.dblink
136 vartree is of type portage.dbapi.vartree.vartree
Aviv Keshet940c17f2013-04-11 18:41:42 -0700137 """
138 if portage_root is None:
Mike Frysingere65f3752014-12-08 00:46:39 -0500139 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700140 portage_root = portage.root
Aviv Keshet940c17f2013-04-11 18:41:42 -0700141 # Ensure that portage_root ends with trailing slash.
142 portage_root = os.path.join(portage_root, '')
143
Aviv Keshete7b20192013-04-24 14:05:53 -0700144 # Create a vartree object corresponding to portage_root.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700145 trees = portage.create_trees(portage_root, portage_root)
146 vartree = trees[portage_root]['vartree']
147
Aviv Keshete7b20192013-04-24 14:05:53 -0700148 # List the matching installed packages in cpv format.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700149 matching_packages = vartree.dbapi.cp_list(package_cp)
150
151 if not matching_packages:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700152 raise PortagePackageAPIError('No matching package for %s in portage_root '
153 '%s' % (package_cp, portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700154
155 if len(matching_packages) > 1:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700156 raise PortagePackageAPIError('Too many matching packages for %s in '
157 'portage_root %s' % (package_cp,
158 portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700159
Aviv Keshete7b20192013-04-24 14:05:53 -0700160 # Convert string match to package dblink.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700161 package_cpv = matching_packages[0]
Alex Klein18a60af2020-06-11 12:08:47 -0600162 package_split = package_info.SplitCPV(package_cpv)
Mike Frysingere65f3752014-12-08 00:46:39 -0500163 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700164 package = portage.dblink(package_split.category,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700165 package_split.pv, settings=vartree.settings,
166 vartree=vartree)
167
Aviv Keshete00caeb2013-04-17 14:03:25 -0700168 return package, vartree
169
170
171def DowngradePackageVersion(portage_root, package_cp,
172 downgrade_to_version='0'):
Aviv Keshete7b20192013-04-24 14:05:53 -0700173 """Downgrade the specified portage package version.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700174
Mike Frysinger02e1e072013-11-10 22:11:34 -0500175 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700176 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500177 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700178 downgrade_to_version: String version to downgrade to. Default: '0'
179
180 Returns:
Aviv Keshet557e6882013-04-25 13:26:09 -0700181 True on success. False on failure (nonzero return code from `mv` command).
Aviv Keshete00caeb2013-04-17 14:03:25 -0700182 """
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700183 try:
184 package, _ = GetPackageAPI(portage_root, package_cp)
185 except PortagePackageAPIError:
186 # Unable to fetch a corresponding portage package API for this
187 # package_cp (either no such package, or name ambigious and matches).
188 # So, just fail out.
189 return False
Aviv Keshete00caeb2013-04-17 14:03:25 -0700190
191 source_directory = package.dbdir
192 destination_path = os.path.join(
193 package.dbroot, package_cp + '-' + downgrade_to_version)
194 if os.path.abspath(source_directory) == os.path.abspath(destination_path):
Aviv Keshet557e6882013-04-25 13:26:09 -0700195 return True
Aviv Keshete00caeb2013-04-17 14:03:25 -0700196 command = ['mv', source_directory, destination_path]
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500197 code = cros_build_lib.sudo_run(command, check=False).returncode
Aviv Keshet557e6882013-04-25 13:26:09 -0700198 return code == 0
Aviv Keshete00caeb2013-04-17 14:03:25 -0700199
200
Aviv Keshete7b20192013-04-24 14:05:53 -0700201def UpdatePackageContents(change_report, package_cp, portage_root=None):
202 """Add newly created files/directors to package contents.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700203
204 Given an ItemizedChangeReport, add the newly created files and directories
205 to the CONTENTS of an installed portage package, such that these files are
206 considered owned by that package.
207
Mike Frysinger02e1e072013-11-10 22:11:34 -0500208 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700209 change_report: ItemizedChangeReport object for the changes to be
210 made to the package.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700211 package_cp: A string similar to 'chromeos-base/autotest-tests' giving
212 the package category and name of the package to be altered.
213 portage_root: Portage root path, corresponding to the board that
214 we are working on. Defaults to '/'
215 """
216 package, vartree = GetPackageAPI(portage_root, package_cp)
217
Aviv Keshete7b20192013-04-24 14:05:53 -0700218 # Append new contents to package contents dictionary.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700219 contents = package.getcontents().copy()
220 for _, filename in change_report.new_files:
221 contents.setdefault(filename, (u'obj', '0', '0'))
222 for _, dirname in change_report.new_directories:
Aviv Keshete7b20192013-04-24 14:05:53 -0700223 # Strip trailing slashes if present.
224 contents.setdefault(dirname.rstrip('/'), (u'dir',))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700225
Aviv Keshete7b20192013-04-24 14:05:53 -0700226 # Write new contents dictionary to file.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700227 vartree.dbapi.writeContentsToContentsFile(package, contents)
228
229
Aviv Keshet19276752013-05-16 11:12:23 -0700230def RemoveBzipPackages(autotest_sysroot):
231 """Remove all bzipped test/dep/profiler packages from sysroot autotest.
Aviv Keshet75d65962013-04-17 16:15:23 -0700232
Mike Frysinger02e1e072013-11-10 22:11:34 -0500233 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700234 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700235 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700236 """
Aviv Keshet19276752013-05-16 11:12:23 -0700237 osutils.RmDir(os.path.join(autotest_sysroot, 'packages'),
Mike Frysingere65f3752014-12-08 00:46:39 -0500238 ignore_missing=True)
Aviv Keshet19276752013-05-16 11:12:23 -0700239 osutils.SafeUnlink(os.path.join(autotest_sysroot, 'packages.checksum'))
Aviv Keshet75d65962013-04-17 16:15:23 -0700240
241
Aviv Keshetb1238c32013-04-01 11:42:13 -0700242def RsyncQuickmerge(source_path, sysroot_autotest_path,
243 include_pattern_file=None, pretend=False,
Aviv Keshet60968ec2013-04-11 18:44:14 -0700244 overwrite=False):
Aviv Keshetb1238c32013-04-01 11:42:13 -0700245 """Run rsync quickmerge command, with specified arguments.
Aviv Keshete7b20192013-04-24 14:05:53 -0700246
Aviv Keshetb1238c32013-04-01 11:42:13 -0700247 Command will take form `rsync -a [options] --exclude=**.pyc
248 --exclude=**.pyo
Don Garrett25f309a2014-03-19 14:02:12 -0700249 [optional --include-from include_pattern_file]
Aviv Keshetb1238c32013-04-01 11:42:13 -0700250 --exclude=* [source_path] [sysroot_autotest_path]`
251
Mike Frysinger02e1e072013-11-10 22:11:34 -0500252 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700253 source_path: Directory to rsync from.
254 sysroot_autotest_path: Directory to rsync too.
255 include_pattern_file: Optional pattern of files to include in rsync.
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500256 pretend: True to use the '-n' option to rsync, to perform dry run.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700257 overwrite: True to omit '-u' option, overwrite all files in sysroot,
258 not just older files.
Aviv Keshet557e6882013-04-25 13:26:09 -0700259
260 Returns:
261 The cros_build_lib.CommandResult object resulting from the rsync command.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700262 """
263 command = ['rsync', '-a']
264
Prathmesh Prabhu137266a2014-02-11 20:02:18 -0800265 # For existing files, preserve destination permissions. This ensures that
266 # existing files end up with the file permissions set by the ebuilds.
267 # If this script copies over a file that does not exist in the destination
268 # tree, it will set the least restrictive permissions allowed in the
269 # destination tree. This could happen if the file copied is not installed by
270 # *any* ebuild, or if the ebuild that installs the file was never emerged.
271 command += ['--no-p', '--chmod=ugo=rwX']
272
Aviv Keshetb1238c32013-04-01 11:42:13 -0700273 if pretend:
274 command += ['-n']
275
276 if not overwrite:
277 command += ['-u']
278
Aviv Keshet60968ec2013-04-11 18:44:14 -0700279 command += ['-i']
Aviv Keshetb1238c32013-04-01 11:42:13 -0700280
281 command += ['--exclude=**.pyc']
282 command += ['--exclude=**.pyo']
283
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700284 # Exclude files with a specific substring in their name, because
285 # they create an ambiguous itemized report. (see unit test file for details)
286 command += ['--exclude=** -> *']
287
Aviv Keshetb1238c32013-04-01 11:42:13 -0700288 if include_pattern_file:
289 command += ['--include-from=%s' % include_pattern_file]
290
291 command += ['--exclude=*']
292
Po-Hsien Wang745ac352018-04-13 12:25:41 -0700293 # Some tests use symlinks. Follow these.
294 command += ['-L']
295
Aviv Keshetb1238c32013-04-01 11:42:13 -0700296 command += [source_path, sysroot_autotest_path]
297
Mike Frysinger13858562020-02-25 16:07:55 -0500298 return cros_build_lib.sudo_run(command, stdout=True, encoding='utf-8')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700299
300
301def ParseArguments(argv):
302 """Parse command line arguments
303
Mike Frysinger02e1e072013-11-10 22:11:34 -0500304 Returns:
305 parsed arguments.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700306 """
Alex Klein727e3202020-05-29 11:13:55 -0600307 parser = commandline.ArgumentParser(
308 description='Perform a fast approximation to emerge-$board '
309 'autotest-all, by rsyncing source tree to sysroot.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700310
Aviv Keshet0a366a02013-07-18 10:52:04 -0700311 default_board = cros_build_lib.GetDefaultBoard()
312 parser.add_argument('--board', metavar='BOARD', default=default_board,
313 help='Board to perform quickmerge for. Default: ' +
314 (default_board or 'Not configured.'))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700315 parser.add_argument('--pretend', action='store_true',
316 help='Dry run only, do not modify sysroot autotest.')
317 parser.add_argument('--overwrite', action='store_true',
318 help='Overwrite existing files even if newer.')
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700319 parser.add_argument('--force', action='store_true',
Simran Basi8fc88992015-04-21 17:15:23 -0700320 help=argparse.SUPPRESS)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700321
Aviv Keshet474469d2013-07-22 12:54:52 -0700322 # Used only if test_that is calling autotest_quickmerge and has detected that
323 # the sysroot autotest path is still in usr/local/autotest (ie the build
324 # pre-dates https://chromium-review.googlesource.com/#/c/62880/ )
325 parser.add_argument('--legacy_path', action='store_true',
326 help=argparse.SUPPRESS)
327
Aviv Keshetb1238c32013-04-01 11:42:13 -0700328 return parser.parse_args(argv)
329
330
331def main(argv):
332 cros_build_lib.AssertInsideChroot()
333
334 args = ParseArguments(argv)
335
Aviv Keshete7b20192013-04-24 14:05:53 -0700336 if os.geteuid() != 0:
Aviv Keshet940c17f2013-04-11 18:41:42 -0700337 try:
Mike Frysinger45602c72019-09-22 02:15:11 -0400338 cros_build_lib.sudo_run([sys.executable] + sys.argv)
Aviv Keshet940c17f2013-04-11 18:41:42 -0700339 except cros_build_lib.RunCommandError:
340 return 1
341 return 0
342
Aviv Keshetb1238c32013-04-01 11:42:13 -0700343 if not args.board:
Mike Frysinger383367e2014-09-16 15:06:17 -0400344 print('No board specified. Aborting.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700345 return 1
346
347 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
David Jamese3b06062013-11-09 18:52:02 -0800348 checkout = manifest.FindCheckout(AUTOTEST_PROJECT_NAME)
Simran Basi348fccc2015-04-28 12:39:01 -0700349 brillo_autotest_src_path = os.path.join(checkout.GetPath(absolute=True), '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700350
351 script_path = os.path.dirname(__file__)
352 include_pattern_file = os.path.join(script_path, INCLUDE_PATTERNS_FILENAME)
353
354 # TODO: Determine the following string programatically.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700355 sysroot_path = os.path.join('/build', args.board, '')
Aviv Keshet474469d2013-07-22 12:54:52 -0700356 sysroot_autotest_path = os.path.join(sysroot_path,
357 constants.AUTOTEST_BUILD_PATH, '')
358 if args.legacy_path:
359 sysroot_autotest_path = os.path.join(sysroot_path, 'usr/local/autotest',
360 '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700361
Simran Basi348fccc2015-04-28 12:39:01 -0700362 # Generate the list of source paths to copy.
363 src_paths = {os.path.abspath(brillo_autotest_src_path)}
364 for quickmerge_file in glob.glob(os.path.join(sysroot_autotest_path,
365 'quickmerge', '*', '*')):
366 try:
367 path = osutils.ReadFile(quickmerge_file).strip()
368 if path and os.path.exists(path):
369 src_paths.add(os.path.abspath(path))
370 except IOError:
371 logging.error('Could not quickmerge for project: %s',
372 os.path.basename(quickmerge_file))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700373
Simran Basi348fccc2015-04-28 12:39:01 -0700374 num_new_files = 0
375 num_modified_files = 0
376 for src_path in src_paths:
377 rsync_output = RsyncQuickmerge(src_path +'/', sysroot_autotest_path,
378 include_pattern_file, args.pretend,
379 args.overwrite)
Aviv Keshete00caeb2013-04-17 14:03:25 -0700380
Simran Basi348fccc2015-04-28 12:39:01 -0700381 if args.verbose:
382 logging.info(rsync_output.output)
383 change_report = ItemizeChangesFromRsyncOutput(rsync_output.output,
384 sysroot_autotest_path)
385 num_new_files = num_new_files + len(change_report.new_files)
386 num_modified_files = num_modified_files + len(change_report.modified_files)
387 if not args.pretend:
388 logging.info('Updating portage database.')
389 UpdatePackageContents(change_report, AUTOTEST_EBUILD, sysroot_path)
Aviv Keshet60968ec2013-04-11 18:44:14 -0700390
Aviv Keshet940c17f2013-04-11 18:41:42 -0700391 if not args.pretend:
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700392 for logfile in glob.glob(os.path.join(sysroot_autotest_path, 'packages',
393 '*.log')):
394 try:
395 # Open file in a try-except block, for atomicity, instead of
396 # doing existence check.
397 with open(logfile, 'r') as f:
398 package_cp = f.readline().strip()
399 DOWNGRADE_EBUILDS.append(package_cp)
400 except IOError:
401 pass
402
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700403 for ebuild in DOWNGRADE_EBUILDS:
Aviv Keshet557e6882013-04-25 13:26:09 -0700404 if not DowngradePackageVersion(sysroot_path, ebuild):
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700405 logging.warning('Unable to downgrade package %s version number.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700406 ebuild)
Aviv Keshet19276752013-05-16 11:12:23 -0700407 RemoveBzipPackages(sysroot_autotest_path)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700408
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700409 sentinel_filename = os.path.join(sysroot_autotest_path,
410 '.quickmerge_sentinel')
Mike Frysinger45602c72019-09-22 02:15:11 -0400411 cros_build_lib.run(['touch', sentinel_filename])
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700412
Aviv Keshet940c17f2013-04-11 18:41:42 -0700413 if args.pretend:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700414 logging.info('The following message is pretend only. No filesystem '
Aviv Keshete7b20192013-04-24 14:05:53 -0700415 'changes made.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700416 logging.info('Quickmerge complete. Created or modified %s files.',
Simran Basi348fccc2015-04-28 12:39:01 -0700417 num_new_files + num_modified_files)
Aviv Keshete00caeb2013-04-17 14:03:25 -0700418
419 return 0