blob: 25c6695fcc0645394bb7d4d25ba37d15f7ba7fea [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():
29 # Only import portage after we've checked that we're inside the chroot.
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
Aviv Keshetb1238c32013-04-01 11:42:13 -070034INCLUDE_PATTERNS_FILENAME = 'autotest-quickmerge-includepatterns'
35AUTOTEST_PROJECT_NAME = 'chromiumos/third_party/autotest'
Aviv Keshet5f3cf722013-05-09 17:35:25 -070036AUTOTEST_EBUILD = 'chromeos-base/autotest'
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070037DOWNGRADE_EBUILDS = ['chromeos-base/autotest']
Aviv Keshet787ffcd2013-04-08 15:14:56 -070038
Aviv Keshetc73cfc32013-06-14 16:18:53 -070039IGNORE_SUBDIRS = ['ExternalSource',
40 'logs',
41 'results',
42 'site-packages']
43
Aviv Keshet787ffcd2013-04-08 15:14:56 -070044# Data structure describing a single rsync filesystem change.
45#
46# change_description: An 11 character string, the rsync change description
47# for the particular file.
48# absolute_path: The absolute path of the created or modified file.
49ItemizedChange = namedtuple('ItemizedChange', ['change_description',
50 'absolute_path'])
51
Aviv Keshet787ffcd2013-04-08 15:14:56 -070052# Data structure describing the rsync new/modified files or directories.
53#
54# new_files: A list of ItemizedChange objects for new files.
55# modified_files: A list of ItemizedChange objects for modified files.
56# new_directories: A list of ItemizedChange objects for new directories.
57ItemizedChangeReport = namedtuple('ItemizedChangeReport',
58 ['new_files', 'modified_files',
59 'new_directories'])
60
Mike Frysingere65f3752014-12-08 00:46:39 -050061
Aviv Keshet84bdfc52013-06-04 13:19:38 -070062class PortagePackageAPIError(Exception):
63 """Exception thrown when unable to retrieve a portage package API."""
64
Aviv Keshet787ffcd2013-04-08 15:14:56 -070065
Aviv Keshet75d65962013-04-17 16:15:23 -070066def GetStalePackageNames(change_list, autotest_sysroot):
Aviv Keshete7b20192013-04-24 14:05:53 -070067 """Given a rsync change report, returns the names of stale test packages.
Aviv Keshet75d65962013-04-17 16:15:23 -070068
69 This function pulls out test package names for client-side tests, stored
70 within the client/site_tests directory tree, that had any files added or
71 modified and for whom any existing bzipped test packages may now be stale.
72
Mike Frysinger02e1e072013-11-10 22:11:34 -050073 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -070074 change_list: A list of ItemizedChange objects corresponding to changed
75 or modified files.
76 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -070077 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -070078
79 Returns:
80 A list of test package names, eg ['factory_Leds', 'login_UserPolicyKeys'].
81 May contain duplicate entries if multiple files within a test directory
82 were modified.
83 """
84 exp = os.path.abspath(autotest_sysroot) + r'/client/site_tests/(.*?)/.*'
85 matches = [re.match(exp, change.absolute_path) for change in change_list]
86 return [match.group(1) for match in matches if match]
87
88
Aviv Keshet787ffcd2013-04-08 15:14:56 -070089def ItemizeChangesFromRsyncOutput(rsync_output, destination_path):
90 """Convert the output of an rsync with `-i` to a ItemizedChangeReport object.
91
Mike Frysinger02e1e072013-11-10 22:11:34 -050092 Args:
Aviv Keshet787ffcd2013-04-08 15:14:56 -070093 rsync_output: String stdout of rsync command that was run with `-i` option.
94 destination_path: String absolute path of the destination directory for the
95 rsync operations. This argument is necessary because
96 rsync's output only gives the relative path of
97 touched/added files.
98
99 Returns:
100 ItemizedChangeReport object giving the absolute paths of files that were
101 created or modified by rsync.
102 """
103 modified_matches = re.findall(r'([.>]f[^+]{9}) (.*)', rsync_output)
104 new_matches = re.findall(r'(>f\+{9}) (.*)', rsync_output)
105 new_symlink_matches = re.findall(r'(cL\+{9}) (.*) -> .*', rsync_output)
106 new_dir_matches = re.findall(r'(cd\+{9}) (.*)', rsync_output)
107
108 absolute_modified = [ItemizedChange(c, os.path.join(destination_path, f))
109 for (c, f) in modified_matches]
110
111 # Note: new symlinks are treated as new files.
112 absolute_new = [ItemizedChange(c, os.path.join(destination_path, f))
113 for (c, f) in new_matches + new_symlink_matches]
114
115 absolute_new_dir = [ItemizedChange(c, os.path.join(destination_path, f))
116 for (c, f) in new_dir_matches]
117
118 return ItemizedChangeReport(new_files=absolute_new,
119 modified_files=absolute_modified,
120 new_directories=absolute_new_dir)
121
122
Aviv Keshete00caeb2013-04-17 14:03:25 -0700123def GetPackageAPI(portage_root, package_cp):
Aviv Keshete7b20192013-04-24 14:05:53 -0700124 """Gets portage API handles for the given package.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700125
Mike Frysinger02e1e072013-11-10 22:11:34 -0500126 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700127 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500128 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700129
130 Returns:
131 Returns (package, vartree) tuple, where
132 package is of type portage.dbapi.vartree.dblink
133 vartree is of type portage.dbapi.vartree.vartree
Aviv Keshet940c17f2013-04-11 18:41:42 -0700134 """
135 if portage_root is None:
Mike Frysingere65f3752014-12-08 00:46:39 -0500136 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700137 portage_root = portage.root
Aviv Keshet940c17f2013-04-11 18:41:42 -0700138 # Ensure that portage_root ends with trailing slash.
139 portage_root = os.path.join(portage_root, '')
140
Aviv Keshete7b20192013-04-24 14:05:53 -0700141 # Create a vartree object corresponding to portage_root.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700142 trees = portage.create_trees(portage_root, portage_root)
143 vartree = trees[portage_root]['vartree']
144
Aviv Keshete7b20192013-04-24 14:05:53 -0700145 # List the matching installed packages in cpv format.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700146 matching_packages = vartree.dbapi.cp_list(package_cp)
147
148 if not matching_packages:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700149 raise PortagePackageAPIError('No matching package for %s in portage_root '
150 '%s' % (package_cp, portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700151
152 if len(matching_packages) > 1:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700153 raise PortagePackageAPIError('Too many matching packages for %s in '
154 'portage_root %s' % (package_cp,
155 portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700156
Aviv Keshete7b20192013-04-24 14:05:53 -0700157 # Convert string match to package dblink.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700158 package_cpv = matching_packages[0]
Alex Deymo075c2292014-09-04 18:31:50 -0700159 package_split = portage_util.SplitCPV(package_cpv)
Mike Frysingere65f3752014-12-08 00:46:39 -0500160 # pylint: disable=no-member
Aviv Keshete7b20192013-04-24 14:05:53 -0700161 package = portage.dblink(package_split.category,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700162 package_split.pv, settings=vartree.settings,
163 vartree=vartree)
164
Aviv Keshete00caeb2013-04-17 14:03:25 -0700165 return package, vartree
166
167
168def DowngradePackageVersion(portage_root, package_cp,
169 downgrade_to_version='0'):
Aviv Keshete7b20192013-04-24 14:05:53 -0700170 """Downgrade the specified portage package version.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700171
Mike Frysinger02e1e072013-11-10 22:11:34 -0500172 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700173 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500174 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700175 downgrade_to_version: String version to downgrade to. Default: '0'
176
177 Returns:
Aviv Keshet557e6882013-04-25 13:26:09 -0700178 True on success. False on failure (nonzero return code from `mv` command).
Aviv Keshete00caeb2013-04-17 14:03:25 -0700179 """
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700180 try:
181 package, _ = GetPackageAPI(portage_root, package_cp)
182 except PortagePackageAPIError:
183 # Unable to fetch a corresponding portage package API for this
184 # package_cp (either no such package, or name ambigious and matches).
185 # So, just fail out.
186 return False
Aviv Keshete00caeb2013-04-17 14:03:25 -0700187
188 source_directory = package.dbdir
189 destination_path = os.path.join(
190 package.dbroot, package_cp + '-' + downgrade_to_version)
191 if os.path.abspath(source_directory) == os.path.abspath(destination_path):
Aviv Keshet557e6882013-04-25 13:26:09 -0700192 return True
Aviv Keshete00caeb2013-04-17 14:03:25 -0700193 command = ['mv', source_directory, destination_path]
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500194 code = cros_build_lib.sudo_run(command, check=False).returncode
Aviv Keshet557e6882013-04-25 13:26:09 -0700195 return code == 0
Aviv Keshete00caeb2013-04-17 14:03:25 -0700196
197
Aviv Keshete7b20192013-04-24 14:05:53 -0700198def UpdatePackageContents(change_report, package_cp, portage_root=None):
199 """Add newly created files/directors to package contents.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700200
201 Given an ItemizedChangeReport, add the newly created files and directories
202 to the CONTENTS of an installed portage package, such that these files are
203 considered owned by that package.
204
Mike Frysinger02e1e072013-11-10 22:11:34 -0500205 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700206 change_report: ItemizedChangeReport object for the changes to be
207 made to the package.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700208 package_cp: A string similar to 'chromeos-base/autotest-tests' giving
209 the package category and name of the package to be altered.
210 portage_root: Portage root path, corresponding to the board that
211 we are working on. Defaults to '/'
212 """
213 package, vartree = GetPackageAPI(portage_root, package_cp)
214
Aviv Keshete7b20192013-04-24 14:05:53 -0700215 # Append new contents to package contents dictionary.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700216 contents = package.getcontents().copy()
217 for _, filename in change_report.new_files:
218 contents.setdefault(filename, (u'obj', '0', '0'))
219 for _, dirname in change_report.new_directories:
Aviv Keshete7b20192013-04-24 14:05:53 -0700220 # Strip trailing slashes if present.
221 contents.setdefault(dirname.rstrip('/'), (u'dir',))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700222
Aviv Keshete7b20192013-04-24 14:05:53 -0700223 # Write new contents dictionary to file.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700224 vartree.dbapi.writeContentsToContentsFile(package, contents)
225
226
Aviv Keshet19276752013-05-16 11:12:23 -0700227def RemoveBzipPackages(autotest_sysroot):
228 """Remove all bzipped test/dep/profiler packages from sysroot autotest.
Aviv Keshet75d65962013-04-17 16:15:23 -0700229
Mike Frysinger02e1e072013-11-10 22:11:34 -0500230 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700231 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700232 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700233 """
Aviv Keshet19276752013-05-16 11:12:23 -0700234 osutils.RmDir(os.path.join(autotest_sysroot, 'packages'),
Mike Frysingere65f3752014-12-08 00:46:39 -0500235 ignore_missing=True)
Aviv Keshet19276752013-05-16 11:12:23 -0700236 osutils.SafeUnlink(os.path.join(autotest_sysroot, 'packages.checksum'))
Aviv Keshet75d65962013-04-17 16:15:23 -0700237
238
Aviv Keshetb1238c32013-04-01 11:42:13 -0700239def RsyncQuickmerge(source_path, sysroot_autotest_path,
240 include_pattern_file=None, pretend=False,
Aviv Keshet60968ec2013-04-11 18:44:14 -0700241 overwrite=False):
Aviv Keshetb1238c32013-04-01 11:42:13 -0700242 """Run rsync quickmerge command, with specified arguments.
Aviv Keshete7b20192013-04-24 14:05:53 -0700243
Aviv Keshetb1238c32013-04-01 11:42:13 -0700244 Command will take form `rsync -a [options] --exclude=**.pyc
245 --exclude=**.pyo
Don Garrett25f309a2014-03-19 14:02:12 -0700246 [optional --include-from include_pattern_file]
Aviv Keshetb1238c32013-04-01 11:42:13 -0700247 --exclude=* [source_path] [sysroot_autotest_path]`
248
Mike Frysinger02e1e072013-11-10 22:11:34 -0500249 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700250 source_path: Directory to rsync from.
251 sysroot_autotest_path: Directory to rsync too.
252 include_pattern_file: Optional pattern of files to include in rsync.
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500253 pretend: True to use the '-n' option to rsync, to perform dry run.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700254 overwrite: True to omit '-u' option, overwrite all files in sysroot,
255 not just older files.
Aviv Keshet557e6882013-04-25 13:26:09 -0700256
257 Returns:
258 The cros_build_lib.CommandResult object resulting from the rsync command.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700259 """
260 command = ['rsync', '-a']
261
Prathmesh Prabhu137266a2014-02-11 20:02:18 -0800262 # For existing files, preserve destination permissions. This ensures that
263 # existing files end up with the file permissions set by the ebuilds.
264 # If this script copies over a file that does not exist in the destination
265 # tree, it will set the least restrictive permissions allowed in the
266 # destination tree. This could happen if the file copied is not installed by
267 # *any* ebuild, or if the ebuild that installs the file was never emerged.
268 command += ['--no-p', '--chmod=ugo=rwX']
269
Aviv Keshetb1238c32013-04-01 11:42:13 -0700270 if pretend:
271 command += ['-n']
272
273 if not overwrite:
274 command += ['-u']
275
Aviv Keshet60968ec2013-04-11 18:44:14 -0700276 command += ['-i']
Aviv Keshetb1238c32013-04-01 11:42:13 -0700277
278 command += ['--exclude=**.pyc']
279 command += ['--exclude=**.pyo']
280
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700281 # Exclude files with a specific substring in their name, because
282 # they create an ambiguous itemized report. (see unit test file for details)
283 command += ['--exclude=** -> *']
284
Aviv Keshetb1238c32013-04-01 11:42:13 -0700285 if include_pattern_file:
286 command += ['--include-from=%s' % include_pattern_file]
287
288 command += ['--exclude=*']
289
Po-Hsien Wang745ac352018-04-13 12:25:41 -0700290 # Some tests use symlinks. Follow these.
291 command += ['-L']
292
Aviv Keshetb1238c32013-04-01 11:42:13 -0700293 command += [source_path, sysroot_autotest_path]
294
Mike Frysinger45602c72019-09-22 02:15:11 -0400295 return cros_build_lib.sudo_run(command, redirect_stdout=True)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700296
297
298def ParseArguments(argv):
299 """Parse command line arguments
300
Mike Frysinger02e1e072013-11-10 22:11:34 -0500301 Returns:
302 parsed arguments.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700303 """
304 parser = argparse.ArgumentParser(description='Perform a fast approximation '
305 'to emerge-$board autotest-all, by '
306 'rsyncing source tree to sysroot.')
307
Aviv Keshet0a366a02013-07-18 10:52:04 -0700308 default_board = cros_build_lib.GetDefaultBoard()
309 parser.add_argument('--board', metavar='BOARD', default=default_board,
310 help='Board to perform quickmerge for. Default: ' +
311 (default_board or 'Not configured.'))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700312 parser.add_argument('--pretend', action='store_true',
313 help='Dry run only, do not modify sysroot autotest.')
314 parser.add_argument('--overwrite', action='store_true',
315 help='Overwrite existing files even if newer.')
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700316 parser.add_argument('--force', action='store_true',
Simran Basi8fc88992015-04-21 17:15:23 -0700317 help=argparse.SUPPRESS)
Aviv Keshete00caeb2013-04-17 14:03:25 -0700318 parser.add_argument('--verbose', action='store_true',
319 help='Print detailed change report.')
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