PageRenderTime 34ms CodeModel.GetById 12ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/tortoisehg/hgtk/thgshelve.py

https://bitbucket.org/tortoisehg/hgtk/
Python | 276 lines | 254 code | 8 blank | 14 comment | 2 complexity | 4938db695fa1ac4c5031c9b653486c3a MD5 | raw file
  1# thgshelve.py - commit dialog for TortoiseHg
  2#
  3# Copyright 2007 Brad Schick, brad at gmail . com
  4# Copyright 2007 TK Soh <teekaysoh@gmail.com>
  5# Copyright 2007 Steve Borho <steve@borho.org>
  6#
  7# This software may be used and distributed according to the terms of the
  8# GNU General Public License version 2, incorporated herein by reference.
  9
 10import os
 11import gtk
 12
 13from mercurial import util, patch, ui
 14
 15from tortoisehg.util.i18n import _
 16from tortoisehg.util import hglib, hgshelve
 17
 18from tortoisehg.hgtk.status import GStatus, FM_STATUS, FM_CHECKED, FM_PATH
 19from tortoisehg.hgtk import gdialog, gtklib
 20
 21class GShelve(GStatus):
 22    """GTK+ based dialog for displaying repository status and shelving changes.
 23
 24    Also provides related operations like add, delete, remove, revert, refresh,
 25    ignore, diff, and edit.
 26    """
 27
 28    ### Overrides of base class methods ###
 29
 30    def init(self):
 31        GStatus.init(self)
 32        self.mode = 'shelve'
 33        self.ui = ErrBufUI(self.ui)
 34
 35    def parse_opts(self):
 36        GStatus.parse_opts(self)
 37        if not self.test_opt('rev'):
 38            self.opts['rev'] = ''
 39
 40    def get_title(self):
 41        return self.get_reponame() + ' - shelve'
 42
 43    def get_icon(self):
 44        return 'shelve.ico'
 45
 46    def auto_check(self):
 47        if not self.test_opt('check'):
 48            return
 49        for row in self.filemodel:
 50            if row[FM_STATUS] in 'MAR' and row[FM_PATH] not in self.excludes:
 51                row[FM_CHECKED] = True
 52        self.update_check_count()
 53        self.opts['check'] = False
 54
 55    def save_settings(self):
 56        settings = GStatus.save_settings(self)
 57        #settings['gshelve'] = self.vpaned.get_position()
 58        return settings
 59
 60
 61    def load_settings(self, settings):
 62        GStatus.load_settings(self, settings)
 63        #if settings:
 64        #    self._setting_vpos = settings['gshelve']
 65        #else:
 66        #    self._setting_vpos = -1
 67
 68
 69    def get_tbbuttons(self):
 70        tbbuttons = GStatus.get_tbbuttons(self)
 71        tbbuttons.insert(0, gtk.SeparatorToolItem())
 72        self.shelve_btn = self.make_toolbutton(gtk.STOCK_FILE, _('Shelve'),
 73                self.shelve_clicked, tip=_('set aside selected changes'))
 74        self.unshelve_btn = self.make_toolbutton(gtk.STOCK_EDIT, _('Unshelve'),
 75                self.unshelve_clicked, tip=_('restore shelved changes'))
 76        self.abandon_btn = self.make_toolbutton(gtk.STOCK_CANCEL, _('Abandon'),
 77                self.abandon_clicked, tip=_('abandon shelved changes'))
 78        tbbuttons.insert(0, self.abandon_btn)
 79        tbbuttons.insert(0, self.unshelve_btn)
 80        tbbuttons.insert(0, self.shelve_btn)
 81        return tbbuttons
 82
 83    def get_body(self):
 84        status_body = GStatus.get_body(self)
 85        #vbox = gtk.VBox()  # For named shelf collection
 86        #self.vpaned = gtk.VPaned()
 87        #self.vpaned.add1(vbox)
 88        #self.vpaned.add2(status_body)
 89        #self.vpaned.set_position(self._setting_vpos)
 90        self.activate_shelve_buttons(True)
 91
 92        self.patch_text = gtk.TextView()
 93        self.patch_text.set_wrap_mode(gtk.WRAP_NONE)
 94        self.patch_text.set_editable(False)
 95        self.patch_text.modify_font(self.difffont)
 96        scroller = gtk.ScrolledWindow()
 97        scroller.set_policy(gtk.POLICY_AUTOMATIC,
 98                            gtk.POLICY_AUTOMATIC)
 99        scroller.add(self.patch_text)
100        self.diff_notebook.append_page(scroller, gtk.Label(_('Shelf Contents')))
101        self.diff_notebook.show_all()
102        return status_body
103
104    def get_custom_menus(self):
105        def shelve(menuitem, files):
106            self.shelve_selected(files)
107            self.activate_shelve_buttons(True)
108        if self.is_merge():
109            return ()
110        else:
111            return ((_('_Shelve'), shelve, 'MAR', 'shelve.ico'),)
112
113
114    def should_live(self, widget=None, event=None):
115        return False
116
117
118    def refresh_complete(self):
119        self.activate_shelve_buttons(True)
120        if self.has_shelve_file():
121            fp = open(self.repo.join('shelve'))
122            buf = self.diff_highlight_buffer(fp.readlines())
123            self.patch_text.set_buffer(buf)
124        else:
125            self.patch_text.set_buffer(gtk.TextBuffer())
126
127
128    ### End of overridable methods ###
129
130    def has_shelve_file(self):
131        return os.path.exists(self.repo.join('shelve'))
132
133    def activate_shelve_buttons(self, status):
134        if status:
135            self.shelve_btn.set_sensitive(len(self.filemodel) > 0)
136            self.unshelve_btn.set_sensitive(self.has_shelve_file())
137            self.abandon_btn.set_sensitive(self.has_shelve_file())
138        else:
139            self.shelve_btn.set_sensitive(False)
140            self.unshelve_btn.set_sensitive(False)
141            self.abandon_btn.set_sensitive(False)
142
143    def shelve_selected(self, files=[]):
144        if len(self.filemodel) < 1:
145            gdialog.Prompt(_('Shelve'),
146                    _('No changes to shelve'), self).run()
147            return
148
149        wfiles = files or self.relevant_checked_files('MAR')
150        if not wfiles:
151            gdialog.Prompt(_('Shelve'),
152                    _('Please select diff chunks to shelve'), self).run()
153            return
154
155        doforce = False
156        doappend = False
157        if self.has_shelve_file():
158            dialog = gtklib.MessageDialog(flags=gtk.DIALOG_MODAL)
159            dialog.set_title(_('Shelve'))
160            dialog.set_markup(_('<b>Shelve file exists!</b>'))
161            dialog.add_buttons(_('Overwrite'), 1,
162                               _('Append'), 2,
163                               _('Cancel'), -1)
164            dialog.set_transient_for(self)
165            rval = dialog.run()
166            dialog.destroy()
167            if rval == 1:
168                doforce = True
169            elif rval == 2:
170                doappend = True
171            else:
172                return
173
174        def filter_patch(ui, chunks):
175            accepted = []
176            for chunk in chunks:
177                file = util.localpath(chunk.filename())
178                if file not in wfiles:
179                    # file was not selected for inclusion
180                    continue
181                if file not in self.chunks:
182                    # file was never filtered, accept all chunks
183                    accepted.append(chunk)
184                    continue
185                schunks = self.chunks[file]
186                for i, c in enumerate(schunks):
187                    if chunk != c:
188                        continue
189                    if i == 0 or c.active:
190                        # take header and active chunks
191                        accepted.append(chunk)
192                    break
193            return accepted
194
195        # hgshelve only works 'interactively'
196        self.ui.setconfig('ui', 'interactive', 'on')
197        opts = {'addremove': None, 'include': [], 'force': doforce,
198                'append': doappend, 'exclude': []}
199        hgshelve.filterpatch = filter_patch
200        # shelve them!
201        hgshelve.shelve(self.ui, self.repo, **opts)
202        self.ui.setconfig('ui', 'interactive', 'off')
203        self.chunks.clear_filechunks() # do not keep chunks
204        self.reload_status()
205
206    def unshelve(self):
207        opts = {'addremove': None, 'include': [], 'force': None,
208                'append': None, 'exclude': [], 'inspect': None}
209        try:
210            self.ui.errorq = []
211            self.ui.quiet = True
212            hgshelve.unshelve(self.ui, self.repo, **opts)
213            self.ui.quiet = False
214            self.reload_status()
215        except (util.Abort, IOError, patch.PatchError), e:
216            gdialog.Prompt(_('Unshelve Abort'),
217                           ''.join(self.ui.errorq), self).run()
218        except Exception, e:
219            gdialog.Prompt(_('Unshelve Error'),
220                           _('Error: %s') % e, self).run()
221
222    def abandon(self):
223        try:
224            response = gdialog.Confirm(_('Confirm Delete'), [], self,
225                                       _('Delete the shelf contents?')).run()
226            if response == gtk.RESPONSE_YES:
227                self.ui.quiet = True
228                hgshelve.abandon(self.ui, self.repo)
229                self.ui.quiet = False
230            self.reload_status()
231        except Exception, e:
232            gdialog.Prompt(_('Abandon Error'),
233                    _('Error: %s') % e, self).run()
234
235    def shelve_clicked(self, toolbutton, data=None):
236        if not self.isuptodate():
237            return
238        self.shelve_selected()
239        self.activate_shelve_buttons(True)
240
241    def unshelve_clicked(self, toolbutton, data=None):
242        if not self.isuptodate():
243            return
244        self.unshelve()
245        self.activate_shelve_buttons(True)
246
247    def abandon_clicked(self, toolbutton, data=None):
248        if not self.isuptodate():
249            return
250        self.abandon()
251        self.activate_shelve_buttons(True)
252
253class ErrBufUI(ui.ui):
254    """ui subclass to save hg and thg errors"""
255
256    def __init__(self, src=None, errorq=[]):
257        ui.ui.__init__(self, src)
258        if src and hasattr(src, 'errorq'):
259            self.errorq = src.errorq
260        else:
261            self.errorq = errorq
262
263    def warn(self, *msg, **opts):
264        self.errorq.extend(msg)
265        ui.ui.warn(self, *msg, **opts)
266
267
268def run(_ui, *pats, **opts):
269    cmdoptions = {
270        'user':opts.get('user', ''), 'date':opts.get('date', ''),
271        'modified':True, 'added':True, 'removed':True, 'deleted':True,
272        'unknown':True, 'ignored':False,
273        'exclude':[], 'include':[],
274        'check': True, 'git':False, 'addremove':False,
275    }
276    return GShelve(_ui, None, None, pats, cmdoptions)