| # Copyright (c) 2010 Google Inc. All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: | |
| # | |
| # * Redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer. | |
| # * Redistributions in binary form must reproduce the above | |
| # copyright notice, this list of conditions and the following disclaimer | |
| # in the documentation and/or other materials provided with the | |
| # distribution. | |
| # * Neither the name of Google Inc. nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| import logging | |
| import optparse | |
| import sys | |
| import urllib | |
| from webkitpy.common.prettypatch import PrettyPatch | |
| from webkitpy.common.system.executive import ScriptError | |
| from webkitpy.tool.commands.command import Command | |
| _log = logging.getLogger(__name__) | |
| class PrettyDiff(Command): | |
| name = 'pretty-diff' | |
| help_text = 'Shows the pretty diff in the default browser' | |
| show_in_main_help = True | |
| def __init__(self): | |
| options = [ | |
| optparse.make_option('-g', '--git-commit', action='store', dest='git_commit', | |
| help=('Operate on a local commit. If a range, the commits are squashed into one. <ref>.... ' | |
| 'includes the working copy changes. UPSTREAM can be used for the upstream/tracking branch.')) | |
| ] | |
| super(PrettyDiff, self).__init__(options) | |
| self._tool = None | |
| def execute(self, options, args, tool): | |
| self._tool = tool | |
| pretty_diff_file = self._show_pretty_diff(options) | |
| if pretty_diff_file: | |
| diff_correct = tool.user.confirm('Was that diff correct?') | |
| pretty_diff_file.close() | |
| if not diff_correct: | |
| sys.exit(1) | |
| def _show_pretty_diff(self, options): | |
| if not self._tool.user.can_open_url(): | |
| return None | |
| try: | |
| pretty_patch = PrettyPatch(self._tool.executive) | |
| patch = self._diff(options) | |
| pretty_diff_file = pretty_patch.pretty_diff_file(patch) | |
| self._open_pretty_diff(pretty_diff_file.name) | |
| # We return the pretty_diff_file here because we need to keep the | |
| # file alive until the user has had a chance to confirm the diff. | |
| return pretty_diff_file | |
| except ScriptError as error: | |
| _log.warning('PrettyPatch failed. :(') | |
| _log.error(error.message_with_output()) | |
| self._exit(error.exit_code or 2) | |
| except OSError: | |
| _log.warning('PrettyPatch unavailable.') | |
| def _diff(self, options): | |
| changed_files = self._tool.git().changed_files(options.git_commit) | |
| return self._tool.git().create_patch(options.git_commit, | |
| changed_files=changed_files) | |
| def _open_pretty_diff(self, file_path): | |
| if self._tool.platform.is_cygwin(): | |
| assert file_path.endswith('.html') | |
| self._tool.executive.run_command(['cygstart', file_path]) | |
| return | |
| url = 'file://%s' % urllib.quote(file_path) | |
| self._tool.user.open_url(url) |