Source

thg / tortoisehg / hgtk / backout.py

# backout.py - TortoiseHg's dialog for backing out changeset
#
# Copyright 2008 TK Soh <teekaysoh@gmail.com>
# Copyright 2008 Steve Borho <steve@borho.org>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.

import gtk
import pango

from tortoisehg.util.i18n import _
from tortoisehg.util import hglib, i18n

from tortoisehg.hgtk import csinfo, gdialog, textview, gtklib

keep = i18n.keepgettext()

class BackoutDialog(gdialog.GDialog):
    """ Backout effect of a changeset """
    def __init__(self, rev=None):
        gdialog.GDialog.__init__(self, resizable=True)
        self.rev = rev

    ### Start of Overriding Section ###

    def get_title(self, reponame):
        return _('Backout changeset - %s') % self.rev

    def get_icon(self):
        return 'menurevert.ico'

    def get_defsize(self):
        return (600, 400)

    def get_setting_name(self):
        return 'backout'

    def get_body(self, vbox):
        # message
        self.msgset = keep._('Backed out changeset: ')
        self.msgset['id'] += self.rev
        self.msgset['str'] += self.rev

        # changeset info
        style = csinfo.panelstyle(label=_('Changeset Description'),
                                  margin=4, padding=2)
        self.csetframe = csinfo.create(self.repo, self.rev, style, withupdate=True)
        vbox.pack_start(self.csetframe, False, False, 2)

        # backout commit message
        frame = gtk.Frame(_('Backout commit message'))
        frame.set_border_width(4)
        msgvbox = gtk.VBox()
        msgvbox.set_border_width(4)
        frame.add(msgvbox)
        vbox.pack_start(frame, True, True, 2)
        self.cmsgframe = frame

        ## message text area
        accelgroup = gtk.AccelGroup()
        self.add_accel_group(accelgroup)
        self.logview = textview.UndoableTextView(accelgroup=accelgroup)
        fontcomment = hglib.getfontconfig()['fontcomment']
        self.logview.modify_font(pango.FontDescription(fontcomment))
        self.buf = self.logview.get_buffer()
        self.buf.set_text(self.msgset['str'])
        scrolledwindow = gtk.ScrolledWindow()
        scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrolledwindow.add(self.logview)
        msgvbox.pack_start(scrolledwindow)
        self.logview.set_editable(False)

        ## tooltips
        self.tips = gtklib.Tooltips()
        self.tips.set_tip(frame,
                _('Commit message text for new changeset that reverses the '
                  'effect of the change being backed out.'))

        ## use English backout message option
        self.eng_msg = gtk.CheckButton(_('Use English backout message'))
        self.eng_msg.connect('toggled', self.eng_msg_toggled)
        engmsg = self.repo.ui.configbool('tortoisehg', 'engmsg', False)
        self.eng_msg.set_active(engmsg)
        msgvbox.pack_start(self.eng_msg, False, False)

        ## merge after backout
        self.merge_button = gtk.CheckButton(
                _('Commit backout before merging with current working parent'))
        self.merge_button.connect('toggled', self.merge_toggeled)
        msgvbox.pack_start(self.merge_button, False, False, 4)

    def get_buttons(self):
        return [('backout', _('Backout'), gtk.RESPONSE_OK),
                ('close', gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)]

    def get_default_button(self):
        return 'backout'

    def get_action_map(self):
        return {gtk.RESPONSE_OK: self.backout}

    def switch_to(self, normal, *args):
        self.csetframe.set_sensitive(normal)
        self.cmsgframe.set_sensitive(normal)
        self.buttons['backout'].set_property('visible', normal)
        self.buttons['close'].set_property('visible', normal)
        if normal:
            self.buttons['close'].grab_focus()

    def command_done(self, returncode, useraborted, *args):
        if returncode == 0:
            self.cmd.set_result(_('Backed out successfully, you must now '
                                  'commit the results'), style='ok')
            self.buttons['backout'].set_property('visible', False)
        elif useraborted:
            self.cmd.set_result(_('Canceled backout'), style='error')
        else:
            self.cmd.set_result(_('Failed to backout'), style='error')

    def load_settings(self):
        checked = self.settings.get_value('merge', True, True)
        self.merge_button.set_active(checked)

    def store_settings(self):
        checked = self.merge_button.get_active()
        self.settings.set_value('merge', checked)
        self.settings.write()

    ### End of Overriding Section ###

    def eng_msg_toggled(self, checkbutton):
        start, end = self.buf.get_bounds()
        msg = self.buf.get_text(start, end)
        state = checkbutton.get_active()
        origmsg = (state and self.msgset['str'] or self.msgset['id'])
        if msg != origmsg:
            res = gdialog.Confirm(_('Confirm Discard Message'),
                    [], self, _('Discard current backout message?')).run()
            if res != gtk.RESPONSE_YES:
                checkbutton.handler_block_by_func(self.eng_msg_toggled)
                checkbutton.set_active(not state)
                checkbutton.handler_unblock_by_func(self.eng_msg_toggled)
                return
        newmsg = (state and self.msgset['id'] or self.msgset['str'])
        self.buf.set_text(newmsg)

    def merge_toggeled(self, checkbutton):
        self.logview.set_editable(checkbutton.get_active())

    def backout(self):
        # do not auto-close when finished
        self.set_after_done(False)

        # prepare command line
        cmdline = ['hg', 'backout', '--rev', self.rev]
        if self.merge_button.get_active():
            start, end = self.buf.get_bounds()
            msg = self.buf.get_text(start, end)
            cmdline += ['--merge']
            cmdline += ['--message', hglib.fromutf(msg)]

        # start backing out
        self.execute_command(cmdline)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.