Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: cros_mark_as_stable.py

Issue 4442001: Add more error checking to preflight queue. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/crosutils.git
Patch Set: Update unit tests Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """This module uprevs a given package's ebuild to the next revision.""" 7 """This module uprevs a given package's ebuild to the next revision."""
8 8
9 9
10 import fileinput 10 import fileinput
11 import gflags 11 import gflags
12 import os 12 import os
13 import re 13 import re
14 import shutil 14 import shutil
15 import subprocess 15 import subprocess
16 import sys 16 import sys
17 17
18 sys.path.append(os.path.join(os.path.dirname(__file__), 'lib')) 18 sys.path.append(os.path.join(os.path.dirname(__file__), 'lib'))
19 from cros_build_lib import Info, RunCommand, Warning, Die 19 from cros_build_lib import Info, RunCommand, Warning, Die
20 20
21 21
22 gflags.DEFINE_string('board', '', 22 gflags.DEFINE_string('board', '',
23 'Board for which the package belongs.', short_name='b') 23 'Board for which the package belongs.', short_name='b')
24 gflags.DEFINE_string('overlays', '', 24 gflags.DEFINE_string('overlays', '',
25 'Space separated list of overlays to modify.', 25 'Colon-separated list of overlays to modify.',
26 short_name='o') 26 short_name='o')
27 gflags.DEFINE_string('packages', '', 27 gflags.DEFINE_string('packages', '',
28 'Space separated list of packages to mark as stable.', 28 'Colon-separated list of packages to mark as stable.',
diandersAtChromium 2010/11/12 19:25:30 Any easy way to detect other places that might hav
sosa 2010/11/12 19:38:09 CBuildbot is the only caller as this manages the p
29 short_name='p') 29 short_name='p')
30 gflags.DEFINE_string('push_options', '', 30 gflags.DEFINE_string('push_options', '',
31 'Options to use with git-cl push using push command.') 31 'Options to use with git-cl push using push command.')
32 gflags.DEFINE_string('srcroot', '%s/trunk/src' % os.environ['HOME'], 32 gflags.DEFINE_string('srcroot', '%s/trunk/src' % os.environ['HOME'],
33 'Path to root src directory.', 33 'Path to root src directory.',
34 short_name='r') 34 short_name='r')
35 gflags.DEFINE_string('tracking_branch', 'cros/master', 35 gflags.DEFINE_string('tracking_branch', 'cros/master',
36 'Used with commit to specify branch to track against.', 36 'Used with commit to specify branch to track against.',
37 short_name='t') 37 short_name='t')
38 gflags.DEFINE_boolean('all', False, 38 gflags.DEFINE_boolean('all', False,
(...skipping 22 matching lines...) Expand all
61 61
62 # ======================= Global Helper Functions ======================== 62 # ======================= Global Helper Functions ========================
63 63
64 64
65 def _Print(message): 65 def _Print(message):
66 """Verbose print function.""" 66 """Verbose print function."""
67 if gflags.FLAGS.verbose: 67 if gflags.FLAGS.verbose:
68 Info(message) 68 Info(message)
69 69
70 70
71 def _CleanStalePackages(board, package_array): 71 def _CleanStalePackages(board, package_array):
diandersAtChromium 2010/11/12 19:25:30 Downside of all the enter_chroot here: it will be
sosa 2010/11/12 19:38:09 This is a really good point I didn't think about.
davidjames 2010/11/12 21:18:05 Done.
72 """Cleans up stale package info from a previous build.""" 72 """Cleans up stale package info from a previous build."""
73 Info('Cleaning up stale packages %s.' % package_array) 73 Info('Cleaning up stale packages %s.' % package_array)
74 unmerge_board_cmd = ['emerge-%s' % board, '--unmerge'] 74 unmerge_board_cmd = ['emerge-%s' % board, '--unmerge']
75 unmerge_board_cmd.extend(package_array) 75 unmerge_board_cmd.extend(package_array)
76 RunCommand(unmerge_board_cmd) 76 RunCommand(unmerge_board_cmd, enter_chroot=True)
77 77
78 unmerge_host_cmd = ['sudo', 'emerge', '--unmerge'] 78 unmerge_host_cmd = ['sudo', 'emerge', '--unmerge']
79 unmerge_host_cmd.extend(package_array) 79 unmerge_host_cmd.extend(package_array)
80 RunCommand(unmerge_host_cmd) 80 RunCommand(unmerge_host_cmd, enter_chroot=True)
81 81
82 RunCommand(['eclean-%s' % board, '-d', 'packages'], redirect_stderr=True) 82 RunCommand(['eclean-%s' % board, '-d', 'packages'], redirect_stderr=True,
83 RunCommand(['sudo', 'eclean', '-d', 'packages'], redirect_stderr=True) 83 enter_chroot=True)
84 RunCommand(['sudo', 'eclean', '-d', 'packages'], redirect_stderr=True,
85 enter_chroot=True)
84 86
85 87
86 def _BestEBuild(ebuilds): 88 def _BestEBuild(ebuilds):
87 """Returns the newest EBuild from a list of EBuild objects.""" 89 """Returns the newest EBuild from a list of EBuild objects."""
88 from portage.versions import vercmp 90 from cros_portage_versions import vercmp
89 winner = ebuilds[0] 91 winner = ebuilds[0]
90 for ebuild in ebuilds[1:]: 92 for ebuild in ebuilds[1:]:
91 if vercmp(winner.version, ebuild.version) < 0: 93 if vercmp(winner.version, ebuild.version) < 0:
92 winner = ebuild 94 winner = ebuild
93 return winner 95 return winner
94 96
95 97
96 def _FindUprevCandidates(files): 98 def _FindUprevCandidates(files):
97 """Return a list of uprev candidates from specified list of files. 99 """Return a list of uprev candidates from specified list of files.
98 100
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 _SimpleRunCommand('git commit -m "%s"' % description) 240 _SimpleRunCommand('git commit -m "%s"' % description)
239 # Ugh. There has got to be an easier way to push to a tracking branch 241 # Ugh. There has got to be an easier way to push to a tracking branch
240 _SimpleRunCommand('git config push.default tracking') 242 _SimpleRunCommand('git config push.default tracking')
241 _SimpleRunCommand('git push') 243 _SimpleRunCommand('git push')
242 244
243 245
244 def _SimpleRunCommand(command): 246 def _SimpleRunCommand(command):
245 """Runs a shell command and returns stdout back to caller.""" 247 """Runs a shell command and returns stdout back to caller."""
246 _Print(' + %s' % command) 248 _Print(' + %s' % command)
247 proc_handle = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 249 proc_handle = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
248 return proc_handle.communicate()[0] 250 stdout = proc_handle.communicate()[0]
251 retcode = proc_handle.wait()
252 assert retcode == 0, "Return code %s for command: %s" % (retcode, command)
diandersAtChromium 2010/11/12 19:25:30 Not convinced that assert should be used here unle
sosa 2010/11/12 19:38:09 Throw an exception. On 2010/11/12 19:25:30, diand
davidjames 2010/11/12 21:18:05 Done.
253 return stdout
249 254
250 255
251 # ======================= End Global Helper Functions ======================== 256 # ======================= End Global Helper Functions ========================
252 257
253 258
254 class _GitBranch(object): 259 class _GitBranch(object):
255 """Wrapper class for a git branch.""" 260 """Wrapper class for a git branch."""
256 261
257 def __init__(self, branch_name): 262 def __init__(self, branch_name):
258 """Sets up variables but does not create the branch.""" 263 """Sets up variables but does not create the branch."""
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 295
291 class _EBuild(object): 296 class _EBuild(object):
292 """Wrapper class for an ebuild.""" 297 """Wrapper class for an ebuild."""
293 298
294 def __init__(self, path): 299 def __init__(self, path):
295 """Initializes all data about an ebuild. 300 """Initializes all data about an ebuild.
296 301
297 Uses equery to find the ebuild path and sets data about an ebuild for 302 Uses equery to find the ebuild path and sets data about an ebuild for
298 easy reference. 303 easy reference.
299 """ 304 """
300 from portage.versions import pkgsplit 305 from cros_portage_versions import pkgsplit
301 self.ebuild_path = path 306 self.ebuild_path = path
302 (self.ebuild_path_no_revision, 307 (self.ebuild_path_no_revision,
303 self.ebuild_path_no_version, 308 self.ebuild_path_no_version,
304 self.current_revision) = self._ParseEBuildPath(self.ebuild_path) 309 self.current_revision) = self._ParseEBuildPath(self.ebuild_path)
305 _, self.category, pkgpath, filename = path.rsplit('/', 3) 310 _, self.category, pkgpath, filename = path.rsplit('/', 3)
306 filename_no_suffix = os.path.join(filename.replace('.ebuild', '')) 311 filename_no_suffix = os.path.join(filename.replace('.ebuild', ''))
307 self.pkgname, version_no_rev, rev = pkgsplit(filename_no_suffix) 312 self.pkgname, version_no_rev, rev = pkgsplit(filename_no_suffix)
308 self.version = '%s-%s' % (version_no_rev, rev) 313 self.version = '%s-%s' % (version_no_rev, rev)
309 self.package = '%s/%s' % (self.category, self.pkgname) 314 self.package = '%s/%s' % (self.category, self.pkgname)
310 self.is_workon = False 315 self.is_workon = False
311 self.is_stable = False 316 self.is_stable = False
312 317
313 for line in fileinput.input(path): 318 for line in fileinput.input(path):
314 if line.startswith('inherit ') and 'cros-workon' in line: 319 if line.startswith('inherit ') and 'cros-workon' in line:
315 self.is_workon = True 320 self.is_workon = True
316 elif (line.startswith('KEYWORDS=') and '~' not in line and 321 elif (line.startswith('KEYWORDS=') and '~' not in line and
317 ('amd64' in line or 'x86' in line or 'arm' in line)): 322 ('amd64' in line or 'x86' in line or 'arm' in line)):
318 self.is_stable = True 323 self.is_stable = True
319 fileinput.close() 324 fileinput.close()
320 325
321 def GetCommitId(self): 326 def GetCommitId(self):
322 """Get the commit id for this ebuild.""" 327 """Get the commit id for this ebuild."""
323 328
324 # Grab and evaluate CROS_WORKON variables from this ebuild. 329 # Grab and evaluate CROS_WORKON variables from this ebuild.
325 unstable_ebuild = '%s-9999.ebuild' % self.ebuild_path_no_version 330 unstable_ebuild = '%s-9999.ebuild' % self.ebuild_path_no_version
326 cmd = ('CROS_WORKON_LOCALNAME="%s" CROS_WORKON_PROJECT="%s" ' 331 cmd = ('export CROS_WORKON_LOCALNAME="%s" CROS_WORKON_PROJECT="%s"; '
327 'eval $(grep -E "^CROS_WORKON" %s) && ' 332 'eval $(grep -E "^CROS_WORKON" %s) && '
328 'echo $CROS_WORKON_PROJECT ' 333 'echo $CROS_WORKON_PROJECT '
329 '$CROS_WORKON_LOCALNAME/$CROS_WORKON_SUBDIR' 334 '$CROS_WORKON_LOCALNAME/$CROS_WORKON_SUBDIR'
330 % (self.pkgname, self.pkgname, unstable_ebuild)) 335 % (self.pkgname, self.pkgname, unstable_ebuild))
331 project, subdir = _SimpleRunCommand(cmd).split() 336 project, subdir = _SimpleRunCommand(cmd).split()
332 337
333 # Calculate srcdir. 338 # Calculate srcdir.
334 srcroot = gflags.FLAGS.srcroot 339 srcroot = gflags.FLAGS.srcroot
335 if self.category == 'chromeos-base': 340 if self.category == 'chromeos-base':
336 dir = 'platform' 341 dir = 'platform'
(...skipping 28 matching lines...) Expand all
365 370
366 @classmethod 371 @classmethod
367 def _ParseEBuildPath(cls, ebuild_path): 372 def _ParseEBuildPath(cls, ebuild_path):
368 """Static method that parses the path of an ebuild 373 """Static method that parses the path of an ebuild
369 374
370 Returns a tuple containing the (ebuild path without the revision 375 Returns a tuple containing the (ebuild path without the revision
371 string, without the version string, and the current revision number for 376 string, without the version string, and the current revision number for
372 the ebuild). 377 the ebuild).
373 """ 378 """
374 # Get the ebuild name without the revision string. 379 # Get the ebuild name without the revision string.
375 (ebuild_no_rev, _, rev_string) = ebuild_path.rpartition('-') 380 (ebuild_no_rev, _, rev_string) = ebuild_path.rpartition('-')
diandersAtChromium 2010/11/12 19:25:30 It looks like you're sorta getting "lucky" that th
davidjames 2010/11/12 21:18:05 Just tested this. Looks like it works, and does no
376 381
377 # Verify the revision string starts with the revision character. 382 # Verify the revision string starts with the revision character.
378 if rev_string.startswith('r'): 383 if rev_string.startswith('r'):
379 # Get the ebuild name without the revision and version strings. 384 # Get the ebuild name without the revision and version strings.
380 ebuild_no_version = ebuild_no_rev.rpartition('-')[0] 385 ebuild_no_version = ebuild_no_rev.rpartition('-')[0]
381 rev_string = rev_string[1:].rpartition('.ebuild')[0] 386 rev_string = rev_string[1:].rpartition('.ebuild')[0]
382 else: 387 else:
383 # Has no revision so we stripped the version number instead. 388 # Has no revision so we stripped the version number instead.
diandersAtChromium 2010/11/12 19:25:30 Old case of having no revision number at all is no
sosa 2010/11/12 19:38:09 This handles the 9999 case for the above comment.
384 ebuild_no_version = ebuild_no_rev 389 ebuild_no_version = ebuild_no_rev
385 ebuild_no_rev = ebuild_path.rpartition('9999.ebuild')[0] + '0.0.1' 390 ebuild_no_rev = ebuild_path.rpartition('9999.ebuild')[0] + '0.0.1'
386 rev_string = '0' 391 rev_string = '0'
387 revision = int(rev_string) 392 revision = int(rev_string)
388 return (ebuild_no_rev, ebuild_no_version, revision) 393 return (ebuild_no_rev, ebuild_no_version, revision)
389 394
390 395
391 class EBuildStableMarker(object): 396 class EBuildStableMarker(object):
392 """Class that revs the ebuild and commits locally or pushes the change.""" 397 """Class that revs the ebuild and commits locally or pushes the change."""
393 398
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 def main(argv): 485 def main(argv):
481 try: 486 try:
482 argv = gflags.FLAGS(argv) 487 argv = gflags.FLAGS(argv)
483 if len(argv) != 2: 488 if len(argv) != 2:
484 _PrintUsageAndDie('Must specify a valid command') 489 _PrintUsageAndDie('Must specify a valid command')
485 else: 490 else:
486 command = argv[1] 491 command = argv[1]
487 except gflags.FlagsError, e : 492 except gflags.FlagsError, e :
488 _PrintUsageAndDie(str(e)) 493 _PrintUsageAndDie(str(e))
489 494
490 package_list = gflags.FLAGS.packages.split() 495 package_list = gflags.FLAGS.packages.split(':')
491 _CheckSaneArguments(package_list, command) 496 _CheckSaneArguments(package_list, command)
492 if gflags.FLAGS.overlays: 497 if gflags.FLAGS.overlays:
493 overlays = dict((path, []) for path in gflags.FLAGS.overlays.split()) 498 overlays = {}
499 for path in gflags.FLAGS.overlays.split(':'):
500 if not os.path.exists(path):
501 Die('Cannot find overlay: %s' % path)
502 overlays[path] = []
494 else: 503 else:
504 Warning('Missing --overlays argument')
495 overlays = { 505 overlays = {
496 '%s/private-overlays/chromeos-overlay' % gflags.FLAGS.srcroot: [], 506 '%s/private-overlays/chromeos-overlay' % gflags.FLAGS.srcroot: [],
497 '%s/third_party/chromiumos-overlay' % gflags.FLAGS.srcroot: [] 507 '%s/third_party/chromiumos-overlay' % gflags.FLAGS.srcroot: []
498 } 508 }
499 509
500 if command == 'commit': 510 if command == 'commit':
501 _BuildEBuildDictionary(overlays, gflags.FLAGS.all, package_list) 511 _BuildEBuildDictionary(overlays, gflags.FLAGS.all, package_list)
502 512
513 cwd = os.getcwd()
503 for overlay, ebuilds in overlays.items(): 514 for overlay, ebuilds in overlays.items():
504 if not os.path.exists(overlay): 515 if not os.path.exists(overlay):
505 Warning("Skipping %s" % overlay) 516 Warning("Skipping %s" % overlay)
506 continue 517 continue
507 os.chdir(overlay) 518 os.chdir(overlay)
diandersAtChromium 2010/11/12 19:25:30 Why is chdir here? What actually needs it? ...an
sosa 2010/11/12 19:38:09 For local git commits. On 2010/11/12 19:25:30, di
davidjames 2010/11/12 21:18:05 Added a comment.
508 519
509 if command == 'clean': 520 if command == 'clean':
510 _Clean() 521 _Clean()
511 elif command == 'push': 522 elif command == 'push':
512 _PushChange() 523 _PushChange()
513 elif command == 'commit' and ebuilds: 524 elif command == 'commit' and ebuilds:
514 work_branch = _GitBranch(_STABLE_BRANCH_NAME) 525 work_branch = _GitBranch(_STABLE_BRANCH_NAME)
515 work_branch.CreateBranch() 526 work_branch.CreateBranch()
516 if not work_branch.Exists(): 527 if not work_branch.Exists():
517 Die('Unable to create stabilizing branch in %s' % overlay) 528 Die('Unable to create stabilizing branch in %s' % overlay)
518 529
519 # Contains the array of packages we actually revved. 530 # Contains the array of packages we actually revved.
520 revved_packages = [] 531 revved_packages = []
521 for ebuild in ebuilds: 532 for ebuild in ebuilds:
522 try: 533 try:
523 _Print('Working on %s' % ebuild.package) 534 _Print('Working on %s' % ebuild.package)
524 worker = EBuildStableMarker(ebuild) 535 worker = EBuildStableMarker(ebuild)
525 commit_id = ebuild.GetCommitId() 536 commit_id = ebuild.GetCommitId()
526 if worker.RevEBuild(commit_id): 537 if worker.RevEBuild(commit_id):
527 message = _GIT_COMMIT_MESSAGE % (ebuild.package, commit_id) 538 message = _GIT_COMMIT_MESSAGE % (ebuild.package, commit_id)
528 worker.CommitChange(message) 539 worker.CommitChange(message)
529 revved_packages.append(ebuild.package) 540 revved_packages.append(ebuild.package)
530 541
531 except (OSError, IOError): 542 except (OSError, IOError):
532 Warning('Cannot rev %s\n' % ebuild.package, 543 Warning('Cannot rev %s\n' % ebuild.package,
533 'Note you will have to go into %s ' 544 'Note you will have to go into %s '
534 'and reset the git repo yourself.' % overlay) 545 'and reset the git repo yourself.' % overlay)
535 raise 546 raise
536 547
548 os.chdir(cwd)
sosa 2010/11/12 19:38:09 Why do you chdir back before work_branch.Delete???
davidjames 2010/11/12 21:18:05 Removed. This was necessary for entering the chro
537 if revved_packages: 549 if revved_packages:
538 _CleanStalePackages(gflags.FLAGS.board, revved_packages) 550 _CleanStalePackages(gflags.FLAGS.board, revved_packages)
539 else: 551 else:
540 work_branch.Delete() 552 work_branch.Delete()
541 553
542 554
543 if __name__ == '__main__': 555 if __name__ == '__main__':
544 main(sys.argv) 556 main(sys.argv)
OLDNEW
« bin/cbuildbot.py ('K') | « bin/cbuildbot_unittest.py ('k') | lib/cros_portage_versions.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698