Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """A subclass of commands.SVN that allows more flexible error recovery. | 5 """A subclass of commands.SVN that allows more flexible error recovery. |
| 6 | 6 |
| 7 This code is only used on the slave but it is living in common/ because it is | 7 This code is only used on the slave but it is living in common/ because it is |
| 8 directly imported from buildbot/slave/bot.py.""" | 8 directly imported from buildbot/slave/bot.py.""" |
| 9 | 9 |
| 10 import os | 10 import os |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 self.gclient_deps = args.get('gclient_deps') | 262 self.gclient_deps = args.get('gclient_deps') |
| 263 self.sourcedata = '%s\n' % self.svnurl | 263 self.sourcedata = '%s\n' % self.svnurl |
| 264 self.rm_timeout = args.get('rm_timeout', self.timeout) | 264 self.rm_timeout = args.get('rm_timeout', self.timeout) |
| 265 self.env = args.get('env') | 265 self.env = args.get('env') |
| 266 self.gclient_nohooks = args.get('gclient_nohooks', False) | 266 self.gclient_nohooks = args.get('gclient_nohooks', False) |
| 267 self.env['CHROMIUM_GYP_SYNTAX_CHECK'] = '1' | 267 self.env['CHROMIUM_GYP_SYNTAX_CHECK'] = '1' |
| 268 self.no_gclient_branch = args.get('no_gclient_branch') | 268 self.no_gclient_branch = args.get('no_gclient_branch') |
| 269 self.no_gclient_revision = args.get('no_gclient_revision', False) | 269 self.no_gclient_revision = args.get('no_gclient_revision', False) |
| 270 self.gclient_transitive = args.get('gclient_transitive') | 270 self.gclient_transitive = args.get('gclient_transitive') |
| 271 self.gclient_jobs = args.get('gclient_jobs') | 271 self.gclient_jobs = args.get('gclient_jobs') |
| 272 self.do_nothing = False | |
| 272 | 273 |
| 273 def start(self): | 274 def start(self): |
| 274 """Start the update process. | 275 """Start the update process. |
| 275 | 276 |
| 276 start() is cut-and-paste from the base class, the block calling | 277 start() is cut-and-paste from the base class, the block calling |
| 277 self.sourcedirIsPatched() and the revert support is the only functional | 278 self.sourcedirIsPatched() and the revert support is the only functional |
| 278 difference from base.""" | 279 difference from base.""" |
| 279 self.sendStatus({'header': "starting " + self.header + "\n"}) | 280 self.sendStatus({'header': "starting " + self.header + "\n"}) |
| 280 self.command = None | 281 self.command = None |
| 281 | 282 |
| 282 # self.srcdir is where the VC system should put the sources | 283 # self.srcdir is where the VC system should put the sources |
| 283 if self.mode == "copy": | 284 if self.mode == "copy": |
| 284 self.srcdir = "source" # hardwired directory name, sorry | 285 self.srcdir = "source" # hardwired directory name, sorry |
| 285 else: | 286 else: |
| 286 self.srcdir = self.workdir | 287 self.srcdir = self.workdir |
| 287 self.sourcedatafile = os.path.join(self.builder.basedir, | 288 self.sourcedatafile = os.path.join(self.builder.basedir, |
| 288 self.srcdir, | 289 self.srcdir, |
| 289 ".buildbot-sourcedata") | 290 ".buildbot-sourcedata") |
| 291 self.do_nothing = os.path.isfile(os.path.join(self.builder.basedir, | |
| 292 self.srcdir, | |
| 293 'update.flag')) | |
| 290 | 294 |
| 291 d = defer.succeed(None) | 295 d = defer.succeed(0) |
| 296 | |
| 297 if self.do_nothing: | |
| 298 # If bot update is run, we don't need to run the traditional update step. | |
| 299 self.sendStatus({'header': 'Found flag file, see "bot update" step, ' | |
| 300 'exiting\n'}) | |
|
agable
2014/02/07 04:47:40
This message should match the messages in the othe
Ryan Tseng
2014/02/07 21:23:07
Done.
| |
| 301 d.addCallback(self._sendRC) | |
| 302 return d | |
| 303 | |
| 292 # Do we need to clobber anything? | 304 # Do we need to clobber anything? |
| 293 if self.mode in ("copy", "clobber", "export"): | 305 if self.mode in ("copy", "clobber", "export"): |
| 294 d.addCallback(self.doClobber, self.workdir) | 306 d.addCallback(self.doClobber, self.workdir) |
| 295 if not (self.sourcedirIsUpdateable() and self.sourcedataMatches()): | 307 if not (self.sourcedirIsUpdateable() and self.sourcedataMatches()): |
| 296 # the directory cannot be updated, so we have to clobber it. | 308 # the directory cannot be updated, so we have to clobber it. |
| 297 # Perhaps the master just changed modes from 'export' to | 309 # Perhaps the master just changed modes from 'export' to |
| 298 # 'update'. | 310 # 'update'. |
| 299 d.addCallback(self.doClobber, self.srcdir) | 311 d.addCallback(self.doClobber, self.srcdir) |
| 300 elif self.sourcedirIsPatched(): | 312 elif self.sourcedirIsPatched(): |
| 301 # The directory is patched. Revert the sources. | 313 # The directory is patched. Revert the sources. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 cmd = ['python', '-c', | 348 cmd = ['python', '-c', |
| 337 'from common import chromium_utils; ' | 349 'from common import chromium_utils; ' |
| 338 'chromium_utils.RemoveDirectory("%s")' % rm_dir.replace('\\', '/')] | 350 'chromium_utils.RemoveDirectory("%s")' % rm_dir.replace('\\', '/')] |
| 339 if self.sudo_for_remove: | 351 if self.sudo_for_remove: |
| 340 cmd = ['sudo'] + cmd | 352 cmd = ['sudo'] + cmd |
| 341 return cmd | 353 return cmd |
| 342 | 354 |
| 343 def doGclientUpdate(self): | 355 def doGclientUpdate(self): |
| 344 """Sync the client | 356 """Sync the client |
| 345 """ | 357 """ |
| 358 self.sendStatus({'header': "In Gclient Update\n"}) | |
| 359 if self.do_nothing: | |
| 360 return defer.Deferred() | |
| 346 dirname = os.path.join(self.builder.basedir, self.srcdir) | 361 dirname = os.path.join(self.builder.basedir, self.srcdir) |
| 347 command = [chromium_utils.GetGClientCommand(), | 362 command = [chromium_utils.GetGClientCommand(), |
| 348 'sync', '--verbose', '--reset', '--manually_grab_svn_rev', | 363 'sync', '--verbose', '--reset', '--manually_grab_svn_rev', |
| 349 '--force', '--with_branch_heads'] | 364 '--force', '--with_branch_heads'] |
| 350 if self.delete_unversioned_trees_when_updating: | 365 if self.delete_unversioned_trees_when_updating: |
| 351 command.append('--delete_unversioned_trees') | 366 command.append('--delete_unversioned_trees') |
| 352 if self.gclient_jobs: | 367 if self.gclient_jobs: |
| 353 command.append('-j%d' % self.gclient_jobs) | 368 command.append('-j%d' % self.gclient_jobs) |
| 354 # Don't run hooks if it was patched or there is a patch since runhooks will | 369 # Don't run hooks if it was patched or there is a patch since runhooks will |
| 355 # be run after. | 370 # be run after. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 380 c = runprocess.RunProcess( | 395 c = runprocess.RunProcess( |
| 381 self.builder, command, dirname, | 396 self.builder, command, dirname, |
| 382 sendRC=False, timeout=self.timeout, | 397 sendRC=False, timeout=self.timeout, |
| 383 keepStdout=True, environ=self.env) | 398 keepStdout=True, environ=self.env) |
| 384 self.command = c | 399 self.command = c |
| 385 return c.start() | 400 return c.start() |
| 386 | 401 |
| 387 def getGclientConfigCommand(self): | 402 def getGclientConfigCommand(self): |
| 388 """Return the command to run the gclient config step. | 403 """Return the command to run the gclient config step. |
| 389 """ | 404 """ |
| 405 self.sendStatus({'header': "In Gclient Config\n"}) | |
| 406 if self.do_nothing: | |
| 407 return defer.Deferred() | |
| 390 dirname = os.path.join(self.builder.basedir, self.srcdir) | 408 dirname = os.path.join(self.builder.basedir, self.srcdir) |
| 391 command = [chromium_utils.GetGClientCommand(), 'config'] | 409 command = [chromium_utils.GetGClientCommand(), 'config'] |
| 392 | 410 |
| 393 if self.gclient_spec: | 411 if self.gclient_spec: |
| 394 command.append('--spec=%s' % self.gclient_spec) | 412 command.append('--spec=%s' % self.gclient_spec) |
| 395 else: | 413 else: |
| 396 command.append(self.svnurl) | 414 command.append(self.svnurl) |
| 397 | 415 |
| 398 git_cache_dir = os.path.abspath( | 416 git_cache_dir = os.path.abspath( |
| 399 os.path.join(self.builder.basedir, os.pardir, os.pardir, os.pardir, | 417 os.path.join(self.builder.basedir, os.pardir, os.pardir, os.pardir, |
| 400 'git_cache')) | 418 'git_cache')) |
| 401 command.append('--cache-dir=' + git_cache_dir) | 419 command.append('--cache-dir=' + git_cache_dir) |
| 402 c = runprocess.RunProcess( | 420 c = runprocess.RunProcess( |
| 403 self.builder, command, dirname, | 421 self.builder, command, dirname, |
| 404 sendRC=False, timeout=self.timeout, | 422 sendRC=False, timeout=self.timeout, |
| 405 keepStdout=True, environ=self.env) | 423 keepStdout=True, environ=self.env) |
| 406 return c | 424 return c |
| 407 | 425 |
| 408 def doVCUpdate(self): | 426 def doVCUpdate(self): |
| 409 """Sync the client | 427 """Sync the client |
| 410 """ | 428 """ |
| 429 self.sendStatus({'header': "In VC Update\n"}) | |
|
agable
2014/02/07 04:47:40
Not sure why you introduced these sendStatus calls
Ryan Tseng
2014/02/07 21:23:07
Oh weird I totally thought i took these out, fixed
| |
| 430 if self.do_nothing: | |
| 431 return defer.Deferred() | |
| 411 # Make sure the .gclient is updated. | 432 # Make sure the .gclient is updated. |
| 412 os.remove(os.path.join(self.builder.basedir, self.srcdir, '.gclient')) | 433 os.remove(os.path.join(self.builder.basedir, self.srcdir, '.gclient')) |
| 413 c = self.getGclientConfigCommand() | 434 c = self.getGclientConfigCommand() |
| 414 self.command = c | 435 self.command = c |
| 415 d = c.start() | 436 d = c.start() |
| 416 d.addCallback(self._abandonOnFailure) | 437 d.addCallback(self._abandonOnFailure) |
| 417 d.addCallback(lambda _: self.doGclientUpdate()) | 438 d.addCallback(lambda _: self.doGclientUpdate()) |
| 418 return d | 439 return d |
| 419 | 440 |
| 420 def doVCFull(self): | 441 def doVCFull(self): |
| 421 """Setup the .gclient file and then sync | 442 """Setup the .gclient file and then sync |
| 422 """ | 443 """ |
| 444 self.sendStatus({'header': "In VC Full\n"}) | |
| 445 if self.do_nothing: | |
| 446 return defer.Deferred() | |
| 423 chromium_utils.MaybeMakeDirectory(self.builder.basedir, self.srcdir) | 447 chromium_utils.MaybeMakeDirectory(self.builder.basedir, self.srcdir) |
| 424 | 448 |
| 425 c = self.getGclientConfigCommand() | 449 c = self.getGclientConfigCommand() |
| 426 self.command = c | 450 self.command = c |
| 427 d = c.start() | 451 d = c.start() |
| 428 d.addCallback(self._abandonOnFailure) | 452 d.addCallback(self._abandonOnFailure) |
| 429 d.addCallback(lambda _: self.doGclientUpdate()) | 453 d.addCallback(lambda _: self.doGclientUpdate()) |
| 430 return d | 454 return d |
| 431 | 455 |
| 432 def doClobber(self, dummy, dirname, _=False): | 456 def doClobber(self, dummy, dirname, _=False): |
| 433 """Move the old directory aside, or delete it if that's already been done. | 457 """Move the old directory aside, or delete it if that's already been done. |
| 434 | 458 |
| 435 This function is designed to be used with a source dir. If it's called | 459 This function is designed to be used with a source dir. If it's called |
| 436 with anything else, the caller will need to be sure to clean up the | 460 with anything else, the caller will need to be sure to clean up the |
| 437 <dirname>.dead directory once it's no longer needed. | 461 <dirname>.dead directory once it's no longer needed. |
| 438 | 462 |
| 439 If this is the first time we're clobbering since we last finished a | 463 If this is the first time we're clobbering since we last finished a |
| 440 successful update or checkout, move the old directory aside so a human | 464 successful update or checkout, move the old directory aside so a human |
| 441 can try to recover from it if desired. Otherwise -- if such a backup | 465 can try to recover from it if desired. Otherwise -- if such a backup |
| 442 directory already exists, because this isn't the first retry -- just | 466 directory already exists, because this isn't the first retry -- just |
| 443 remove the old directory. | 467 remove the old directory. |
| 444 | 468 |
| 445 Args: | 469 Args: |
| 446 dummy: unused | 470 dummy: unused |
| 447 dirname: the directory within self.builder.basedir to be clobbered | 471 dirname: the directory within self.builder.basedir to be clobbered |
| 448 """ | 472 """ |
| 473 if self.do_nothing: | |
| 474 return defer.Deferred() | |
| 449 old_dir = os.path.join(self.builder.basedir, dirname) | 475 old_dir = os.path.join(self.builder.basedir, dirname) |
| 450 dead_dir = old_dir + '.dead' | 476 dead_dir = old_dir + '.dead' |
| 451 if os.path.isdir(old_dir): | 477 if os.path.isdir(old_dir): |
| 452 if os.path.isdir(dead_dir): | 478 if os.path.isdir(dead_dir): |
| 453 command = self._RemoveDirectoryCommand(old_dir) | 479 command = self._RemoveDirectoryCommand(old_dir) |
| 454 else: | 480 else: |
| 455 command = _RenameDirectoryCommand(old_dir, dead_dir) | 481 command = _RenameDirectoryCommand(old_dir, dead_dir) |
| 456 c = runprocess.RunProcess( | 482 c = runprocess.RunProcess( |
| 457 self.builder, command, self.builder.basedir, | 483 self.builder, command, self.builder.basedir, |
| 458 sendRC=0, timeout=self.rm_timeout, | 484 sendRC=0, timeout=self.rm_timeout, |
| 459 environ=self.env) | 485 environ=self.env) |
| 460 self.command = c | 486 self.command = c |
| 461 # See commands.SVN.doClobber for notes about sendRC. | 487 # See commands.SVN.doClobber for notes about sendRC. |
| 462 d = c.start() | 488 d = c.start() |
| 463 d.addCallback(self._abandonOnFailure) | 489 d.addCallback(self._abandonOnFailure) |
| 464 return d | 490 return d |
| 465 return None | 491 return None |
| 466 | 492 |
| 467 def doRevert(self, dummy): | 493 def doRevert(self, dummy): |
| 468 """Revert any modification done by a previous patch. | 494 """Revert any modification done by a previous patch. |
| 469 | 495 |
| 470 This is done in 2 parts to trap potential errors at each step. Note that | 496 This is done in 2 parts to trap potential errors at each step. Note that |
| 471 it is assumed that .orig and .rej files will be reverted, e.g. deleted by | 497 it is assumed that .orig and .rej files will be reverted, e.g. deleted by |
| 472 the 'gclient revert' command. If the try bot is configured with | 498 the 'gclient revert' command. If the try bot is configured with |
| 473 'global-ignores=*.orig', patch failure will occur.""" | 499 'global-ignores=*.orig', patch failure will occur.""" |
| 500 if self.do_nothing: | |
| 501 return defer.Deferred() | |
| 474 dirname = os.path.join(self.builder.basedir, self.srcdir) | 502 dirname = os.path.join(self.builder.basedir, self.srcdir) |
| 475 command = [chromium_utils.GetGClientCommand(), 'revert', '--nohooks'] | 503 command = [chromium_utils.GetGClientCommand(), 'revert', '--nohooks'] |
| 476 c = runprocess.RunProcess( | 504 c = runprocess.RunProcess( |
| 477 self.builder, command, dirname, | 505 self.builder, command, dirname, |
| 478 sendRC=False, timeout=self.timeout, | 506 sendRC=False, timeout=self.timeout, |
| 479 keepStdout=True, environ=self.env) | 507 keepStdout=True, environ=self.env) |
| 480 self.command = c | 508 self.command = c |
| 481 d = c.start() | 509 d = c.start() |
| 482 d.addCallback(self._abandonOnFailure) | 510 d.addCallback(self._abandonOnFailure) |
| 483 # Remove patch residues. | 511 # Remove patch residues. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 495 c = runprocess.RunProcess( | 523 c = runprocess.RunProcess( |
| 496 self.builder, command, dirname, | 524 self.builder, command, dirname, |
| 497 sendRC=False, timeout=self.timeout, | 525 sendRC=False, timeout=self.timeout, |
| 498 keepStdout=True, environ=self.env) | 526 keepStdout=True, environ=self.env) |
| 499 self.command = c | 527 self.command = c |
| 500 d = c.start() | 528 d = c.start() |
| 501 d.addCallback(self._abandonOnFailure) | 529 d.addCallback(self._abandonOnFailure) |
| 502 return d | 530 return d |
| 503 | 531 |
| 504 def doPatch(self, res): | 532 def doPatch(self, res): |
| 533 if self.do_nothing: | |
| 534 return defer.Deferred() | |
| 505 patchlevel = self.patch[0] | 535 patchlevel = self.patch[0] |
| 506 diff = FixDiffLineEnding(self.patch[1]) | 536 diff = FixDiffLineEnding(self.patch[1]) |
| 507 | 537 |
| 508 # Allow overwriting the root with an environment variable. | 538 # Allow overwriting the root with an environment variable. |
| 509 root = self.env.get("GCLIENT_PATCH_ROOT", None) | 539 root = self.env.get("GCLIENT_PATCH_ROOT", None) |
| 510 | 540 |
| 511 if len(self.patch) >= 3 and root is None: | 541 if len(self.patch) >= 3 and root is None: |
| 512 root = self.patch[2] | 542 root = self.patch[2] |
| 513 command = [ | 543 command = [ |
| 514 self.getCommand("patch"), | 544 self.getCommand("patch"), |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 535 initialStdin=diff, environ=self.env) | 565 initialStdin=diff, environ=self.env) |
| 536 self.command = c | 566 self.command = c |
| 537 d = c.start() | 567 d = c.start() |
| 538 d.addCallback(self._abandonOnFailure) | 568 d.addCallback(self._abandonOnFailure) |
| 539 if diff.find('DEPS') != -1: | 569 if diff.find('DEPS') != -1: |
| 540 d.addCallback(self.doVCUpdateOnPatch) | 570 d.addCallback(self.doVCUpdateOnPatch) |
| 541 d.addCallback(self._abandonOnFailure) | 571 d.addCallback(self._abandonOnFailure) |
| 542 return d | 572 return d |
| 543 | 573 |
| 544 def doVCUpdateOnPatch(self, res): | 574 def doVCUpdateOnPatch(self, res): |
| 575 if self.do_nothing: | |
| 576 return defer.Deferred() | |
| 545 if self.revision and not self.branch and '@' not in str(self.revision): | 577 if self.revision and not self.branch and '@' not in str(self.revision): |
| 546 self.branch = 'src' | 578 self.branch = 'src' |
| 547 self.delete_unversioned_trees_when_updating = False | 579 self.delete_unversioned_trees_when_updating = False |
| 548 return self.doVCUpdate() | 580 return self.doVCUpdate() |
| 549 | 581 |
| 550 def doRunHooks(self, dummy): | 582 def doRunHooks(self, dummy): |
| 551 """Runs "gclient runhooks" after patching.""" | 583 """Runs "gclient runhooks" after patching.""" |
| 552 dirname = os.path.join(self.builder.basedir, self.srcdir) | 584 dirname = os.path.join(self.builder.basedir, self.srcdir) |
| 553 command = [chromium_utils.GetGClientCommand(), 'runhooks'] | 585 command = [chromium_utils.GetGClientCommand(), 'runhooks'] |
| 554 c = runprocess.RunProcess( | 586 c = runprocess.RunProcess( |
| 555 self.builder, command, dirname, | 587 self.builder, command, dirname, |
| 556 sendRC=False, timeout=self.timeout, | 588 sendRC=False, timeout=self.timeout, |
| 557 keepStdout=True, environ=self.env) | 589 keepStdout=True, environ=self.env) |
| 558 self.command = c | 590 self.command = c |
| 559 d = c.start() | 591 d = c.start() |
| 560 d.addCallback(self._abandonOnFailure) | 592 d.addCallback(self._abandonOnFailure) |
| 561 return d | 593 return d |
| 562 | 594 |
| 563 def writeSourcedata(self, res): | 595 def writeSourcedata(self, res): |
| 564 """Write the sourcedata file and remove any dead source directory.""" | 596 """Write the sourcedata file and remove any dead source directory.""" |
| 597 if self.do_nothing: | |
| 598 return defer.Deferred() | |
| 565 dead_dir = os.path.join(self.builder.basedir, self.srcdir + '.dead') | 599 dead_dir = os.path.join(self.builder.basedir, self.srcdir + '.dead') |
| 566 if os.path.isdir(dead_dir): | 600 if os.path.isdir(dead_dir): |
| 567 msg = 'Removing dead source dir' | 601 msg = 'Removing dead source dir' |
| 568 self.sendStatus({'header': msg + '\n'}) | 602 self.sendStatus({'header': msg + '\n'}) |
| 569 log.msg(msg) | 603 log.msg(msg) |
| 570 command = self._RemoveDirectoryCommand(dead_dir) | 604 command = self._RemoveDirectoryCommand(dead_dir) |
| 571 c = runprocess.RunProcess( | 605 c = runprocess.RunProcess( |
| 572 self.builder, command, self.builder.basedir, | 606 self.builder, command, self.builder.basedir, |
| 573 sendRC=0, timeout=self.rm_timeout, | 607 sendRC=0, timeout=self.rm_timeout, |
| 574 environ=self.env) | 608 environ=self.env) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 try: | 657 try: |
| 624 # We run this code in a try because it fails with an assertion if | 658 # We run this code in a try because it fails with an assertion if |
| 625 # the module is loaded twice. | 659 # the module is loaded twice. |
| 626 commandRegistry['gclient'] = 'slave.chromium_commands.GClient' | 660 commandRegistry['gclient'] = 'slave.chromium_commands.GClient' |
| 627 return | 661 return |
| 628 except (AssertionError, NameError): | 662 except (AssertionError, NameError): |
| 629 pass | 663 pass |
| 630 | 664 |
| 631 | 665 |
| 632 RegisterCommands() | 666 RegisterCommands() |
| OLD | NEW |