blob: 1de086441825449036b569f93d1fbe187ca9d10d [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
Aviv Keshete7b20192013-04-24 14:05:53 -070011import argparse
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070012import glob
Aviv Keshete00caeb2013-04-17 14:03:25 -070013import logging
Aviv Keshetb1238c32013-04-01 11:42:13 -070014import os
Aviv Keshet787ffcd2013-04-08 15:14:56 -070015import re
Aviv Keshetb1238c32013-04-01 11:42:13 -070016import sys
Aviv Keshet787ffcd2013-04-08 15:14:56 -070017from collections import namedtuple
18
Don Garrett88b8d782014-05-13 17:30:55 -070019from chromite.cbuildbot import constants
Aviv Keshetb1238c32013-04-01 11:42:13 -070020from chromite.lib import cros_build_lib
21from chromite.lib import git
Aviv Keshet557e6882013-04-25 13:26:09 -070022from chromite.lib import osutils
Alex Deymo075c2292014-09-04 18:31:50 -070023from chromite.lib import portage_util
Aviv Keshetb1238c32013-04-01 11:42:13 -070024
Aviv Keshetb1238c32013-04-01 11:42:13 -070025
Aviv Keshet940c17f2013-04-11 18:41:42 -070026if cros_build_lib.IsInsideChroot():
Don Garrett25f309a2014-03-19 14:02:12 -070027 # pylint: disable=F0401
Aviv Keshet940c17f2013-04-11 18:41:42 -070028 # Only import portage after we've checked that we're inside the chroot.
29 import portage
30
Aviv Keshetb1238c32013-04-01 11:42:13 -070031INCLUDE_PATTERNS_FILENAME = 'autotest-quickmerge-includepatterns'
32AUTOTEST_PROJECT_NAME = 'chromiumos/third_party/autotest'
Aviv Keshet5f3cf722013-05-09 17:35:25 -070033AUTOTEST_EBUILD = 'chromeos-base/autotest'
Aviv Keshetfe54a8a2013-09-16 15:49:03 -070034DOWNGRADE_EBUILDS = ['chromeos-base/autotest']
Aviv Keshet787ffcd2013-04-08 15:14:56 -070035
Aviv Keshetc73cfc32013-06-14 16:18:53 -070036IGNORE_SUBDIRS = ['ExternalSource',
37 'logs',
38 'results',
39 'site-packages']
40
Aviv Keshet787ffcd2013-04-08 15:14:56 -070041# Data structure describing a single rsync filesystem change.
42#
43# change_description: An 11 character string, the rsync change description
44# for the particular file.
45# absolute_path: The absolute path of the created or modified file.
46ItemizedChange = namedtuple('ItemizedChange', ['change_description',
47 'absolute_path'])
48
49
50# Data structure describing the rsync new/modified files or directories.
51#
52# new_files: A list of ItemizedChange objects for new files.
53# modified_files: A list of ItemizedChange objects for modified files.
54# new_directories: A list of ItemizedChange objects for new directories.
55ItemizedChangeReport = namedtuple('ItemizedChangeReport',
56 ['new_files', 'modified_files',
57 'new_directories'])
58
Aviv Keshet84bdfc52013-06-04 13:19:38 -070059class PortagePackageAPIError(Exception):
60 """Exception thrown when unable to retrieve a portage package API."""
61
Aviv Keshet787ffcd2013-04-08 15:14:56 -070062
Aviv Keshetc73cfc32013-06-14 16:18:53 -070063
64def GetNewestFileTime(path, ignore_subdirs=[]):
65 #pylint: disable-msg=W0102
66 """Recursively determine the newest file modification time.
67
Mike Frysinger02e1e072013-11-10 22:11:34 -050068 Args:
Aviv Keshetc73cfc32013-06-14 16:18:53 -070069 path: The absolute path of the directory to recursively search.
70 ignore_subdirs: list of names of subdirectores of given path, to be
71 ignored by recursive search. Useful as a speed
72 optimization, to ignore directories full of many
73 files.
74
75 Returns:
76 The modification time of the most recently modified file recursively
77 contained within the specified directory. Returned as seconds since
78 Jan. 1, 1970, 00:00 GMT, with fractional part (floating point number).
79 """
80 command = ['find', path]
81 for ignore in ignore_subdirs:
82 command.extend(['-path', os.path.join(path, ignore), '-prune', '-o'])
83 command.extend(['-printf', r'%T@\n'])
84
Yu-Ju Hong3add4432014-01-30 11:46:15 -080085 command_result = cros_build_lib.RunCommand(command, error_code_ok=True,
86 capture_output=True)
Aviv Keshetc73cfc32013-06-14 16:18:53 -070087 float_times = [float(str_time) for str_time in
88 command_result.output.split('\n')
89 if str_time != '']
90
91 return max(float_times)
92
93
Aviv Keshet75d65962013-04-17 16:15:23 -070094def GetStalePackageNames(change_list, autotest_sysroot):
Aviv Keshete7b20192013-04-24 14:05:53 -070095 """Given a rsync change report, returns the names of stale test packages.
Aviv Keshet75d65962013-04-17 16:15:23 -070096
97 This function pulls out test package names for client-side tests, stored
98 within the client/site_tests directory tree, that had any files added or
99 modified and for whom any existing bzipped test packages may now be stale.
100
Mike Frysinger02e1e072013-11-10 22:11:34 -0500101 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700102 change_list: A list of ItemizedChange objects corresponding to changed
103 or modified files.
104 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700105 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700106
107 Returns:
108 A list of test package names, eg ['factory_Leds', 'login_UserPolicyKeys'].
109 May contain duplicate entries if multiple files within a test directory
110 were modified.
111 """
112 exp = os.path.abspath(autotest_sysroot) + r'/client/site_tests/(.*?)/.*'
113 matches = [re.match(exp, change.absolute_path) for change in change_list]
114 return [match.group(1) for match in matches if match]
115
116
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700117def ItemizeChangesFromRsyncOutput(rsync_output, destination_path):
118 """Convert the output of an rsync with `-i` to a ItemizedChangeReport object.
119
Mike Frysinger02e1e072013-11-10 22:11:34 -0500120 Args:
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700121 rsync_output: String stdout of rsync command that was run with `-i` option.
122 destination_path: String absolute path of the destination directory for the
123 rsync operations. This argument is necessary because
124 rsync's output only gives the relative path of
125 touched/added files.
126
127 Returns:
128 ItemizedChangeReport object giving the absolute paths of files that were
129 created or modified by rsync.
130 """
131 modified_matches = re.findall(r'([.>]f[^+]{9}) (.*)', rsync_output)
132 new_matches = re.findall(r'(>f\+{9}) (.*)', rsync_output)
133 new_symlink_matches = re.findall(r'(cL\+{9}) (.*) -> .*', rsync_output)
134 new_dir_matches = re.findall(r'(cd\+{9}) (.*)', rsync_output)
135
136 absolute_modified = [ItemizedChange(c, os.path.join(destination_path, f))
137 for (c, f) in modified_matches]
138
139 # Note: new symlinks are treated as new files.
140 absolute_new = [ItemizedChange(c, os.path.join(destination_path, f))
141 for (c, f) in new_matches + new_symlink_matches]
142
143 absolute_new_dir = [ItemizedChange(c, os.path.join(destination_path, f))
144 for (c, f) in new_dir_matches]
145
146 return ItemizedChangeReport(new_files=absolute_new,
147 modified_files=absolute_modified,
148 new_directories=absolute_new_dir)
149
150
Aviv Keshete00caeb2013-04-17 14:03:25 -0700151def GetPackageAPI(portage_root, package_cp):
Aviv Keshete7b20192013-04-24 14:05:53 -0700152 """Gets portage API handles for the given package.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700153
Mike Frysinger02e1e072013-11-10 22:11:34 -0500154 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700155 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500156 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700157
158 Returns:
159 Returns (package, vartree) tuple, where
160 package is of type portage.dbapi.vartree.dblink
161 vartree is of type portage.dbapi.vartree.vartree
Aviv Keshet940c17f2013-04-11 18:41:42 -0700162 """
163 if portage_root is None:
Aviv Keshete7b20192013-04-24 14:05:53 -0700164 # pylint: disable-msg=E1101
165 portage_root = portage.root
Aviv Keshet940c17f2013-04-11 18:41:42 -0700166 # Ensure that portage_root ends with trailing slash.
167 portage_root = os.path.join(portage_root, '')
168
Aviv Keshete7b20192013-04-24 14:05:53 -0700169 # Create a vartree object corresponding to portage_root.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700170 trees = portage.create_trees(portage_root, portage_root)
171 vartree = trees[portage_root]['vartree']
172
Aviv Keshete7b20192013-04-24 14:05:53 -0700173 # List the matching installed packages in cpv format.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700174 matching_packages = vartree.dbapi.cp_list(package_cp)
175
176 if not matching_packages:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700177 raise PortagePackageAPIError('No matching package for %s in portage_root '
178 '%s' % (package_cp, portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700179
180 if len(matching_packages) > 1:
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700181 raise PortagePackageAPIError('Too many matching packages for %s in '
182 'portage_root %s' % (package_cp,
183 portage_root))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700184
Aviv Keshete7b20192013-04-24 14:05:53 -0700185 # Convert string match to package dblink.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700186 package_cpv = matching_packages[0]
Alex Deymo075c2292014-09-04 18:31:50 -0700187 package_split = portage_util.SplitCPV(package_cpv)
Aviv Keshete7b20192013-04-24 14:05:53 -0700188 # pylint: disable-msg=E1101
189 package = portage.dblink(package_split.category,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700190 package_split.pv, settings=vartree.settings,
191 vartree=vartree)
192
Aviv Keshete00caeb2013-04-17 14:03:25 -0700193 return package, vartree
194
195
196def DowngradePackageVersion(portage_root, package_cp,
197 downgrade_to_version='0'):
Aviv Keshete7b20192013-04-24 14:05:53 -0700198 """Downgrade the specified portage package version.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700199
Mike Frysinger02e1e072013-11-10 22:11:34 -0500200 Args:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700201 portage_root: Root directory of portage tree. Eg '/' or '/build/lumpy'
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500202 package_cp: A string similar to 'chromeos-base/autotest-tests'.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700203 downgrade_to_version: String version to downgrade to. Default: '0'
204
205 Returns:
Aviv Keshet557e6882013-04-25 13:26:09 -0700206 True on success. False on failure (nonzero return code from `mv` command).
Aviv Keshete00caeb2013-04-17 14:03:25 -0700207 """
Aviv Keshet84bdfc52013-06-04 13:19:38 -0700208 try:
209 package, _ = GetPackageAPI(portage_root, package_cp)
210 except PortagePackageAPIError:
211 # Unable to fetch a corresponding portage package API for this
212 # package_cp (either no such package, or name ambigious and matches).
213 # So, just fail out.
214 return False
Aviv Keshete00caeb2013-04-17 14:03:25 -0700215
216 source_directory = package.dbdir
217 destination_path = os.path.join(
218 package.dbroot, package_cp + '-' + downgrade_to_version)
219 if os.path.abspath(source_directory) == os.path.abspath(destination_path):
Aviv Keshet557e6882013-04-25 13:26:09 -0700220 return True
Aviv Keshete00caeb2013-04-17 14:03:25 -0700221 command = ['mv', source_directory, destination_path]
Aviv Keshet557e6882013-04-25 13:26:09 -0700222 code = cros_build_lib.SudoRunCommand(command, error_code_ok=True).returncode
223 return code == 0
Aviv Keshete00caeb2013-04-17 14:03:25 -0700224
225
Aviv Keshete7b20192013-04-24 14:05:53 -0700226def UpdatePackageContents(change_report, package_cp, portage_root=None):
227 """Add newly created files/directors to package contents.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700228
229 Given an ItemizedChangeReport, add the newly created files and directories
230 to the CONTENTS of an installed portage package, such that these files are
231 considered owned by that package.
232
Mike Frysinger02e1e072013-11-10 22:11:34 -0500233 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700234 change_report: ItemizedChangeReport object for the changes to be
235 made to the package.
Aviv Keshete00caeb2013-04-17 14:03:25 -0700236 package_cp: A string similar to 'chromeos-base/autotest-tests' giving
237 the package category and name of the package to be altered.
238 portage_root: Portage root path, corresponding to the board that
239 we are working on. Defaults to '/'
240 """
241 package, vartree = GetPackageAPI(portage_root, package_cp)
242
Aviv Keshete7b20192013-04-24 14:05:53 -0700243 # Append new contents to package contents dictionary.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700244 contents = package.getcontents().copy()
245 for _, filename in change_report.new_files:
246 contents.setdefault(filename, (u'obj', '0', '0'))
247 for _, dirname in change_report.new_directories:
Aviv Keshete7b20192013-04-24 14:05:53 -0700248 # Strip trailing slashes if present.
249 contents.setdefault(dirname.rstrip('/'), (u'dir',))
Aviv Keshet940c17f2013-04-11 18:41:42 -0700250
Aviv Keshete7b20192013-04-24 14:05:53 -0700251 # Write new contents dictionary to file.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700252 vartree.dbapi.writeContentsToContentsFile(package, contents)
253
254
Aviv Keshet19276752013-05-16 11:12:23 -0700255def RemoveBzipPackages(autotest_sysroot):
256 """Remove all bzipped test/dep/profiler packages from sysroot autotest.
Aviv Keshet75d65962013-04-17 16:15:23 -0700257
Mike Frysinger02e1e072013-11-10 22:11:34 -0500258 Args:
Aviv Keshet75d65962013-04-17 16:15:23 -0700259 autotest_sysroot: Absolute path of autotest in the sysroot,
Aviv Keshet474469d2013-07-22 12:54:52 -0700260 e.g. '/build/lumpy/usr/local/build/autotest'
Aviv Keshet75d65962013-04-17 16:15:23 -0700261 """
Aviv Keshet19276752013-05-16 11:12:23 -0700262 osutils.RmDir(os.path.join(autotest_sysroot, 'packages'),
263 ignore_missing=True)
264 osutils.SafeUnlink(os.path.join(autotest_sysroot, 'packages.checksum'))
Aviv Keshet75d65962013-04-17 16:15:23 -0700265
266
Aviv Keshetb1238c32013-04-01 11:42:13 -0700267def RsyncQuickmerge(source_path, sysroot_autotest_path,
268 include_pattern_file=None, pretend=False,
Aviv Keshet60968ec2013-04-11 18:44:14 -0700269 overwrite=False):
Aviv Keshetb1238c32013-04-01 11:42:13 -0700270 """Run rsync quickmerge command, with specified arguments.
Aviv Keshete7b20192013-04-24 14:05:53 -0700271
Aviv Keshetb1238c32013-04-01 11:42:13 -0700272 Command will take form `rsync -a [options] --exclude=**.pyc
273 --exclude=**.pyo
Don Garrett25f309a2014-03-19 14:02:12 -0700274 [optional --include-from include_pattern_file]
Aviv Keshetb1238c32013-04-01 11:42:13 -0700275 --exclude=* [source_path] [sysroot_autotest_path]`
276
Mike Frysinger02e1e072013-11-10 22:11:34 -0500277 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700278 source_path: Directory to rsync from.
279 sysroot_autotest_path: Directory to rsync too.
280 include_pattern_file: Optional pattern of files to include in rsync.
Mike Frysingerad8c6ca2014-02-03 11:28:45 -0500281 pretend: True to use the '-n' option to rsync, to perform dry run.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700282 overwrite: True to omit '-u' option, overwrite all files in sysroot,
283 not just older files.
Aviv Keshet557e6882013-04-25 13:26:09 -0700284
285 Returns:
286 The cros_build_lib.CommandResult object resulting from the rsync command.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700287 """
288 command = ['rsync', '-a']
289
Prathmesh Prabhu137266a2014-02-11 20:02:18 -0800290 # For existing files, preserve destination permissions. This ensures that
291 # existing files end up with the file permissions set by the ebuilds.
292 # If this script copies over a file that does not exist in the destination
293 # tree, it will set the least restrictive permissions allowed in the
294 # destination tree. This could happen if the file copied is not installed by
295 # *any* ebuild, or if the ebuild that installs the file was never emerged.
296 command += ['--no-p', '--chmod=ugo=rwX']
297
Aviv Keshetb1238c32013-04-01 11:42:13 -0700298 if pretend:
299 command += ['-n']
300
301 if not overwrite:
302 command += ['-u']
303
Aviv Keshet60968ec2013-04-11 18:44:14 -0700304 command += ['-i']
Aviv Keshetb1238c32013-04-01 11:42:13 -0700305
306 command += ['--exclude=**.pyc']
307 command += ['--exclude=**.pyo']
308
Aviv Keshet787ffcd2013-04-08 15:14:56 -0700309 # Exclude files with a specific substring in their name, because
310 # they create an ambiguous itemized report. (see unit test file for details)
311 command += ['--exclude=** -> *']
312
Aviv Keshetb1238c32013-04-01 11:42:13 -0700313 if include_pattern_file:
314 command += ['--include-from=%s' % include_pattern_file]
315
316 command += ['--exclude=*']
317
318 command += [source_path, sysroot_autotest_path]
319
Aviv Keshet60968ec2013-04-11 18:44:14 -0700320 return cros_build_lib.SudoRunCommand(command, redirect_stdout=True)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700321
322
323def ParseArguments(argv):
324 """Parse command line arguments
325
Mike Frysinger02e1e072013-11-10 22:11:34 -0500326 Returns:
327 parsed arguments.
Aviv Keshetb1238c32013-04-01 11:42:13 -0700328 """
329 parser = argparse.ArgumentParser(description='Perform a fast approximation '
330 'to emerge-$board autotest-all, by '
331 'rsyncing source tree to sysroot.')
332
Aviv Keshet0a366a02013-07-18 10:52:04 -0700333
334 default_board = cros_build_lib.GetDefaultBoard()
335 parser.add_argument('--board', metavar='BOARD', default=default_board,
336 help='Board to perform quickmerge for. Default: ' +
337 (default_board or 'Not configured.'))
Aviv Keshetb1238c32013-04-01 11:42:13 -0700338 parser.add_argument('--pretend', action='store_true',
339 help='Dry run only, do not modify sysroot autotest.')
340 parser.add_argument('--overwrite', action='store_true',
341 help='Overwrite existing files even if newer.')
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700342 parser.add_argument('--force', action='store_true',
343 help='Do not check whether destination tree is newer '
344 'than source tree, always perform quickmerge.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700345 parser.add_argument('--verbose', action='store_true',
346 help='Print detailed change report.')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700347
Aviv Keshet474469d2013-07-22 12:54:52 -0700348 # Used only if test_that is calling autotest_quickmerge and has detected that
349 # the sysroot autotest path is still in usr/local/autotest (ie the build
350 # pre-dates https://chromium-review.googlesource.com/#/c/62880/ )
351 parser.add_argument('--legacy_path', action='store_true',
352 help=argparse.SUPPRESS)
353
Aviv Keshetb1238c32013-04-01 11:42:13 -0700354 return parser.parse_args(argv)
355
356
357def main(argv):
358 cros_build_lib.AssertInsideChroot()
359
360 args = ParseArguments(argv)
361
Aviv Keshete7b20192013-04-24 14:05:53 -0700362 if os.geteuid() != 0:
Aviv Keshet940c17f2013-04-11 18:41:42 -0700363 try:
364 cros_build_lib.SudoRunCommand([sys.executable] + sys.argv)
365 except cros_build_lib.RunCommandError:
366 return 1
367 return 0
368
Aviv Keshetb1238c32013-04-01 11:42:13 -0700369 if not args.board:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700370 print 'No board specified. Aborting.'
Aviv Keshetb1238c32013-04-01 11:42:13 -0700371 return 1
372
373 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
David Jamese3b06062013-11-09 18:52:02 -0800374 checkout = manifest.FindCheckout(AUTOTEST_PROJECT_NAME)
375 source_path = os.path.join(checkout.GetPath(absolute=True), '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700376
377 script_path = os.path.dirname(__file__)
378 include_pattern_file = os.path.join(script_path, INCLUDE_PATTERNS_FILENAME)
379
380 # TODO: Determine the following string programatically.
Aviv Keshet940c17f2013-04-11 18:41:42 -0700381 sysroot_path = os.path.join('/build', args.board, '')
Aviv Keshet474469d2013-07-22 12:54:52 -0700382 sysroot_autotest_path = os.path.join(sysroot_path,
383 constants.AUTOTEST_BUILD_PATH, '')
384 if args.legacy_path:
385 sysroot_autotest_path = os.path.join(sysroot_path, 'usr/local/autotest',
386 '')
Aviv Keshetb1238c32013-04-01 11:42:13 -0700387
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700388 if not args.force:
389 newest_dest_time = GetNewestFileTime(sysroot_autotest_path, IGNORE_SUBDIRS)
390 newest_source_time = GetNewestFileTime(source_path, IGNORE_SUBDIRS)
391 if newest_dest_time >= newest_source_time:
392 logging.info('The sysroot appears to be newer than the source tree, '
393 'doing nothing and exiting now.')
394 return 0
395
Aviv Keshet60968ec2013-04-11 18:44:14 -0700396 rsync_output = RsyncQuickmerge(source_path, sysroot_autotest_path,
Aviv Keshete7b20192013-04-24 14:05:53 -0700397 include_pattern_file, args.pretend,
398 args.overwrite)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700399
Aviv Keshete00caeb2013-04-17 14:03:25 -0700400 if args.verbose:
401 logging.info(rsync_output.output)
402
Aviv Keshet60968ec2013-04-11 18:44:14 -0700403 change_report = ItemizeChangesFromRsyncOutput(rsync_output.output,
404 sysroot_autotest_path)
405
Aviv Keshet940c17f2013-04-11 18:41:42 -0700406 if not args.pretend:
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700407 logging.info('Updating portage database.')
Aviv Keshet5f3cf722013-05-09 17:35:25 -0700408 UpdatePackageContents(change_report, AUTOTEST_EBUILD,
Aviv Keshet940c17f2013-04-11 18:41:42 -0700409 sysroot_path)
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700410 for logfile in glob.glob(os.path.join(sysroot_autotest_path, 'packages',
411 '*.log')):
412 try:
413 # Open file in a try-except block, for atomicity, instead of
414 # doing existence check.
415 with open(logfile, 'r') as f:
416 package_cp = f.readline().strip()
417 DOWNGRADE_EBUILDS.append(package_cp)
418 except IOError:
419 pass
420
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700421 for ebuild in DOWNGRADE_EBUILDS:
Aviv Keshet557e6882013-04-25 13:26:09 -0700422 if not DowngradePackageVersion(sysroot_path, ebuild):
Aviv Keshet3cc4e9e2013-04-24 10:47:23 -0700423 logging.warning('Unable to downgrade package %s version number.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700424 ebuild)
Aviv Keshet19276752013-05-16 11:12:23 -0700425 RemoveBzipPackages(sysroot_autotest_path)
Aviv Keshetb1238c32013-04-01 11:42:13 -0700426
Aviv Keshetc73cfc32013-06-14 16:18:53 -0700427 sentinel_filename = os.path.join(sysroot_autotest_path,
428 '.quickmerge_sentinel')
429 cros_build_lib.RunCommand(['touch', sentinel_filename])
430
Aviv Keshetfe54a8a2013-09-16 15:49:03 -0700431
Aviv Keshet940c17f2013-04-11 18:41:42 -0700432 if args.pretend:
Aviv Keshete00caeb2013-04-17 14:03:25 -0700433 logging.info('The following message is pretend only. No filesystem '
Aviv Keshete7b20192013-04-24 14:05:53 -0700434 'changes made.')
Aviv Keshete00caeb2013-04-17 14:03:25 -0700435 logging.info('Quickmerge complete. Created or modified %s files.',
Aviv Keshete7b20192013-04-24 14:05:53 -0700436 len(change_report.new_files) +
437 len(change_report.modified_files))
Aviv Keshete00caeb2013-04-17 14:03:25 -0700438
439 return 0