OLD | NEW |
---|---|
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.', |
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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 _SimpleRunCommand('git commit -m "%s"' % description) | 238 _SimpleRunCommand('git commit -m "%s"' % description) |
239 # Ugh. There has got to be an easier way to push to a tracking branch | 239 # Ugh. There has got to be an easier way to push to a tracking branch |
240 _SimpleRunCommand('git config push.default tracking') | 240 _SimpleRunCommand('git config push.default tracking') |
241 _SimpleRunCommand('git push') | 241 _SimpleRunCommand('git push') |
242 | 242 |
243 | 243 |
244 def _SimpleRunCommand(command): | 244 def _SimpleRunCommand(command): |
245 """Runs a shell command and returns stdout back to caller.""" | 245 """Runs a shell command and returns stdout back to caller.""" |
246 _Print(' + %s' % command) | 246 _Print(' + %s' % command) |
247 proc_handle = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) | 247 proc_handle = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) |
248 return proc_handle.communicate()[0] | 248 stdout = proc_handle.communicate()[0] |
249 retcode = proc_handle.wait() | |
250 if retcode != 0: | |
251 raise subprocess.CalledProcessError(retcode, command, output=stdout) | |
252 return stdout | |
249 | 253 |
250 | 254 |
251 # ======================= End Global Helper Functions ======================== | 255 # ======================= End Global Helper Functions ======================== |
252 | 256 |
253 | 257 |
254 class _GitBranch(object): | 258 class _GitBranch(object): |
255 """Wrapper class for a git branch.""" | 259 """Wrapper class for a git branch.""" |
256 | 260 |
257 def __init__(self, branch_name): | 261 def __init__(self, branch_name): |
258 """Sets up variables but does not create the branch.""" | 262 """Sets up variables but does not create the branch.""" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 elif (line.startswith('KEYWORDS=') and '~' not in line and | 320 elif (line.startswith('KEYWORDS=') and '~' not in line and |
317 ('amd64' in line or 'x86' in line or 'arm' in line)): | 321 ('amd64' in line or 'x86' in line or 'arm' in line)): |
318 self.is_stable = True | 322 self.is_stable = True |
319 fileinput.close() | 323 fileinput.close() |
320 | 324 |
321 def GetCommitId(self): | 325 def GetCommitId(self): |
322 """Get the commit id for this ebuild.""" | 326 """Get the commit id for this ebuild.""" |
323 | 327 |
324 # Grab and evaluate CROS_WORKON variables from this ebuild. | 328 # Grab and evaluate CROS_WORKON variables from this ebuild. |
325 unstable_ebuild = '%s-9999.ebuild' % self.ebuild_path_no_version | 329 unstable_ebuild = '%s-9999.ebuild' % self.ebuild_path_no_version |
326 cmd = ('CROS_WORKON_LOCALNAME="%s" CROS_WORKON_PROJECT="%s" ' | 330 cmd = ('export CROS_WORKON_LOCALNAME="%s" CROS_WORKON_PROJECT="%s"; ' |
327 'eval $(grep -E "^CROS_WORKON" %s) && ' | 331 'eval $(grep -E "^CROS_WORKON" %s) && ' |
328 'echo $CROS_WORKON_PROJECT ' | 332 'echo $CROS_WORKON_PROJECT ' |
329 '$CROS_WORKON_LOCALNAME/$CROS_WORKON_SUBDIR' | 333 '$CROS_WORKON_LOCALNAME/$CROS_WORKON_SUBDIR' |
330 % (self.pkgname, self.pkgname, unstable_ebuild)) | 334 % (self.pkgname, self.pkgname, unstable_ebuild)) |
331 project, subdir = _SimpleRunCommand(cmd).split() | 335 project, subdir = _SimpleRunCommand(cmd).split() |
332 | 336 |
333 # Calculate srcdir. | 337 # Calculate srcdir. |
334 srcroot = gflags.FLAGS.srcroot | 338 srcroot = gflags.FLAGS.srcroot |
335 if self.category == 'chromeos-base': | 339 if self.category == 'chromeos-base': |
336 dir = 'platform' | 340 dir = 'platform' |
337 else: | 341 else: |
338 dir = 'third_party' | 342 dir = 'third_party' |
339 srcdir = os.path.join(srcroot, dir, subdir) | 343 srcdir = os.path.join(srcroot, dir, subdir) |
340 | 344 |
341 # TODO(anush): This hack is only necessary because the kernel ebuild has | 345 # TODO(anush): This hack is only necessary because the kernel ebuild has |
342 # 'if' statements, so we can't grab the CROS_WORKON_LOCALNAME properly. | 346 # 'if' statements, so we can't grab the CROS_WORKON_LOCALNAME properly. |
343 # We should clean up the kernel ebuild and remove this hack. | 347 # We should clean up the kernel ebuild and remove this hack. |
344 if not os.path.exists(srcdir) and subdir == 'kernel/': | 348 if not os.path.isdir(srcdir) and subdir == 'kernel/': |
345 srcdir = os.path.join(srcroot, 'third_party/kernel/files') | 349 srcdir = os.path.join(srcroot, 'third_party/kernel/files') |
346 | 350 |
347 if not os.path.exists(srcdir): | 351 if not os.path.isdir(srcdir): |
348 Die('Cannot find commit id for %s' % self.ebuild_path) | 352 Die('Cannot find commit id for %s' % self.ebuild_path) |
349 | 353 |
350 # Verify that we're grabbing the commit id from the right project name. | 354 # Verify that we're grabbing the commit id from the right project name. |
351 # NOTE: chromeos-kernel has the wrong project name, so it fails this | 355 # NOTE: chromeos-kernel has the wrong project name, so it fails this |
352 # check. | 356 # check. |
353 # TODO(davidjames): Fix the project name in the chromeos-kernel ebuild. | 357 # TODO(davidjames): Fix the project name in the chromeos-kernel ebuild. |
354 cmd = 'cd %s && git config --get remote.cros.projectname' % srcdir | 358 cmd = 'cd %s && git config --get remote.cros.projectname' % srcdir |
355 actual_project = _SimpleRunCommand(cmd).rstrip() | 359 actual_project = _SimpleRunCommand(cmd).rstrip() |
356 if project not in (actual_project, 'chromeos-kernel'): | 360 if project not in (actual_project, 'chromeos-kernel'): |
357 Die('Project name mismatch for %s (%s != %s)' % (unstable_ebuild, project, | 361 Die('Project name mismatch for %s (%s != %s)' % (unstable_ebuild, project, |
358 actual_project)) | 362 actual_project)) |
359 | 363 |
360 # Get commit id. | 364 # Get commit id. |
361 output = _SimpleRunCommand('cd %s && git rev-parse HEAD' % srcdir) | 365 output = _SimpleRunCommand('cd %s && git rev-parse HEAD' % srcdir) |
362 if not output: | 366 if not output: |
363 Die('Missing commit id for %s' % self.ebuild_path) | 367 Die('Missing commit id for %s' % self.ebuild_path) |
364 return output.rstrip() | 368 return output.rstrip() |
365 | 369 |
366 @classmethod | 370 @classmethod |
367 def _ParseEBuildPath(cls, ebuild_path): | 371 def _ParseEBuildPath(cls, ebuild_path): |
368 """Static method that parses the path of an ebuild | 372 """Static method that parses the path of an ebuild |
369 | 373 |
370 Returns a tuple containing the (ebuild path without the revision | 374 Returns a tuple containing the (ebuild path without the revision |
371 string, without the version string, and the current revision number for | 375 string, without the version string, and the current revision number for |
372 the ebuild). | 376 the ebuild). |
373 """ | 377 """ |
374 # Get the ebuild name without the revision string. | 378 # Get the ebuild name without the revision string. |
375 (ebuild_no_rev, _, rev_string) = ebuild_path.rpartition('-') | 379 (ebuild_no_rev, _, rev_string) = ebuild_path.rpartition('-') |
diandersAtChromium
2010/11/12 22:09:35
Sorry! I got confused with rsplit. :( Thanks fo
| |
376 | 380 |
377 # Verify the revision string starts with the revision character. | 381 # Verify the revision string starts with the revision character. |
378 if rev_string.startswith('r'): | 382 if rev_string.startswith('r'): |
379 # Get the ebuild name without the revision and version strings. | 383 # Get the ebuild name without the revision and version strings. |
380 ebuild_no_version = ebuild_no_rev.rpartition('-')[0] | 384 ebuild_no_version = ebuild_no_rev.rpartition('-')[0] |
381 rev_string = rev_string[1:].rpartition('.ebuild')[0] | 385 rev_string = rev_string[1:].rpartition('.ebuild')[0] |
382 else: | 386 else: |
383 # Has no revision so we stripped the version number instead. | 387 # Has no revision so we stripped the version number instead. |
diandersAtChromium
2010/11/12 22:09:35
I'm still confused how this would handle something
davidjames
2010/11/12 22:31:25
This looks like a real bug to me. But it's not new
| |
384 ebuild_no_version = ebuild_no_rev | 388 ebuild_no_version = ebuild_no_rev |
385 ebuild_no_rev = ebuild_path.rpartition('9999.ebuild')[0] + '0.0.1' | 389 ebuild_no_rev = ebuild_path.rpartition('9999.ebuild')[0] + '0.0.1' |
386 rev_string = '0' | 390 rev_string = '0' |
387 revision = int(rev_string) | 391 revision = int(rev_string) |
388 return (ebuild_no_rev, ebuild_no_version, revision) | 392 return (ebuild_no_rev, ebuild_no_version, revision) |
389 | 393 |
390 | 394 |
391 class EBuildStableMarker(object): | 395 class EBuildStableMarker(object): |
392 """Class that revs the ebuild and commits locally or pushes the change.""" | 396 """Class that revs the ebuild and commits locally or pushes the change.""" |
393 | 397 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
480 def main(argv): | 484 def main(argv): |
481 try: | 485 try: |
482 argv = gflags.FLAGS(argv) | 486 argv = gflags.FLAGS(argv) |
483 if len(argv) != 2: | 487 if len(argv) != 2: |
484 _PrintUsageAndDie('Must specify a valid command') | 488 _PrintUsageAndDie('Must specify a valid command') |
485 else: | 489 else: |
486 command = argv[1] | 490 command = argv[1] |
487 except gflags.FlagsError, e : | 491 except gflags.FlagsError, e : |
488 _PrintUsageAndDie(str(e)) | 492 _PrintUsageAndDie(str(e)) |
489 | 493 |
490 package_list = gflags.FLAGS.packages.split() | 494 package_list = gflags.FLAGS.packages.split(':') |
491 _CheckSaneArguments(package_list, command) | 495 _CheckSaneArguments(package_list, command) |
492 if gflags.FLAGS.overlays: | 496 if gflags.FLAGS.overlays: |
493 overlays = dict((path, []) for path in gflags.FLAGS.overlays.split()) | 497 overlays = {} |
498 for path in gflags.FLAGS.overlays.split(':'): | |
499 if not os.path.isdir(path): | |
500 Die('Cannot find overlay: %s' % path) | |
501 overlays[path] = [] | |
494 else: | 502 else: |
503 Warning('Missing --overlays argument') | |
495 overlays = { | 504 overlays = { |
496 '%s/private-overlays/chromeos-overlay' % gflags.FLAGS.srcroot: [], | 505 '%s/private-overlays/chromeos-overlay' % gflags.FLAGS.srcroot: [], |
497 '%s/third_party/chromiumos-overlay' % gflags.FLAGS.srcroot: [] | 506 '%s/third_party/chromiumos-overlay' % gflags.FLAGS.srcroot: [] |
498 } | 507 } |
499 | 508 |
500 if command == 'commit': | 509 if command == 'commit': |
501 _BuildEBuildDictionary(overlays, gflags.FLAGS.all, package_list) | 510 _BuildEBuildDictionary(overlays, gflags.FLAGS.all, package_list) |
502 | 511 |
503 for overlay, ebuilds in overlays.items(): | 512 for overlay, ebuilds in overlays.items(): |
504 if not os.path.exists(overlay): | 513 if not os.path.isdir(overlay): |
505 Warning("Skipping %s" % overlay) | 514 Warning("Skipping %s" % overlay) |
506 continue | 515 continue |
516 | |
517 # TODO(davidjames): Currently, all code that interacts with git depends on | |
518 # the cwd being set to the overlay directory. We should instead pass in | |
519 # this parameter so that we don't need to modify the cwd globally. | |
507 os.chdir(overlay) | 520 os.chdir(overlay) |
diandersAtChromium
2010/11/12 22:09:35
Technically, it would probably still be a good ide
davidjames
2010/11/12 22:31:25
Agreed. Since this is unrelated, I'm going to corr
| |
508 | 521 |
509 if command == 'clean': | 522 if command == 'clean': |
510 _Clean() | 523 _Clean() |
511 elif command == 'push': | 524 elif command == 'push': |
512 _PushChange() | 525 _PushChange() |
513 elif command == 'commit' and ebuilds: | 526 elif command == 'commit' and ebuilds: |
514 work_branch = _GitBranch(_STABLE_BRANCH_NAME) | 527 work_branch = _GitBranch(_STABLE_BRANCH_NAME) |
515 work_branch.CreateBranch() | 528 work_branch.CreateBranch() |
516 if not work_branch.Exists(): | 529 if not work_branch.Exists(): |
517 Die('Unable to create stabilizing branch in %s' % overlay) | 530 Die('Unable to create stabilizing branch in %s' % overlay) |
(...skipping 17 matching lines...) Expand all Loading... | |
535 raise | 548 raise |
536 | 549 |
537 if revved_packages: | 550 if revved_packages: |
538 _CleanStalePackages(gflags.FLAGS.board, revved_packages) | 551 _CleanStalePackages(gflags.FLAGS.board, revved_packages) |
539 else: | 552 else: |
540 work_branch.Delete() | 553 work_branch.Delete() |
541 | 554 |
542 | 555 |
543 if __name__ == '__main__': | 556 if __name__ == '__main__': |
544 main(sys.argv) | 557 main(sys.argv) |
OLD | NEW |