| OLD | NEW |
| 1 # Copyright (c) 2010 Google Inc. All rights reserved. | 1 # Copyright (c) 2010 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| 11 # in the documentation and/or other materials provided with the | 11 # in the documentation and/or other materials provided with the |
| 12 # distribution. | 12 # distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived from | 14 # contributors may be used to endorse or promote products derived from |
| 15 # this software without specific prior written permission. | 15 # this software without specific prior written permission. |
| 16 # | 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR/ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR/ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 import Queue | |
| 30 import json | 29 import json |
| 31 import logging | 30 import logging |
| 32 import optparse | 31 import optparse |
| 33 import re | 32 import re |
| 34 import sys | 33 import sys |
| 35 import threading | |
| 36 import time | 34 import time |
| 37 import traceback | 35 import traceback |
| 38 import urllib | |
| 39 import urllib2 | 36 import urllib2 |
| 40 | 37 |
| 41 from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer | 38 from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer |
| 42 from webkitpy.common.memoized import memoized | 39 from webkitpy.common.memoized import memoized |
| 43 from webkitpy.common.system.executive import ScriptError | 40 from webkitpy.common.system.executive import ScriptError |
| 44 from webkitpy.layout_tests.controllers.test_result_writer import TestResultWrite
r | 41 from webkitpy.layout_tests.controllers.test_result_writer import TestResultWrite
r |
| 45 from webkitpy.layout_tests.models import test_failures | |
| 46 from webkitpy.layout_tests.models.test_expectations import TestExpectations, BAS
ELINE_SUFFIX_LIST, SKIP | 42 from webkitpy.layout_tests.models.test_expectations import TestExpectations, BAS
ELINE_SUFFIX_LIST, SKIP |
| 47 from webkitpy.layout_tests.port import factory | 43 from webkitpy.layout_tests.port import factory |
| 48 from webkitpy.tool.commands.command import Command | 44 from webkitpy.tool.commands.command import Command |
| 49 | 45 |
| 50 | 46 |
| 51 _log = logging.getLogger(__name__) | 47 _log = logging.getLogger(__name__) |
| 52 | 48 |
| 53 | 49 |
| 54 # FIXME: Should TestResultWriter know how to compute this string? | 50 # FIXME: Should TestResultWriter know how to compute this string? |
| 55 def _baseline_name(fs, test_name, suffix): | 51 def _baseline_name(fs, test_name, suffix): |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 print json.dumps(self._scm_changes) | 178 print json.dumps(self._scm_changes) |
| 183 | 179 |
| 184 | 180 |
| 185 class RebaselineTest(BaseInternalRebaselineCommand): | 181 class RebaselineTest(BaseInternalRebaselineCommand): |
| 186 name = "rebaseline-test-internal" | 182 name = "rebaseline-test-internal" |
| 187 help_text = "Rebaseline a single test from a buildbot. Only intended for use
by other webkit-patch commands." | 183 help_text = "Rebaseline a single test from a buildbot. Only intended for use
by other webkit-patch commands." |
| 188 | 184 |
| 189 def _results_url(self, builder_name): | 185 def _results_url(self, builder_name): |
| 190 return self._tool.buildbot.builder_with_name(builder_name).latest_layout
_test_results_url() | 186 return self._tool.buildbot.builder_with_name(builder_name).latest_layout
_test_results_url() |
| 191 | 187 |
| 192 def _save_baseline(self, data, target_baseline, baseline_directory, test_nam
e, suffix): | 188 def _save_baseline(self, data, target_baseline): |
| 193 if not data: | 189 if not data: |
| 194 _log.debug("No baseline data to save.") | 190 _log.debug("No baseline data to save.") |
| 195 return | 191 return |
| 196 | 192 |
| 197 filesystem = self._tool.filesystem | 193 filesystem = self._tool.filesystem |
| 198 filesystem.maybe_make_directory(filesystem.dirname(target_baseline)) | 194 filesystem.maybe_make_directory(filesystem.dirname(target_baseline)) |
| 199 filesystem.write_binary_file(target_baseline, data) | 195 filesystem.write_binary_file(target_baseline, data) |
| 200 if not self._tool.scm().exists(target_baseline): | 196 if not self._tool.scm().exists(target_baseline): |
| 201 self._add_to_scm_later(target_baseline) | 197 self._add_to_scm_later(target_baseline) |
| 202 | 198 |
| 203 def _rebaseline_test(self, builder_name, test_name, suffix, results_url): | 199 def _rebaseline_test(self, builder_name, test_name, suffix, results_url): |
| 204 baseline_directory = self._baseline_directory(builder_name) | 200 baseline_directory = self._baseline_directory(builder_name) |
| 205 | 201 |
| 206 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res
ult(test_name, suffix)) | 202 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res
ult(test_name, suffix)) |
| 207 target_baseline = self._tool.filesystem.join(baseline_directory, self._f
ile_name_for_expected_result(test_name, suffix)) | 203 target_baseline = self._tool.filesystem.join(baseline_directory, self._f
ile_name_for_expected_result(test_name, suffix)) |
| 208 | 204 |
| 209 _log.debug("Retrieving %s." % source_baseline) | 205 _log.debug("Retrieving %s." % source_baseline) |
| 210 self._save_baseline(self._tool.web.get_binary(source_baseline, convert_4
04_to_None=True), | 206 self._save_baseline(self._tool.web.get_binary(source_baseline, convert_4
04_to_None=True), |
| 211 target_baseline, baseline_directory, test_name, suff
ix) | 207 target_baseline) |
| 212 | 208 |
| 213 def _rebaseline_test_and_update_expectations(self, options): | 209 def _rebaseline_test_and_update_expectations(self, options): |
| 214 self._baseline_suffix_list = options.suffixes.split(',') | 210 self._baseline_suffix_list = options.suffixes.split(',') |
| 215 | 211 |
| 216 port = self._tool.port_factory.get_from_builder_name(options.builder) | 212 port = self._tool.port_factory.get_from_builder_name(options.builder) |
| 217 if port.reference_files(options.test): | 213 if port.reference_files(options.test): |
| 218 if 'png' in self._baseline_suffix_list: | 214 if 'png' in self._baseline_suffix_list: |
| 219 _log.warning("Cannot rebaseline image result for reftest: %s", o
ptions.test) | 215 _log.warning("Cannot rebaseline image result for reftest: %s", o
ptions.test) |
| 220 return | 216 return |
| 221 assert self._baseline_suffix_list == ['txt'] | 217 assert self._baseline_suffix_list == ['txt'] |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 | 862 |
| 867 if not options.dry_run and tool.scm().has_working_directory_changes(): | 863 if not options.dry_run and tool.scm().has_working_directory_changes(): |
| 868 _log.error("Cannot proceed with working directory changes. Clean wor
king directory first.") | 864 _log.error("Cannot proceed with working directory changes. Clean wor
king directory first.") |
| 869 return | 865 return |
| 870 | 866 |
| 871 revision_data = self.bot_revision_data() | 867 revision_data = self.bot_revision_data() |
| 872 if not revision_data: | 868 if not revision_data: |
| 873 return | 869 return |
| 874 | 870 |
| 875 min_revision = int(min([item["revision"] for item in revision_data])) | 871 min_revision = int(min([item["revision"] for item in revision_data])) |
| 876 tests, revision, commit, author, bugs, has_any_needs_rebaseline_lines =
self.tests_to_rebaseline( | 872 tests, revision, commit, author, bugs, _ = self.tests_to_rebaseline( |
| 877 tool, min_revision, print_revisions=options.verbose) | 873 tool, min_revision, print_revisions=options.verbose) |
| 878 | 874 |
| 879 if options.verbose: | 875 if options.verbose: |
| 880 _log.info("Min revision across all bots is %s." % min_revision) | 876 _log.info("Min revision across all bots is %s." % min_revision) |
| 881 for item in revision_data: | 877 for item in revision_data: |
| 882 _log.info("%s: r%s" % (item["builder"], item["revision"])) | 878 _log.info("%s: r%s" % (item["builder"], item["revision"])) |
| 883 | 879 |
| 884 if not tests: | 880 if not tests: |
| 885 _log.debug('No tests to rebaseline.') | 881 _log.debug('No tests to rebaseline.') |
| 886 return | 882 return |
| 887 | 883 |
| 888 if self.tree_status() == 'closed': | 884 if self.tree_status() == 'closed': |
| 889 _log.info('Cannot proceed. Tree is closed.') | 885 _log.info('Cannot proceed. Tree is closed.') |
| 890 return | 886 return |
| 891 | 887 |
| 892 _log.info('Rebaselining %s for r%s by %s.' % (list(tests), revision, aut
hor)) | 888 _log.info('Rebaselining %s for r%s by %s.' % (list(tests), revision, aut
hor)) |
| 893 | 889 |
| 894 test_prefix_list, lines_to_remove = self.get_test_prefix_list(tests) | 890 test_prefix_list, _ = self.get_test_prefix_list(tests) |
| 895 | 891 |
| 896 did_switch_branches = False | 892 did_switch_branches = False |
| 897 did_finish = False | 893 did_finish = False |
| 898 old_branch_name_or_ref = '' | 894 old_branch_name_or_ref = '' |
| 899 rebaseline_branch_name = self.AUTO_REBASELINE_BRANCH_NAME | 895 rebaseline_branch_name = self.AUTO_REBASELINE_BRANCH_NAME |
| 900 try: | 896 try: |
| 901 # Save the current branch name and check out a clean branch for the
patch. | 897 # Save the current branch name and check out a clean branch for the
patch. |
| 902 old_branch_name_or_ref = tool.scm().current_branch_or_ref() | 898 old_branch_name_or_ref = tool.scm().current_branch_or_ref() |
| 903 if old_branch_name_or_ref == self.AUTO_REBASELINE_BRANCH_NAME: | 899 if old_branch_name_or_ref == self.AUTO_REBASELINE_BRANCH_NAME: |
| 904 rebaseline_branch_name = self.AUTO_REBASELINE_ALT_BRANCH_NAME | 900 rebaseline_branch_name = self.AUTO_REBASELINE_ALT_BRANCH_NAME |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 issue_already_closed = tool.executive.run_command( | 934 issue_already_closed = tool.executive.run_command( |
| 939 ['git', 'config', 'branch.%s.rietveldissue' % rebaseline
_branch_name], | 935 ['git', 'config', 'branch.%s.rietveldissue' % rebaseline
_branch_name], |
| 940 return_exit_code=True) | 936 return_exit_code=True) |
| 941 if not issue_already_closed: | 937 if not issue_already_closed: |
| 942 self._run_git_cl_command(options, ['set_close']) | 938 self._run_git_cl_command(options, ['set_close']) |
| 943 | 939 |
| 944 tool.scm().ensure_cleanly_tracking_remote_master() | 940 tool.scm().ensure_cleanly_tracking_remote_master() |
| 945 if old_branch_name_or_ref: | 941 if old_branch_name_or_ref: |
| 946 tool.scm().checkout_branch(old_branch_name_or_ref) | 942 tool.scm().checkout_branch(old_branch_name_or_ref) |
| 947 tool.scm().delete_branch(rebaseline_branch_name) | 943 tool.scm().delete_branch(rebaseline_branch_name) |
| OLD | NEW |