2 # Copyright (c) 2009, Google Inc. All rights reserved.
3 # Copyright (c) 2009 Apple Inc. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 from modules.comments import bug_comment_from_commit_text
32 from modules.logging import log
33 from modules.scm import ScriptError, CheckoutNeedsUpdate
34 from modules.webkitlandingscripts import WebKitLandingScripts, commit_message_for_this_commit
35 from modules.webkitport import WebKitPort
36 from modules.workqueue import WorkQueue
38 class LandingSequence:
39 def __init__(self, patch, options, tool):
41 self._options = options
43 self._port = WebKitPort.get_port(self._options)
50 commit_log = self.commit()
51 self.close_patch(commit_log)
54 def run_and_handle_errors(self):
57 except CheckoutNeedsUpdate, e:
58 log("Commit failed because the checkout is out of date. Please update and try again.")
59 log("You can pass --no-build to skip building/testing after update if you believe the new commits did not affect the results.")
60 WorkQueue.exit_after_handled_error(e)
61 except ScriptError, e:
62 if not self._options.quiet:
63 log(e.message_with_output())
64 if self._options.non_interactive:
65 # Mark the patch as commit-queue- and comment in the bug.
66 self._tool.bugs.reject_patch_from_commit_queue(self._patch["id"], e.message_with_output())
67 WorkQueue.exit_after_handled_error(e)
70 self._tool.scm().update_webkit()
72 def apply_patch(self):
73 log("Processing patch %s from bug %s." % (self._patch["id"], self._patch["bug_id"]))
74 self._tool.scm().apply_patch(self._patch, force=self._options.non_interactive)
77 # Make sure the tree is still green after updating, before building this patch.
78 # The first patch ends up checking tree status twice, but that's OK.
79 WebKitLandingScripts.ensure_builders_are_green(self._tool.buildbot, self._options)
80 WebKitLandingScripts.build_webkit(quiet=self._options.quiet, port=self._port)
83 # When running non-interactively we don't want to launch Safari and we want to exit after the first failure.
84 WebKitLandingScripts.run_webkit_tests(launch_safari=not self._options.non_interactive, fail_fast=self._options.non_interactive, quiet=self._options.quiet, port=self._port)
87 commit_message = commit_message_for_this_commit(self._tool.scm())
88 return self._tool.scm().commit_with_message(commit_message.message())
90 def close_patch(self, commit_log):
91 comment_text = bug_comment_from_commit_text(self._tool.scm(), commit_log)
92 self._tool.bugs.clear_attachment_flags(self._patch["id"], comment_text)
95 # Check to make sure there are no r? or r+ patches on the bug before closing.
96 # Assume that r- patches are just previous patches someone forgot to obsolete.
97 patches = self._tool.bugs.fetch_patches_from_bug(self._patch["bug_id"])
99 review_flag = patch.get("review")
100 if review_flag == "?" or review_flag == "+":
101 log("Not closing bug %s as attachment %s has review=%s. Assuming there are more patches to land from this bug." % (patch["bug_id"], patch["id"], review_flag))
103 self._tool.bugs.close_bug_as_fixed(self._patch["bug_id"], "All reviewed patches have been landed. Closing bug.")
106 class ConditionalLandingSequence(LandingSequence):
107 def __init__(self, patch, options, tool):
108 LandingSequence.__init__(self, patch, options, tool)
111 if self._options.build:
112 LandingSequence.build(self)
115 if self._options.build and self._options.test:
116 LandingSequence.test(self)
119 if self._options.close_bug:
120 LandingSequence.close_bug(self)