blob: 80bce3cb755b18a8ad42f4bf3b44c3ff744c7f5a [file] [log] [blame]
Aviv Keshetb1238c32013-04-01 11:42:13 -07001# Copyright (c) 2013 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
Mike Frysingerad8c6ca2014-02-03 11:28:45 -05005"""Fast alternative to `emerge-$BOARD autotest-all`
Aviv Keshetb1238c32013-04-01 11:42:13 -07006
Aviv Keshetb1238c32013-04-01 11:42:13 -07007Simple script to be run inside the chroot. Used as a fast approximation of
8emerge-$board autotest-all, by simply rsync'ing changes from trunk to sysroot.
9"""
10
Mike Frysinger383367e2014-09-16 15:06:17 -040011from __future__ import print_function
12
Aviv Keshete7b20192013-04-24 14:05:53 -070013import argparse
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070014import glob
Aviv Keshete00caeb2013-04-17 14:03:25 -070015import logging
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
Don Garrett88b8d782014-05-13 17:30:55 -070021from chromite.cbuildbot import constants
Aviv Keshetb1238c32013-04-01 11:42:13 -070022from chromite.lib import cros_build_lib
23from chromite.lib import git
Aviv Keshet557e6882013-04-25 13:26:09 -070024from chromite.lib import osutils
Alex Deymo075c2292014-09-04 18:31:50 -070025from chromite.lib import portage_util
Aviv Keshetb1238c32013-04-01 11:42:13 -070026
Aviv Keshetb1238c32013-04-01 11:42:13 -070027
Aviv Keshet940c17f2013-04-11 18:41:42 -070028if cros_build_lib.IsInsideChroot():
Don Garrett25f309a2014-03-19 14:02:12 -070029 # pylint: disable=F0401
Aviv Keshet940c17f2013-04-11 18:41:42 -070030 # Only import portage after we've checked that we're inside the chroot.
31 import portage
32
Aviv Keshetb1238c32013-04-01 11:42:13 -070033INCLUDE_PATTERNS_FILENAME = 'autotest-quickmerge-includepatterns'
34AUTOTEST_PROJECT_NAME = 'chromiumos/third_party/autotest'
Aviv Keshet5f3cf722013-05-09 17:35:25 -070035AUTOTEST_EBUILD = 'chromeos-base/autotest'
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070036DOWNGRADE_EBUILDS = ['chromeos-base/autotest']
Aviv Keshet787ffcd2013-04-08 15:14:56 -070037
Aviv Keshetc73cfc32013-06-14 16:18:53 -070038IGNORE_SUBDIRS = ['ExternalSource',
39 'logs',
40 'results',
41 'site-packages']
42
Aviv Keshet787ffcd2013-04-08 15:14:56 -070043# Data structure describing a single rsync filesystem change.
44#
45# change_description: An 11 character string, the rsync change description
46# for the particular file.
47# absolute_path: The absolute path of the created or modified file.
48ItemizedChange = namedtuple('ItemizedChange', ['change_description',
49 'absolute_path'])
50
51
52# 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
Aviv Keshet84bdfc52013-06-04 13:19:38 -070061class PortagePackageAPIError(Exception):
62 """Exception thrown when unable to retrieve a portage package API."""
63
Aviv Keshet787ffcd2013-04-08 15:14:56 -070064
Aviv Keshetc73cfc32013-06-14 16:18:53 -070065
66def GetNewestFileTime(path, ignore_subdirs=[]):
67 #pylint: disable-msg=W0102
68 """Recursively determine the newest file modification time.
69
Mike Frysinger02e1e072013-11-10 22:11:34 -050070 Args:
Aviv Keshetc73cfc32013-06-14 16:18:53 -070071 path: The absolute path of the directory to recursively search.
72 ignore_subdirs: list of names of subdirectores of given path, to be
73 ignored by recursive search. Useful as a speed
74 optimization, to ignore directories full of many
75 files.
76
77 Returns:
78 The modification time of the most recently modified file recursively
79 contained within the specified directory. Returned as seconds since
80 Jan. 1, 1970, 00:00 GMT, with fractional part (floating point number).
81 """
82 command = ['find', path]
83 for ignore in ignore_subdirs:
84 command.extend(['-path', os.path.join(path, ignore), '-prune', '-o'])
85 command.extend(['-printf', r'%T@\n'])
86
Yu-Ju Hong3add4432014-01-30 11:46:15 -080087 command_result = cros_build_lib.RunCommand(command, error_code_ok=True,
88 capture_output=True)
Aviv Keshetc73cfc32013-06-14 16:18:53 -070089 float_times = [float(str_time) for str_time in
90 command_result.output.split('\n')
91 if str_time != '']
92
93 return max(float_times)
94
95
Aviv Keshet75d65962013-04-17 16:15:23 -070096def GetStalePackageNames(change_list, autotest_sysroot):
Aviv Keshete7b20192013-04-24 14:05:53 -070097 """Given a rsync change report, returns the names of stale test packages.
Aviv Keshet75d65962013-04-17 16:15:23 -070098
99 This function pulls out test package names for client-side tests, stored
100 within the client/site_tests directory tree, that had any files added or
101 modified and for whom any existing bzipped test packages may now be stale.
102
Mike Frysinger02e1e072013-11-10 22:11:34 -0500103 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700104 change_list: A list of ItemizedChange objects corresponding to changed
105 or modified files.
106 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700107 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700108
109 Returns:
110 A list of test package names, eg ['factory_Leds', 'login_UserPolicyKeys'].
111 May contain duplicate entries if multiple files within a test directory
112 were modified.
113 """
114 exp = os.path.abspath(autotest_sysroot) + r'/client/site_tests/(.*?)/.*'
115 matches = [re.match(exp, change.absolute_path) for change in change_list]
116 return [match.group(1) for match in matches if match]
117
118
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700119def ItemizeChangesFromRsyncOutput(rsync_output, destination_path):
120 """Convert the output of an rsync with `-i` to a ItemizedChangeReport object.
121
Mike Frysinger02e1e072013-11-10 22:11:34 -0500122 Args:
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700123 rsync_output: String stdout of rsync command that was run with `-i` option.
124 destination_path: String absolute path of the destination directory for the
125 rsync operations. This argument is necessary because
126 rsync's output only gives the relative path of
127 touched/added files.
128
129 Returns:
130 ItemizedChangeReport object giving the absolute paths of files that were
131 created or modified by rsync.
132 """
133 modified_matches = re.findall(r'([.>]f[^+]{9}) (.*)', rsync_output)
134 new_matches = re.findall(r'(>f\+{9}) (.*)', rsync_output)
135 new_symlink_matches = re.findall(r'(cL\+{9}) (.*) -> .*', rsync_output)
136 new_dir_matches = re.findall(r'(cd\+{9}) (.*)', rsync_output)
137
138 absolute_modified = [ItemizedChange(c, os.path.join(destination_path, f))
139 for (c, f) in modified_matches]
140
141 # Note: new symlinks are treated as new files.
142 absolute_new = [ItemizedChange(c, os.path.join(destination_path, f))
143 for (c, f) in new_matches + new_symlink_matches]
144
145 absolute_new_dir = [ItemizedChange(c, os.path.join(destination_path, f))
146 for (c, f) in new_dir_matches]
147
148 return ItemizedChangeReport(new_files=absolute_new,
149 modified_files=absolute_modified,
150 new_directories=absolute_new_dir)
151
152
Aviv Keshete00caeb2013-04-17 14:03:25 -0700153def GetPackageAPI(portage_root, package_cp):
Aviv Keshete7b20192013-04-24 14:05:53 -0700154 """Gets portage API handles for the given package.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700155
Mike Frysinger02e1e072013-11-10 22:11:34 -0500156 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700157 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500158 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700159
160 Returns:
161 Returns (package, vartree) tuple, where
162 package is of type portage.dbapi.vartree.dblink
163 vartree is of type portage.dbapi.vartree.vartree
Aviv Keshet940c17f2013-04-11 18:41:42 -0700164 """
165 if portage_root is None:
Aviv Keshete7b20192013-04-24 14:05:53 -0700166 # pylint: disable-msg=E1101
167 portage_root = portage.root
Aviv Keshet940c17f2013-04-11 18:41:42 -0700168 # Ensure that portage_root ends with trailing slash.
169 portage_root = os.path.join(portage_root, '')
170
Aviv Keshete7b20192013-04-24 14:05:53 -0700171 # Create a vartree object corresponding to portage_root.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700172 trees = portage.create_trees(portage_root, portage_root)
173 vartree = trees[portage_root]['vartree']
174
Aviv Keshete7b20192013-04-24 14:05:53 -0700175 # List the matching installed packages in cpv format.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700176 matching_packages = vartree.dbapi.cp_list(package_cp)
177
178 if not matching_packages:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700179 raise PortagePackageAPIError('No matching package for %s in portage_root '
180 '%s' % (package_cp, portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700181
182 if len(matching_packages) > 1:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700183 raise PortagePackageAPIError('Too many matching packages for %s in '
184 'portage_root %s' % (package_cp,
185 portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700186
Aviv Keshete7b20192013-04-24 14:05:53 -0700187 # Convert string match to package dblink.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700188 package_cpv = matching_packages[0]
Alex Deymo075c2292014-09-04 18:31:50 -0700189 package_split = portage_util.SplitCPV(package_cpv)
Aviv Keshete7b20192013-04-24 14:05:53 -0700190 # pylint: disable-msg=E1101
191 package = portage.dblink(package_split.category,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700192 package_split.pv, settings=vartree.settings,
193 vartree=vartree)
194
Aviv Keshete00caeb2013-04-17 14:03:25 -0700195 return package, vartree
196
197
198def DowngradePackageVersion(portage_root, package_cp,
199 downgrade_to_version='0'):
Aviv Keshete7b20192013-04-24 14:05:53 -0700200 """Downgrade the specified portage package version.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700201
Mike Frysinger02e1e072013-11-10 22:11:34 -0500202 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700203 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500204 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700205 downgrade_to_version: String version to downgrade to. Default: '0'
206
207 Returns:
Aviv Keshet557e6882013-04-25 13:26:09 -0700208 True on success. False on failure (nonzero return code from `mv` command).
Aviv Keshete00caeb2013-04-17 14:03:25 -0700209 """
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700210 try:
211 package, _ = GetPackageAPI(portage_root, package_cp)
212 except PortagePackageAPIError:
213 # Unable to fetch a corresponding portage package API for this
214 # package_cp (either no such package, or name ambigious and matches).
215 # So, just fail out.
216 return False
Aviv Keshete00caeb2013-04-17 14:03:25 -0700217
218 source_directory = package.dbdir
219 destination_path = os.path.join(
220 package.dbroot, package_cp + '-' + downgrade_to_version)
221 if os.path.abspath(source_directory) == os.path.abspath(destination_path):
Aviv Keshet557e6882013-04-25 13:26:09 -0700222 return True
Aviv Keshete00caeb2013-04-17 14:03:25 -0700223 command = ['mv', source_directory, destination_path]
Aviv Keshet557e6882013-04-25 13:26:09 -0700224 code = cros_build_lib.SudoRunCommand(command, error_code_ok=True).returncode
225 return code == 0
Aviv Keshete00caeb2013-04-17 14:03:25 -0700226
227
Aviv Keshete7b20192013-04-24 14:05:53 -0700228def UpdatePackageContents(change_report, package_cp, portage_root=None):
229 """Add newly created files/directors to package contents.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700230
231 Given an ItemizedChangeReport, add the newly created files and directories
232 to the CONTENTS of an installed portage package, such that these files are
233 considered owned by that package.
234
Mike Frysinger02e1e072013-11-10 22:11:34 -0500235 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700236 change_report: ItemizedChangeReport object for the changes to be
237 made to the package.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700238 package_cp: A string similar to 'chromeos-base/autotest-tests' giving
239 the package category and name of the package to be altered.
240 portage_root: Portage root path, corresponding to the board that
241 we are working on. Defaults to '/'
242 """
243 package, vartree = GetPackageAPI(portage_root, package_cp)
244
Aviv Keshete7b20192013-04-24 14:05:53 -0700245 # Append new contents to package contents dictionary.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700246 contents = package.getcontents().copy()
247 for _, filename in change_report.new_files:
248 contents.setdefault(filename, (u'obj', '0', '0'))
249 for _, dirname in change_report.new_directories:
Aviv Keshete7b20192013-04-24 14:05:53 -0700250 # Strip trailing slashes if present.
251 contents.setdefault(dirname.rstrip('/'), (u'dir',))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700252
Aviv Keshete7b20192013-04-24 14:05:53 -0700253 # Write new contents dictionary to file.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700254 vartree.dbapi.writeContentsToContentsFile(package, contents)
255
256
Aviv Keshet19276752013-05-16 11:12:23 -0700257def RemoveBzipPackages(autotest_sysroot):
258 """Remove all bzipped test/dep/profiler packages from sysroot autotest.
Aviv Keshet75d65962013-04-17 16:15:23 -0700259
Mike Frysinger02e1e072013-11-10 22:11:34 -0500260 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700261 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700262 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700263 """
Aviv Keshet19276752013-05-16 11:12:23 -0700264 osutils.RmDir(os.path.join(autotest_sysroot, 'packages'),
265 ignore_missing=True)
266 osutils.SafeUnlink(os.path.join(autotest_sysroot, 'packages.checksum'))
Aviv Keshet75d65962013-04-17 16:15:23 -0700267
268
Aviv Keshetb1238c32013-04-01 11:42:13 -0700269def RsyncQuickmerge(source_path, sysroot_autotest_path,
270 include_pattern_file=None, pretend=False,
Aviv Keshet60968ec2013-04-11 18:44:14 -0700271 overwrite=False):
Aviv Keshetb1238c32013-04-01 11:42:13 -0700272 """Run rsync quickmerge command, with specified arguments.
Aviv Keshete7b20192013-04-24 14:05:53 -0700273
Aviv Keshetb1238c32013-04-01 11:42:13 -0700274 Command will take form `rsync -a [options] --exclude=**.pyc
275 --exclude=**.pyo
Don Garrett25f309a2014-03-19 14:02:12 -0700276 [optional --include-from include_pattern_file]
Aviv Keshetb1238c32013-04-01 11:42:13 -0700277 --exclude=* [source_path] [sysroot_autotest_path]`
278
Mike Frysinger02e1e072013-11-10 22:11:34 -0500279 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700280 source_path: Directory to rsync from.
281 sysroot_autotest_path: Directory to rsync too.
282 include_pattern_file: Optional pattern of files to include in rsync.
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500283 pretend: True to use the '-n' option to rsync, to perform dry run.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700284 overwrite: True to omit '-u' option, overwrite all files in sysroot,
285 not just older files.
Aviv Keshet557e6882013-04-25 13:26:09 -0700286
287 Returns:
288 The cros_build_lib.CommandResult object resulting from the rsync command.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700289 """
290 command = ['rsync', '-a']
291
Prathmesh Prabhu137266a2014-02-11 20:02:18 -0800292 # For existing files, preserve destination permissions. This ensures that
293 # existing files end up with the file permissions set by the ebuilds.
294 # If this script copies over a file that does not exist in the destination
295 # tree, it will set the least restrictive permissions allowed in the
296 # destination tree. This could happen if the file copied is not installed by
297 # *any* ebuild, or if the ebuild that installs the file was never emerged.
298 command += ['--no-p', '--chmod=ugo=rwX']
299
Aviv Keshetb1238c32013-04-01 11:42:13 -0700300 if pretend:
301 command += ['-n']
302
303 if not overwrite:
304 command += ['-u']
305
Aviv Keshet60968ec2013-04-11 18:44:14 -0700306 command += ['-i']
Aviv Keshetb1238c32013-04-01 11:42:13 -0700307
308 command += ['--exclude=**.pyc']
309 command += ['--exclude=**.pyo']
310
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700311 # Exclude files with a specific substring in their name, because
312 # they create an ambiguous itemized report. (see unit test file for details)
313 command += ['--exclude=** -> *']
314
Aviv Keshetb1238c32013-04-01 11:42:13 -0700315 if include_pattern_file:
316 command += ['--include-from=%s' % include_pattern_file]
317
318 command += ['--exclude=*']
319
320 command += [source_path, sysroot_autotest_path]
321
Aviv Keshet60968ec2013-04-11 18:44:14 -0700322 return cros_build_lib.SudoRunCommand(command, redirect_stdout=True)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700323
324
325def ParseArguments(argv):
326 """Parse command line arguments
327
Mike Frysinger02e1e072013-11-10 22:11:34 -0500328 Returns:
329 parsed arguments.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700330 """
331 parser = argparse.ArgumentParser(description='Perform a fast approximation '
332 'to emerge-$board autotest-all, by '
333 'rsyncing source tree to sysroot.')
334
Aviv Keshet0a366a02013-07-18 10:52:04 -0700335
336 default_board = cros_build_lib.GetDefaultBoard()
337 parser.add_argument('--board', metavar='BOARD', default=default_board,
338 help='Board to perform quickmerge for. Default: ' +
339 (default_board or 'Not configured.'))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700340 parser.add_argument('--pretend', action='store_true',
341 help='Dry run only, do not modify sysroot autotest.')
342 parser.add_argument('--overwrite', action='store_true',
343 help='Overwrite existing files even if newer.')
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700344 parser.add_argument('--force', action='store_true',
345 help='Do not check whether destination tree is newer '
346 'than source tree, always perform quickmerge.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700347 parser.add_argument('--verbose', action='store_true',
348 help='Print detailed change report.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700349
Aviv Keshet474469d2013-07-22 12:54:52 -0700350 # Used only if test_that is calling autotest_quickmerge and has detected that
351 # the sysroot autotest path is still in usr/local/autotest (ie the build
352 # pre-dates https://chromium-review.googlesource.com/#/c/62880/ )
353 parser.add_argument('--legacy_path', action='store_true',
354 help=argparse.SUPPRESS)
355
Aviv Keshetb1238c32013-04-01 11:42:13 -0700356 return parser.parse_args(argv)
357
358
359def main(argv):
360 cros_build_lib.AssertInsideChroot()
361
362 args = ParseArguments(argv)
363
Aviv Keshete7b20192013-04-24 14:05:53 -0700364 if os.geteuid() != 0:
Aviv Keshet940c17f2013-04-11 18:41:42 -0700365 try:
366 cros_build_lib.SudoRunCommand([sys.executable] + sys.argv)
367 except cros_build_lib.RunCommandError:
368 return 1
369 return 0
370
Aviv Keshetb1238c32013-04-01 11:42:13 -0700371 if not args.board:
Mike Frysinger383367e2014-09-16 15:06:17 -0400372 print('No board specified. Aborting.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700373 return 1
374
375 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
David Jamese3b06062013-11-09 18:52:02 -0800376 checkout = manifest.FindCheckout(AUTOTEST_PROJECT_NAME)
377 source_path = os.path.join(checkout.GetPath(absolute=True), '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700378
379 script_path = os.path.dirname(__file__)
380 include_pattern_file = os.path.join(script_path, INCLUDE_PATTERNS_FILENAME)
381
382 # TODO: Determine the following string programatically.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700383 sysroot_path = os.path.join('/build', args.board, '')
Aviv Keshet474469d2013-07-22 12:54:52 -0700384 sysroot_autotest_path = os.path.join(sysroot_path,
385 constants.AUTOTEST_BUILD_PATH, '')
386 if args.legacy_path:
387 sysroot_autotest_path = os.path.join(sysroot_path, 'usr/local/autotest',
388 '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700389
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700390 if not args.force:
391 newest_dest_time = GetNewestFileTime(sysroot_autotest_path, IGNORE_SUBDIRS)
392 newest_source_time = GetNewestFileTime(source_path, IGNORE_SUBDIRS)
393 if newest_dest_time >= newest_source_time:
394 logging.info('The sysroot appears to be newer than the source tree, '
395 'doing nothing and exiting now.')
396 return 0
397
Aviv Keshet60968ec2013-04-11 18:44:14 -0700398 rsync_output = RsyncQuickmerge(source_path, sysroot_autotest_path,
Aviv Keshete7b20192013-04-24 14:05:53 -0700399 include_pattern_file, args.pretend,
400 args.overwrite)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700401
Aviv Keshete00caeb2013-04-17 14:03:25 -0700402 if args.verbose:
403 logging.info(rsync_output.output)
404
Aviv Keshet60968ec2013-04-11 18:44:14 -0700405 change_report = ItemizeChangesFromRsyncOutput(rsync_output.output,
406 sysroot_autotest_path)
407
Aviv Keshet940c17f2013-04-11 18:41:42 -0700408 if not args.pretend:
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700409 logging.info('Updating portage database.')
Aviv Keshet5f3cf722013-05-09 17:35:25 -0700410 UpdatePackageContents(change_report, AUTOTEST_EBUILD,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700411 sysroot_path)
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700412 for logfile in glob.glob(os.path.join(sysroot_autotest_path, 'packages',
413 '*.log')):
414 try:
415 # Open file in a try-except block, for atomicity, instead of
416 # doing existence check.
417 with open(logfile, 'r') as f:
418 package_cp = f.readline().strip()
419 DOWNGRADE_EBUILDS.append(package_cp)
420 except IOError:
421 pass
422
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700423 for ebuild in DOWNGRADE_EBUILDS:
Aviv Keshet557e6882013-04-25 13:26:09 -0700424 if not DowngradePackageVersion(sysroot_path, ebuild):
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700425 logging.warning('Unable to downgrade package %s version number.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700426 ebuild)
Aviv Keshet19276752013-05-16 11:12:23 -0700427 RemoveBzipPackages(sysroot_autotest_path)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700428
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700429 sentinel_filename = os.path.join(sysroot_autotest_path,
430 '.quickmerge_sentinel')
431 cros_build_lib.RunCommand(['touch', sentinel_filename])
432
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700433
Aviv Keshet940c17f2013-04-11 18:41:42 -0700434 if args.pretend:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700435 logging.info('The following message is pretend only. No filesystem '
Aviv Keshete7b20192013-04-24 14:05:53 -0700436 'changes made.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700437 logging.info('Quickmerge complete. Created or modified %s files.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700438 len(change_report.new_files) +
439 len(change_report.modified_files))
Aviv Keshete00caeb2013-04-17 14:03:25 -0700440
441 return 0