[packages/mercurial] - up to 4.7

arekm arekm at pld-linux.org
Sun Aug 26 11:42:54 CEST 2018


commit c748309cdc47d6b31e08b4b65986ec7c0155184c
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Sun Aug 26 11:42:44 2018 +0200

    - up to 4.7

 gtools.py           | 1900 ---------------------------------------------------
 mercurial-doc.patch |   12 -
 mercurial.spec      |   42 +-
 3 files changed, 25 insertions(+), 1929 deletions(-)
---
diff --git a/mercurial.spec b/mercurial.spec
index 3b0023c..dd99f5e 100644
--- a/mercurial.spec
+++ b/mercurial.spec
@@ -14,16 +14,16 @@
 Summary:	Mercurial Distributed SCM
 Summary(pl.UTF-8):	Mercurial - rozproszony system kontroli wersji
 Name:		mercurial
-Version:	3.7.3
-Release:	2
+Version:	4.7
+Release:	1
 License:	GPL v2+
 Group:		Development/Version Control
 Source0:	https://www.mercurial-scm.org/release/%{name}-%{version}.tar.gz
-# Source0-md5:	f47c9c76b7bf429dafecb71fa81c01b4
-Source1:	gtools.py
+# Source0-md5:	a7ba37fb38308218fdb1f7ad37caa305
+
 Source2:	%{name}-%{webapp}.config
 Source3:	%{name}-%{webapp}-httpd.config
-Patch0:		%{name}-doc.patch
+
 Patch1:		%{name}-clean-environment.patch
 URL:		https://www.mercurial-scm.org/
 BuildRequires:	gettext-tools
@@ -121,22 +121,14 @@ hgk=
 
 %prep
 %setup -q
-%patch0 -p1
-%patch1 -p0
-cp -p %{SOURCE1} hgext/gtools.py
 
-# remove flaky tests failing due to glib deprecation warnings
-%{__rm} tests/{test-help.t,test-extension.t,test-alias.t,test-status-color.t,test-i18n.t,test-qrecord.t,test-strict.t,test-duplicateoptions.py}
+%patch1 -p0
 
 # fails on builders due to lack of networking
 %{__rm} tests/test-clonebundles.t
 
 # flaky tests
-%{__rm} tests/{test-template-engine.t,test-convert-cvs-synthetic.t,test-parse-date.t}
-
-%ifarch x32
-%{__rm} tests/test-context.py
-%endif
+%{__rm} tests/{test-convert-cvs-synthetic.t,test-convert-cvs,test-convert-cvs-detectmerge.t,test-convert-cvsnt-mergepoints.t,test-convert-cvs-branch.t,test-parse-date.t,test-gpg.t}
 
 %build
 %py_build
@@ -186,23 +178,39 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(644,root,root,755)
-%doc CONTRIBUTORS README
+%doc CONTRIBUTORS README.rst
 %attr(755,root,root) %{_bindir}/hg
 %{_mandir}/man1/*.1*
 %{_mandir}/man5/*.5*
 
 %files -n python-%{name}
 %defattr(644,root,root,755)
+%{py_sitedir}/hgdemandimport
 %{py_sitedir}/hgext
+%{py_sitedir}/hgext3rd
 %dir %{py_sitedir}/%{name}
 %attr(755,root,root) %{py_sitedir}/%{name}/*.so
 %{py_sitedir}/%{name}/*.py[co]
+%dir %{py_sitedir}/%{name}/cext
+%{py_sitedir}/%{name}/cext/*.py[co]
+%attr(755,root,root) %{py_sitedir}/%{name}/cext/*.so
+%{py_sitedir}/%{name}/cffi
 %{py_sitedir}/%{name}/default.d
 %{py_sitedir}/%{name}/help
 %{py_sitedir}/%{name}/hgweb
-%{py_sitedir}/%{name}/httpclient
 %{py_sitedir}/%{name}/pure
 %{py_sitedir}/%{name}/templates
+%dir %{py_sitedir}/%{name}/thirdparty
+%{py_sitedir}/%{name}/thirdparty/*.py[co]
+%{py_sitedir}/%{name}/thirdparty/attr
+%{py_sitedir}/%{name}/thirdparty/cbor
+%{py_sitedir}/%{name}/thirdparty/concurrent
+%dir %{py_sitedir}/%{name}/thirdparty/zope
+%{py_sitedir}/%{name}/thirdparty/zope/*.py[co]
+%dir %{py_sitedir}/%{name}/thirdparty/zope/interface
+%{py_sitedir}/%{name}/thirdparty/zope/interface/*.py[co]
+%attr(755,root,root) %{py_sitedir}/%{name}/thirdparty/zope/interface/*.so
+%{py_sitedir}/%{name}/utils
 %dir %{py_sitedir}/%{name}/locale
 %lang(da) %{py_sitedir}/%{name}/locale/da
 %lang(de) %{py_sitedir}/%{name}/locale/de
diff --git a/gtools.py b/gtools.py
deleted file mode 100644
index b9a45eb..0000000
--- a/gtools.py
+++ /dev/null
@@ -1,1900 +0,0 @@
-# gtools.py - Graphical diff and status extension for Mercurial
-#
-# Copyright 2007 Brad Schick, brad at gmail . com
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
-# 
-"""gtools extension provides graphical status and commit dialogs
-
-The gtools extension provides gtk+ based graphical status, log,
-and commit dialogs. Each dialogs provides a convenient way to see what 
-has changed in a repository. Data is displayed in a list that can be
-sorted, selected, and double-clicked to launch diff and editor tools.
-Right-click context menus and toolbars provide operations like commit, 
-add, view, delete, ignore, remove, revert, and refresh.
-
-Files are diff'ed and edited in place whenever possible, so you can
-make changes within external tools and save them directly back to the
-working copy. To enable gtools:
-
-   [extensions]
-   hgext.gtools =
-
-   [gtools]
-   # external diff tool and options
-   diffcmd = gdiff
-   diffopts = -Nprc5
- 
-   # editor, if not specified [ui] editor is used
-   editor = scite
- 
-   # set the fonts for the comments, diffs, and lists
-   fontcomment = courier 10
-   fontdiff = courier 10
-   fontlist = courier 9
-
-   # make the integrated diff window appear at the bottom or side
-   diffbottom = False
- 
-The external diff tool is run as shown below. Unless specified otherwise,
-file_rev1 and file_rev2 are the parent revision and the working copy 
-respectively:
-
-diffcmd diffopts file_rev1 file_rev2
-"""
-
-import mercurial.demandimport; mercurial.demandimport.enable()
-
-import os
-import threading
-import StringIO
-import sys
-import shutil
-import tempfile
-import datetime
-import cPickle
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
-import pango
-
-from mercurial.i18n import _
-from mercurial.node import *
-from mercurial import cmdutil, util, ui, hg, commands, patch
-from hgext import extdiff
-
-gtk.gdk.threads_init()
-
-def gcommit(ui, repo, *pats, **opts):
-    """graphical display for committing outstanding changes
-
-    Displays a list of either all or specified files that can be committed
-    and provides a entry field for the commit message. If a list of 
-    files is omitted, all changes reported by "hg status" will be 
-    committed.
-
-    Each file in the list can be double-clicked to launch a diff or editor
-    tool. Right-click context menus allow for single file operations.
-    """
-    dialog = GCommit(ui, repo, pats, opts, True)
-    run(dialog)
-
-def gstatus(ui, repo, *pats, **opts):
-    """graphical display of changed files in the working directory
-
-    Displays the status of files in the repository. If names are given, 
-    only files that match are shown. Clean and ignored files are not 
-    shown by default, but the can be added from within the dialog or the
-    command-line (with -c, -i or -A)
-
-    NOTE: status may appear to disagree with diff if permissions have
-    changed or a merge has occurred. The standard diff format does not
-    report permission changes and diff only reports changes relative
-    to one merge parent.
-
-    If one revision is given, it is used as the base revision.
-    If two revisions are given, the difference between them is shown.
-
-    The codes used to show the status of files are:
-    M = modified
-    A = added
-    R = removed
-    C = clean
-    ! = deleted, but still tracked
-    ? = not tracked
-    I = ignored
-
-    Each file in the list can be double-clicked to launch a diff or editor
-    tool. Right-click context menus allow for single file operations.
-    """
-    dialog = GStatus(ui, repo, pats, opts, True)
-    run(dialog)
-
-
-def glog(ui, repo, *pats, **opts):
-    """display revision history of entire repository or files
-
-    Displays the revision history of the specified files or the entire
-    project.
-
-    File history is shown without following rename or copy history of
-    files.  Use -f/--follow with a file name to follow history across
-    renames and copies. --follow without a file name will only show
-    ancestors or descendants of the starting revision. --follow-first
-    only follows the first parent of merge revisions.
-
-    If no revision range is specified, the default is tip:0 unless
-    --follow is set, in which case the working directory parent is
-    used as the starting revision.
-
-    Each log entry in the list can be double-clicked to launch a status
-    view of that revision. Diff options like --git are passed to the 
-    status view when a log entry is activated.
-    """
-    dialog = GLog(ui, repo, pats, opts, True)
-    run(dialog)
-
-
-def run(dialog):
-    gtk.gdk.threads_enter()
-    dialog.display()
-    gtk.main()
-    gtk.gdk.threads_leave()
-
-
-cmdtable = {
-'gcommit|gci':
-(gcommit,
- [('A', 'addremove', None, _('skip prompt for marking new/missing files as added/removed')),
-  ('d', 'date', '', _('record datecode as commit date')),
-  ('u', 'user', '', _('record user as commiter')),
-  ('m', 'message', '', _('use <text> as commit message')),
-  ('l', 'logfile', '', _('read commit message from <file>')),
-  ('g', 'git', None, _('use git extended diff format')),
-  ('c', 'check', False, _('automatically check commitable files'))] + commands.walkopts,
- _('hg gcommit [OPTION]... [FILE]...')),
-'gstatus|gst':
-(gstatus,
- [('A', 'all', None, _('show status of all files')),
-  ('m', 'modified', None, _('show only modified files')),
-  ('a', 'added', None, _('show only added files')),
-  ('r', 'removed', None, _('show only removed files')),
-  ('d', 'deleted', None, _('show only deleted (but tracked) files')),
-  ('c', 'clean', None, _('show only files without changes')),
-  ('u', 'unknown', None, _('show only unknown (not tracked) files')),
-  ('i', 'ignored', None, _('show only ignored files')),
-  ('',  'rev', [], _('show difference from revision')),
-  ('g', 'git', None, _('use git extended diff format')),
-  ('c', 'check', False, _('automatically check displayed files'))] + commands.walkopts,
- _('hg gstat [OPTION]... [FILE]...')),
-'glog|ghistory':
-(glog,
- [('f', 'follow', None,
-   _('follow changeset history, or file history across copies and renames')),
-  ('', 'follow-first', None,
-   _('only follow the first parent of merge changesets')),
-  ('d', 'date', '', _('show revs matching date spec')),
-  ('C', 'copies', None, _('show copied files')),
-  ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
-  ('l', 'limit', '', _('limit number of changes displayed')),
-  ('r', 'rev', [], _('show the specified revision or range')),
-  ('', 'removed', None, _('include revs where files were removed')),
-  ('M', 'no-merges', None, _('do not show merges')),
-  ('m', 'only-merges', None, _('show only merges')),
-  ('P', 'prune', [], _('do not display revision or any of its ancestors')),
-  ('g', 'git', None, _('use git extended diff format'))] + commands.walkopts,
-_('hg glog [OPTION]... [FILE]')),
-}
-
-
-class SimpleMessage(gtk.MessageDialog):
-    def run(self):
-        response = gtk.MessageDialog.run(self)
-        self.destroy()
-        return response
-
-
-class Prompt(SimpleMessage):
-    def __init__(self, title, message, parent):
-        gtk.MessageDialog.__init__(self, parent, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
-                                    gtk.BUTTONS_CLOSE)
-        self.set_title(title)
-        self.set_markup('<b>' + message + '</b>')
-
-
-class Confirm(SimpleMessage):
-    """Dialog returns gtk.RESPONSE_YES or gtk.RESPONSE_NO 
-    """
-    def __init__(self, title, files, parent, primary=None):
-        gtk.MessageDialog.__init__(self, parent, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION,
-                                    gtk.BUTTONS_YES_NO)
-        self.set_title('Confirm ' + title)
-        if primary is None:
-            primary = title + ' file' + ((len(files) > 1 and 's') or '') + '?'
-        primary = '<b>' + primary + '</b>'
-        self.set_markup(primary)
-        message = ''
-        for i, file in enumerate(files):
-            message += '   ' + file + '\n'
-            if i == 9: 
-                message += '   ...\n'
-                break
-        self.format_secondary_text(message)
-
-
-class GDialog(gtk.Window):
-    """GTK+ based dialog for displaying mercurial information
-
-    The following methods are meant to be overridden by subclasses. At this
-    point GCommit is really the only intended subclass.
-
-        parse_opts(self)
-        get_title(self)
-        get_minsize(self)
-        get_defsize(self)
-        get_tbbuttons(self)
-        get_body(self)
-        get_extras(self)
-        prepare_display(self)
-        should_live(self, widget, event)
-        save_settings(self)
-        load_settings(self, settings)
-    """
-
-    # "Constants"
-    settings_version = 1
-
-    def __init__(self, ui, repo, pats, opts, main):
-        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
-        self._cwd = repo.root
-        self.ui = ui
-        self.ui.interactive=False
-        self.repo = repo
-        self.pats = pats
-        self.opts = opts
-        self.main = main
-
-    ### Following methods are meant to be overridden by subclasses ###
-
-    def parse_opts(self):
-        pass
-
-
-    def get_title(self):
-        return ''
-
-
-    def get_minsize(self):
-        return (395, 200)
-
-
-    def get_defsize(self):
-        return self._setting_defsize 
-
-
-    def get_tbbuttons(self):
-        return []
-
-
-    def get_body(self):
-        return None
-
-
-    def get_extras(self):
-        return None
-
-
-    def prepare_display(self):
-        pass
-
-
-    def should_live(self, widget=None, event=None):
-        return False
-
-
-    def save_settings(self):
-        rect = self.get_allocation()
-        return {'gdialog': (rect.width, rect.height)}
-
-
-    def load_settings(self, settings):
-        if settings:
-            self._setting_defsize = settings['gdialog']
-        else:
-            self._setting_defsize = (678, 585)
-
-    ### End of overridable methods ###
-
-    def display(self):
-        self._parse_config()
-        self._load_settings()
-        self._setup_gtk()
-        self._parse_opts()
-        self.prepare_display()
-        self.show_all()
-
-
-    def test_opt(self, opt):
-        return opt in self.opts and self.opts[opt]
-
-
-    def _parse_config(self):
-        # defaults    
-        self.fontcomment = 'courier 10'
-        self.fontdiff = 'courier 10'
-        self.fontlist = 'courier 9'
-        self.diffopts = ''
-        self.diffcmd = ''
-        self.diffbottom = ''
-
-        for attr, setting in self.ui.configitems('gtools'):
-            if setting : setattr(self, attr, setting)
-
-        if not self.diffcmd :
-            if not self.diffopts : self.diffopts = '-Npru'
-            self.diffcmd = 'diff'
-
-        if not self.diffbottom or self.diffbottom.lower() == 'false' or self.diffbottom == '0':
-            self.diffbottom = False
-        else:
-            self.diffbottom = True
-
-
-    def _parse_opts(self):
-        # Remove dry_run since Hg only honors it for certain commands
-        self.opts['dry_run'] = False
-        self.opts['force_editor'] = False
-        self.parse_opts()
-
-
-    def merge_opts(self, defaults, mergelist=()):
-        """Merge default options with the specified local options and globals.
-        Results is defaults + merglist + globals
-        """
-        newopts = {}
-        for hgopt in defaults:
-            newopts[hgopt[1].replace('-', '_')] = hgopt[2]
-        for mergeopt in mergelist:
-            newopts[mergeopt] = self.opts[mergeopt]
-        newopts.update(self.global_opts())
-        return newopts
-
-
-    def global_opts(self):
-        globals = {}
-        hgglobals = [opt[1].replace('-', '_') for opt in commands.globalopts if opt[1] != 'help']
-        for key in self.opts:
-            if key in  hgglobals :
-                globals[key] = self.opts[key]
-        return globals
-
-
-    def count_revs(self):
-        cnt = 0
-        if self.test_opt('rev'):
-            for rev in self.opts['rev']:
-                cnt += len(rev.split(cmdutil.revrangesep, 1))
-        return cnt
-
-
-    def make_toolbutton(self, stock, label, handler, userdata=None):
-        tbutton = gtk.ToolButton(stock)
-        tbutton.set_use_underline(True)
-        tbutton.set_label(label)
-        tbutton.connect('clicked', handler, userdata)
-        return tbutton
-
-
-    def _setup_gtk(self):
-        self.set_title(self.get_title())
-        
-        # Minimum size
-        minx, miny = self.get_minsize()
-        self.set_size_request(minx, miny)
-        # Initial size
-        defx, defy = self.get_defsize()
-        self.set_default_size(defx, defy)
-        
-        vbox = gtk.VBox(False, 0)
-        self.add(vbox)
-        
-        toolbar = gtk.Toolbar()
-        tbuttons =  self.get_tbbuttons()
-        for tbutton in tbuttons:
-            toolbar.insert(tbutton, -1)
-
-        vbox.pack_start(toolbar, False, False, 0)
-
-        # Subclass returns the main body
-        body = self.get_body()
-        vbox.pack_start(body, True, True, 0)
-        
-        hbox = gtk.HBox(False, 0)
-        hbox.set_border_width(6)
-        vbox.pack_end(hbox, False, False, 0)
-        
-        bbox = gtk.HButtonBox()
-        bbox.set_layout(gtk.BUTTONBOX_EDGE)
-        hbox.pack_end(bbox, False, False)
-
-        if self.main:
-            button = gtk.Button(stock=gtk.STOCK_QUIT)
-        else:
-            button = gtk.Button(stock=gtk.STOCK_CLOSE)
-
-        button.connect('clicked', self._quit_clicked)
-        bbox.pack_end(button, False, False)
-        self.connect('destroy', self._destroying)
-        self.connect('delete_event', self.should_live)
-
-        # Subclass provides extra stuff to left of Quit button
-        extras = self.get_extras()
-        if extras:
-            hbox.pack_start(extras, False, False)
-
-
-    def _quit_clicked(self, button):
-        if not self.should_live():
-            self.destroy()
-
-
-    def _destroying(self, gtkobj):
-        try:
-            file = None
-            settings = self.save_settings()
-            versioned = (GDialog.settings_version, settings)
-            dirname = os.path.join(os.path.expanduser('~'), '.hgext/gtools')
-            filename = os.path.join(dirname, self.__class__.__name__)
-            try:
-                if not os.path.exists(dirname):
-                    os.makedirs(dirname)
-                file = open(filename, 'wb')
-                cPickle.dump(versioned, file, cPickle.HIGHEST_PROTOCOL)
-            except (IOError, cPickle.PickleError):
-                pass
-        finally:
-            if file:
-                file.close()
-            if self.main:
-                gtk.main_quit()
-
-
-    def _load_settings(self):
-        try:
-            file = None
-            settings = None
-            dirname = os.path.join(os.path.expanduser('~'), '.hgext/gtools')
-            filename = os.path.join(dirname, self.__class__.__name__)
-            try:
-                file = open(filename, 'rb')
-                versioned = cPickle.load(file)
-                if versioned[0] == GDialog.settings_version:
-                    settings = versioned[1]
-            except (IOError, cPickle.PickleError), inst:
-                pass
-        finally:
-            if file:
-                file.close()
-            self.load_settings(settings)
-
-
-    def restore_cwd(self):
-        # extdiff works on relative directories to avoid showing temp paths. Since another thread
-        # could be running that changed cwd, we always need to set it back. This is a race condition
-        # but not likely to be a problem.
-        os.chdir(self._cwd)
-
-
-    def _hg_call_wrapper(self, title, command, showoutput=True):
-        """Run the specified command and display any resulting aborts, messages, 
-        and errors 
-        """
-        self.restore_cwd()
-        textout = ''
-        saved = sys.stderr
-        errors = StringIO.StringIO()
-        try:
-            sys.stderr = errors
-            self.ui.pushbuffer()
-            try:
-                command()
-            except util.Abort, inst:
-                Prompt(title + ' Aborted', str(inst), self).run()
-                return False, ''
-        finally:
-            sys.stderr = saved
-            textout = self.ui.popbuffer() 
-            prompttext = ''
-            if showoutput:
-                prompttext = textout + '\n'
-            prompttext += errors.getvalue()
-            errors.close()
-            if len(prompttext) > 1:
-                Prompt(title + ' Messages and Errors', prompttext, self).run()
-
-        return True, textout
-
-
-
-class GLog(GDialog):
-    """GTK+ based dialog for displaying repository logs
-    """
-
-    # "Constants"
-    block_count = 150
-
-
-    def get_title(self):
-        return os.path.basename(self.repo.root) + ' log ' + ':'.join(self.opts['rev']) + ' ' + ' '.join(self.pats)
-
-
-    def parse_opts(self):
-        # Disable quiet to get full log info
-        self.ui.quiet = False
-
-
-    def get_tbbuttons(self):
-        return [self.make_toolbutton(gtk.STOCK_REFRESH, 're_fresh', self._refresh_clicked),
-                     gtk.SeparatorToolItem()]
-
-
-    def prepare_display(self):
-        self.refreshing = False
-        self._last_rev = -999
-        # If the log load failed, no reason to continue
-        if not self.reload_log():
-            raise util.Abort('could not load log')
-
-
-    def save_settings(self):
-        settings = GDialog.save_settings(self)
-        settings['glog'] = self._vpaned.get_position()
-        return settings
-
-
-    def load_settings(self, settings):
-        GDialog.load_settings(self, settings)
-        if settings:
-            self._setting_vpos = settings['glog']
-        else:
-            self._setting_vpos = -1
-
-
-    def _hg_log(self, rev, pats, verbose):
-        def dohglog():
-            self.restore_cwd()
-            self.repo.dirstate.invalidate()
-            commands.log(self.ui, self.repo, *pats, **self.opts)
-
-        logtext = ''
-        success = False
-        saved_revs = self.opts['rev']
-        saved_verbose = self.ui.verbose
-        try:
-            self.opts['rev'] = rev
-            self.ui.verbose = verbose
-            success, logtext = self._hg_call_wrapper('Log', dohglog, False)
-        finally:
-            self.opts['rev'] = saved_revs
-            self.ui.verbose = saved_verbose
-        return success, logtext
-
-
-    def reload_log(self):
-        """Clear out the existing ListStore model and reload it from the repository. 
-        """
-        # If the last refresh is still being processed, then do nothing
-        if self.refreshing:
-            return False
-
-        # For long logs this is the slowest part, but given the current
-        # Hg API doesn't allow it to be easily processed in chuncks
-        success, logtext = self._hg_log(self.opts['rev'], self.pats, False)
-        if not success:
-            return False
-
-        if not logtext:
-            return True
-
-        # Currently selected file
-        iter = self.tree.get_selection().get_selected()[1]
-        if iter:
-            reselect = self.model[iter][0]
-        else:
-            reselect = None
-
-        # Load the new data into the tree's model
-        self.tree.hide()
-        self.model.clear()
-
-        # Generator that parses and inserts log entries
-        def inserter(logtext):
-            while logtext:
-                blocks = logtext.strip('\n').split('\n\n', GLog.block_count)
-                if len(blocks) > GLog.block_count:
-                    logtext = blocks[GLog.block_count]
-                    del blocks[GLog.block_count]
-                else:
-                    logtext = None
-    
-                for block in blocks:
-                    # defaults
-                    log = { 'user' : 'missing', 'summary' : '' }
-                    lines = block.split('\n')
-                    parents = []
-                    for line in lines:
-                        line = util.fromlocal(line)
-                        sep = line.index(':')
-                        info = line[0:sep]
-                        value = line[sep+1:].strip()
-    
-                        if info == 'changeset':
-                            log['rev'] = value.split(':')[0]
-                        elif info == 'parent':
-                            parents.append(long(value.split(':')[0]))
-                        else:
-                            log[info] = value
-    
-                    self.model.append((log['rev'], log['user'], log['summary'], log['date'], 
-                                       util.strdate(util.tolocal(log['date']), '%a %b %d %H:%M:%S %Y', {})[0],
-                                       parents))
-                yield logtext is not None
-
-
-        # Insert entries during idle to improve response time, but run
-        # the first batch synchronously to attempt the reselect below
-        gen = inserter(logtext)
-        self.refreshing = gen.next()
-
-        # If insert didn't finish, setup idle processing for the remainder
-        if self.refreshing:
-            def doidle():
-                self.refreshing = gen.next()
-                return self.refreshing
-            gobject.idle_add(doidle)
-
-        selection = self.tree.get_selection()
-        for row in self.model:
-            if row[0] == reselect:
-                selection.select_iter(row.iter)
-                break
-        else:
-            self.tree.scroll_to_cell((0,))
-            selection.select_path((0,))
-
-        self.tree.show()
-        self.tree.grab_focus()
-        return True
-
-
-    def load_details(self, rev, parents):
-        save_removed = self.opts['removed'] 
-        self.opts['removed'] = False
-        success, logtext = self._hg_log(rev, [], True)
-        self.opts['removed'] = save_removed
-
-        if not success:
-            self.details_text.set_buffer(gtk.TextBuffer())
-            return False
-
-        buffer = gtk.TextBuffer()
-        buff_iter = buffer.get_start_iter()
-        buffer.create_tag('changeset', foreground='#000090', paragraph_background='#F0F0F0')
-        buffer.create_tag('date', foreground='#000090', paragraph_background='#F0F0F0')
-        buffer.create_tag('files', foreground='#5C5C5C', paragraph_background='#F0F0F0')
-        if parents == 1:
-            buffer.create_tag('parent', foreground='#900000', paragraph_background='#F0F0F0')
-        elif parents == 2:
-            buffer.create_tag('parent', foreground='#006400', paragraph_background='#F0F0F0')
-
-        lines = logtext.split('\n')
-        lines_iter = iter(lines)
-
-        for line in lines_iter:
-            line = util.fromlocal(line)
-            if line.startswith('changeset:'):
-                buffer.insert_with_tags_by_name(buff_iter, line + '\n', 'changeset')
-            if line.startswith('date:'):
-                buffer.insert_with_tags_by_name(buff_iter, line + '\n', 'date')
-            elif line.startswith('parent:'):
-                buffer.insert_with_tags_by_name(buff_iter, line + '\n', 'parent')
-            elif line.startswith('files:'):
-                buffer.insert_with_tags_by_name(buff_iter, line + '\n', 'files')
-            elif line.startswith('description:'):
-                buffer.insert(buff_iter, '\n')
-                break;
-
-        for line in lines_iter:
-            line = util.fromlocal(line)
-            buffer.insert(buff_iter, line + '\n')
-
-        self.details_text.set_buffer(buffer)
-        return True
-
-
-    def _search_in_tree(self, model, column, key, iter, data):
-        """Searches all fields shown in the tree when the user hits crtr+f,
-        not just the ones that are set via tree.set_search_column.
-        Case insensitive
-        """
-        key = key.lower()
-        searchable = [x.lower() for x in (
-                        model.get_value(iter,0), #rev id (local)
-                        model.get_value(iter,1), #author
-                        model.get_value(iter,2), #summary
-                        )]
-        for field in searchable:
-            if field.find(key) != -1:
-                return False
-        return True
-
-
-    def get_body(self):
-        self._menu = gtk.Menu()
-        self._menu.set_size_request(90, -1)
-        menuitem = gtk.MenuItem('_status', True)
-        menuitem.connect('activate', self._show_status)
-        menuitem.set_border_width(1)
-        self._menu.append(menuitem)
-        menuitem = gtk.MenuItem("_export patch",True)
-        menuitem.connect('activate',self._export_patch)
-        menuitem.set_border_width(1)
-        self._menu.append(menuitem)
-        self._menu.show_all()
-
-        self.model = gtk.ListStore(str, str, str, str, long, object)
-        self.model.set_default_sort_func(self._sort_by_rev)
-
-        self.tree = gtk.TreeView(self.model)
-        self.tree.connect('button-release-event', self._tree_button_release)
-        self.tree.connect('popup-menu', self._tree_popup_menu)
-        self.tree.connect('row-activated', self._tree_row_act)
-        self.tree.set_reorderable(False)
-        self.tree.set_enable_search(True)
-        self.tree.set_search_equal_func(self._search_in_tree,None)
-        self.tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
-        self.tree.get_selection().connect('changed', self._tree_selection_changed)
-        self.tree.set_rubber_banding(False)
-        self.tree.modify_font(pango.FontDescription(self.fontlist))
-        self.tree.set_rules_hint(True) 
-        
-        changeset_cell = gtk.CellRendererText()
-        user_cell = gtk.CellRendererText()
-        summary_cell = gtk.CellRendererText()
-        date_cell = gtk.CellRendererText()
-        
-        col0 = gtk.TreeViewColumn('rev', changeset_cell)
-        col0.add_attribute(changeset_cell, 'text', 0)
-        col0.set_cell_data_func(changeset_cell, self._text_color)
-        col0.set_sort_column_id(0)
-        col0.set_resizable(False)
-        
-        col1 = gtk.TreeViewColumn('user', user_cell)
-        col1.add_attribute(user_cell, 'text', 1)
-        col1.set_cell_data_func(user_cell, self._text_color)
-        col1.set_sort_column_id(1)
-        col1.set_resizable(True)
-        
-        col2 = gtk.TreeViewColumn('summary', summary_cell)
-        col2.add_attribute(summary_cell, 'text', 2)
-        col2.set_cell_data_func(summary_cell, self._text_color)
-        col2.set_sort_column_id(2)
-        col2.set_resizable(True)
-
-        col3 = gtk.TreeViewColumn('date', date_cell)
-        col3.add_attribute(date_cell, 'text', 3)
-        col3.set_cell_data_func(date_cell, self._text_color)
-        col3.set_sort_column_id(4)
-        col3.set_resizable(True)
-
-        self.tree.append_column(col0)
-        self.tree.append_column(col1)
-        self.tree.append_column(col2)
-        self.tree.append_column(col3)
-        self.tree.set_headers_clickable(True)
-        
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-        scroller.add(self.tree)
-        
-        tree_frame = gtk.Frame()
-        tree_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-        tree_frame.add(scroller)
-
-        details_frame = gtk.Frame()
-        details_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-        details_frame.add(scroller)
-        
-        self.details_text = gtk.TextView()
-        self.details_text.set_wrap_mode(gtk.WRAP_WORD)
-        self.details_text.set_editable(False)
-        self.details_text.modify_font(pango.FontDescription(self.fontcomment))
-        scroller.add(self.details_text)
-
-        self._vpaned = gtk.VPaned()
-        self._vpaned.pack1(tree_frame, True, False)
-        self._vpaned.pack2(details_frame, True, True)
-        self._vpaned.set_position(self._setting_vpos)
-        return self._vpaned
-
-
-    def _sort_by_rev(self, model, iter1, iter2):
-        lhs, rhs = (model.get_value(iter1, 0), model.get_value(iter2, 0))
-
-        # GTK+ bug that calls sort before a full row is inserted causing values to be None.
-        if None in (lhs, rhs) :
-            return 0
-
-        result = long(rhs) - long(lhs)
-        return min(max(result, -1), 1)
-
-
-    def _text_color(self, column, text_renderer, list, row_iter):
-        parents = list[row_iter][5]
-        if len(parents) == 2:
-            text_renderer.set_property('foreground', '#006400')
-        elif len(parents) == 1:
-            text_renderer.set_property('foreground', '#900000')
-        else:
-            text_renderer.set_property('foreground', 'black')
-
-
-    def _show_status(self, menuitem):
-        row = self.model[self.tree.get_selection().get_selected()[1]]
-        rev = long(row[0])
-        parents = row[5]
-        if len(parents) == 0:
-            parents = [rev-1]
-
-        for parent in parents:
-            statopts = self.merge_opts(cmdtable['gstatus|gst'][1], ('include', 'exclude', 'git'))
-            statopts['rev'] = ['%u:%u' % (parent, rev)]
-            statopts['modified'] = True
-            statopts['added'] = True
-            statopts['removed'] = True
-            dialog = GStatus(self.ui, self.repo, [], statopts, False)
-            dialog.display()
-        return True
-
-
-    def _export_patch(self, menuitem):
-        row = self.model[self.tree.get_selection().get_selected()[1]]
-        rev = long(row[0])
-        fd = NativeSaveFileDialogWrapper(Title = "Save patch to")
-        result = fd.run()
-
-        if result:
-            # In case new export args are added in the future, merge the hg defaults
-            exportOpts= self.merge_opts(commands.table['^export'][1], ())
-            exportOpts['output'] = result
-            def dohgexport():
-                commands.export(self.ui,self.repo,str(rev),**exportOpts)
-            success, outtext = self._hg_call_wrapper("Export",dohgexport,False)
-
-
-    def _tree_selection_changed(self, selection):
-        ''' Update the details text '''
-        if selection.count_selected_rows() == 0:
-            return False
-        rev = [self.model[selection.get_selected()[1]][0]]
-        if rev != self._last_rev:
-            self._last_rev = rev
-            parents = self.model[selection.get_selected()[1]][5]
-            self.load_details(rev, len(parents))
-
-        return False
-
-
-    def _refresh_clicked(self, toolbutton, data=None):
-        self.reload_log()
-        return True
-
-
-    def _tree_button_release(self, widget, event) :
-        if event.button == 3 and not (event.state & (gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK)):
-            self._tree_popup_menu(widget, event.button, event.time)
-        return False
-
-
-    def _tree_popup_menu(self, widget, button=0, time=0) :
-        self._menu.popup(None, None, None, button, time)
-        return True
-
-
-    def _tree_row_act(self, tree, path, column) :
-        """Default action is the first entry in the context menu
-        """
-        self._menu.get_children()[0].activate()
-        return True
-
-
-
-class GStatus(GDialog):
-    """GTK+ based dialog for displaying repository status
-
-    Also provides related operations like add, delete, remove, revert, refresh,
-    ignore, diff, and edit.
-
-    The following methods are meant to be overridden by subclasses. At this
-    point GCommit is really the only intended subclass.
-
-        auto_check(self)
-        get_menu_info(self)
-    """
-
-    ### Following methods are meant to be overridden by subclasses ###
-
-    def auto_check(self):
-        if self.test_opt('check'):
-            for entry in self.model : entry[0] = True
-
-
-    def get_menu_info(self):
-        """Returns menu info in this order: merge, addrem, unknown, clean, ignored, deleted 
-        """
-        return ((('_difference', self._diff_file), ('_view right', self._view_file), 
-                    ('view _left', self._view_left_file), ('_revert', self._revert_file), ('l_og', self._log_file)),
-                (('_difference', self._diff_file), ('_view', self._view_file), 
-                    ('_revert', self._revert_file), ('l_og', self._log_file)),
-                (('_view', self._view_file), ('_delete', self._delete_file), 
-                    ('_add', self._add_file), ('_ignore', self._ignore_file)),
-                (('_view', self._view_file), ('re_move', self._remove_file), ('l_og', self._log_file)),
-                (('_view', self._view_file), ('_delete', self._delete_file)),
-                (('_view', self._view_file), ('_revert', self._revert_file), 
-                    ('re_move', self._remove_file), ('l_og', self._log_file)))
-
-    ### End of overridable methods ###
-
-
-    ### Overrides of base class methods ###
-
-    def parse_opts(self):
-        self._ready = False
-
-        # Determine which files to display
-        if self.test_opt('all'):
-            for check in self._show_checks.values():
-                check.set_active(True)
-        else:
-            set = False
-            for opt in self.opts :
-                if opt in self._show_checks and self.opts[opt]:
-                    set = True
-                    self._show_checks[opt].set_active(True)
-            if not set:
-                for check in [item[1] for item in self._show_checks.iteritems() 
-                              if item[0] in ('modified', 'added', 'removed', 
-                                             'deleted', 'unknown')]:
-                    check.set_active(True)
-
-
-    def get_title(self):
-        return os.path.basename(self.repo.root) + ' status ' + ':'.join(self.opts['rev'])  + ' ' + ' '.join(self.pats)
-
-
-    def get_defsize(self):
-        return self._setting_defsize
-
-
-    def get_tbbuttons(self):
-        tbuttons = [self.make_toolbutton(gtk.STOCK_REFRESH, 're_fresh', self._refresh_clicked),
-                     gtk.SeparatorToolItem()]
-
-        if self.count_revs() < 2:
-            tbuttons += [self.make_toolbutton(gtk.STOCK_MEDIA_REWIND, 're_vert', self._revert_clicked),
-                         self.make_toolbutton(gtk.STOCK_ADD, '_add', self._add_clicked),
-                         self.make_toolbutton(gtk.STOCK_DELETE, '_delete', self._delete_clicked),
-                         gtk.SeparatorToolItem(),
-                         self.make_toolbutton(gtk.STOCK_YES, '_select', self._sel_desel_clicked, True),
-                         self.make_toolbutton(gtk.STOCK_NO, '_deselect', self._sel_desel_clicked, False),
-                         gtk.SeparatorToolItem()]
-
-        self.showdiff_toggle = gtk.ToggleToolButton(gtk.STOCK_JUSTIFY_FILL)
-        self.showdiff_toggle.set_use_underline(True)
-        self.showdiff_toggle.set_label('_show diff')
-        self.showdiff_toggle.set_active(False)
-        self._showdiff_toggled_id = self.showdiff_toggle.connect('toggled', self._showdiff_toggled )
-        tbuttons.append(self.showdiff_toggle)
-        return tbuttons
-
-
-    def save_settings(self):
-        settings = GDialog.save_settings(self)
-        settings['gstatus'] = (self._diffpane.get_position(), self._setting_lastpos)
-        return settings
-
-
-    def load_settings(self, settings):
-        GDialog.load_settings(self, settings)
-        if settings:
-            mysettings = settings['gstatus']
-            self._setting_pos = mysettings[0]
-            self._setting_lastpos = mysettings[1]
-        else:
-            self._setting_pos = 64000
-            self._setting_lastpos = 270
-
-
-    def get_body(self):
-        self.connect('map-event', self._displayed)
-
-        # TODO: should generate menus dynamically during right-click, currently
-        # there can be entires that are not always supported or relavant.
-        merge, addrem, unknown, clean, ignored, deleted  = self.get_menu_info()
-        merge_menu = self.make_menu(merge)
-        addrem_menu = self.make_menu(addrem)
-        unknown_menu = self.make_menu(unknown)
-        clean_menu = self.make_menu(clean)
-        ignored_menu = self.make_menu(ignored)
-        deleted_menu = self.make_menu(deleted)
-
-        # Dictionary with a key of file-stat and values containing context-menus
-        self._menus = {}
-        self._menus['M'] = merge_menu
-        self._menus['A'] = addrem_menu
-        self._menus['R'] = addrem_menu
-        self._menus['?'] = unknown_menu
-        self._menus['C'] = clean_menu
-        self._menus['I'] = ignored_menu
-        self._menus['!'] = deleted_menu
-
-        self.model = gtk.ListStore(bool, str, str)
-        self.model.set_sort_func(1001, self._sort_by_stat)
-        self.model.set_default_sort_func(self._sort_by_stat)
-
-        self.tree = gtk.TreeView(self.model)
-        self.tree.connect('button-press-event', self._tree_button_press)
-        self.tree.connect('button-release-event', self._tree_button_release)
-        self.tree.connect('popup-menu', self._tree_popup_menu)
-        self.tree.connect('row-activated', self._tree_row_act)
-        self.tree.connect('key-press-event', self._tree_key_press)
-        self.tree.set_reorderable(False)
-        self.tree.set_enable_search(True)
-        self.tree.set_search_column(2)
-        self.tree.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
-        self.tree.get_selection().connect('changed', self._tree_selection_changed, False)
-        self.tree.set_rubber_banding(True)
-        self.tree.modify_font(pango.FontDescription(self.fontlist))
-        self.tree.set_headers_clickable(True)
-        
-        toggle_cell = gtk.CellRendererToggle()
-        toggle_cell.connect('toggled', self._select_toggle)
-        toggle_cell.set_property('activatable', True)
-
-        path_cell = gtk.CellRendererText()
-        stat_cell = gtk.CellRendererText()
-
-        if self.count_revs() < 2:
-            col0 = gtk.TreeViewColumn('select', toggle_cell)
-            col0.add_attribute(toggle_cell, 'active', 0)
-            col0.set_sort_column_id(0)
-            col0.set_resizable(False)
-            self.tree.append_column(col0)
-        
-        col1 = gtk.TreeViewColumn('st', stat_cell)
-        col1.add_attribute(stat_cell, 'text', 1)
-        col1.set_cell_data_func(stat_cell, self._text_color)
-        col1.set_sort_column_id(1001)
-        col1.set_resizable(False)
-        self.tree.append_column(col1)
-        
-        col2 = gtk.TreeViewColumn('path', path_cell)
-        col2.add_attribute(path_cell, 'text', 2)
-        col2.set_cell_data_func(path_cell, self._text_color)
-        col2.set_sort_column_id(2)
-        col2.set_resizable(True)
-        self.tree.append_column(col2)
-       
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-        scroller.add(self.tree)
-        
-        tree_frame = gtk.Frame()
-        tree_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-        tree_frame.add(scroller)
-
-        diff_frame = gtk.Frame()
-        diff_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-        diff_frame.add(scroller)
-        
-        self.diff_text = gtk.TextView()
-        self.diff_text.set_wrap_mode(gtk.WRAP_NONE)
-        self.diff_text.set_editable(False)
-        self.diff_text.modify_font(pango.FontDescription(self.fontdiff))
-        scroller.add(self.diff_text)
-
-        if self.diffbottom:
-            self._diffpane = gtk.VPaned()
-        else:
-            self._diffpane = gtk.HPaned()
-
-        self._diffpane.pack1(tree_frame, True, False)
-        self._diffpane.pack2(diff_frame, True, True)
-        self._diffpane.set_position(self._setting_pos)
-        self._diffpane_moved_id = self._diffpane.connect('notify::position', self._diffpane_moved)
-        return self._diffpane
-
-
-    def get_extras(self):
-        table = gtk.Table(rows=2, columns=3)
-        table.set_col_spacings(8)
-
-        self._show_checks = {}
-        row, col = 0, 0
-        checks = ('modified', 'added', 'removed')
-        if self.count_revs() <= 1:
-            checks += ('deleted', 'unknown', 'clean', 'ignored')
-
-        for type in checks:
-            check = gtk.CheckButton('_' + type)
-            check.connect('toggled', self._show_toggle, type)
-            table.attach(check, col, col+1, row, row+1)
-            self._show_checks[type] = check
-            col += row
-            row = not row
-        return table
-        
-
-    def prepare_display(self):
-        self._ready = True
-        self._last_files = []
-        # If the status load failed, no reason to continue
-        if not self.reload_status():
-            raise util.Abort('could not load status')
-        self.auto_check()
-
-
-    def _displayed(self, widget, event):
-        self._diffpane_moved(self._diffpane)
-        return False
-
-
-    def should_live(self, widget=None, event=None):
-        return False
-
-    ### End of overrides ###
-
-    def _do_reload_status(self):
-        """Clear out the existing ListStore model and reload it from the repository status. 
-        Also recheck and reselect files that remain in the list.
-        """
-        self.restore_cwd()
-        self.repo.dirstate.invalidate()
-
-        # The following code was copied from the status function in mercurial\commands.py
-        # and modified slightly to work here
-        
-        # node2 is None (the working dir) when 0 or 1 rev is specificed
-        self._node1, self._node2 = cmdutil.revpair(self.repo, self.opts.get('rev'))
-    
-        files, matchfn, anypats = cmdutil.matchpats(self.repo, self.pats, self.opts)
-        cwd = (self.pats and self.repo.getcwd()) or ''
-        modified, added, removed, deleted, unknown, ignored, clean = [
-            n for n in self.repo.status(node1=self._node1, node2=self._node2, files=files,
-                                 match=matchfn,
-                                 list_ignored=self.test_opt('ignored'),
-                                 list_clean=self.test_opt('clean'))]
-
-        changetypes = (('modified', 'M', modified),
-                       ('added', 'A', added),
-                       ('removed', 'R', removed),
-                       ('deleted', '!', deleted),
-                       ('unknown', '?', unknown),
-                       ('ignored', 'I', ignored))
-    
-        explicit_changetypes = changetypes + (('clean', 'C', clean),)
-
-        # List of the currently checked and selected files to pass on to the new data
-        recheck = [entry[2] for entry in self.model if entry[0]]
-        reselect = [self.model[iter][2] for iter in self.tree.get_selection().get_selected_rows()[1]]
-
-        # Load the new data into the tree's model
-        self.tree.hide()
-        self.model.clear()
-    
-        for opt, char, changes in ([ct for ct in explicit_changetypes
-                                    if self.test_opt(ct[0])] or changetypes) :
-            for file in changes:
-                file = util.localpath(file)
-                self.model.append([file in recheck, char, file])
-
-        selection = self.tree.get_selection()
-        selected = False
-        for row in self.model:
-            if row[2] in reselect:
-                selection.select_iter(row.iter)
-                selected = True
-
-        if not selected:
-            selection.select_path((0,))
-
-        self.tree.show()
-        self.tree.grab_focus()
-        return True
-
-
-    def reload_status(self):
-        if not self._ready: return False
-        success, outtext = self._hg_call_wrapper('Status', self._do_reload_status)
-        return success
-
-
-    def make_menu(self, entries):
-        menu = gtk.Menu()
-        for entry in entries:
-            menu.append(self._make_menuitem(entry[0], entry[1]))
-        menu.set_size_request(90, -1)
-        menu.show_all()
-        return menu
-
-
-    def _make_menuitem(self, label, handler):
-        menuitem = gtk.MenuItem(label, True)
-        menuitem.connect('activate', self._context_menu_act, handler)
-        menuitem.set_border_width(1)
-        return menuitem
-
-
-    def _select_toggle(self, cellrenderer, path):
-        self.model[path][0] = not self.model[path][0]
-        return True
-
-
-    def _show_toggle(self, check, type):
-        self.opts[type] = check.get_active()
-        self.reload_status()
-        return True
-
-
-    def _sort_by_stat(self, model, iter1, iter2):
-        order = 'MAR!?IC'
-        lhs, rhs = (model.get_value(iter1, 1), model.get_value(iter2, 1))
-
-        # GTK+ bug that calls sort before a full row is inserted causing values to be None.
-        # When this happens, just return any value since the call is irrelevant and will be
-        # followed by another with the correct (non-None) value
-        if None in (lhs, rhs) :
-            return 0
-
-        result = order.find(lhs) - order.find(rhs)
-        return min(max(result, -1), 1)
-        
-
-    def _text_color(self, column, text_renderer, list, row_iter):
-        stat = list[row_iter][1]
-        if stat == 'M':  
-            text_renderer.set_property('foreground', '#000090')
-        elif stat == 'A':
-            text_renderer.set_property('foreground', '#006400')
-        elif stat == 'R':
-            text_renderer.set_property('foreground', '#900000')
-        elif stat == 'C':
-            text_renderer.set_property('foreground', 'black')
-        elif stat == '!':
-            text_renderer.set_property('foreground', 'red')
-        elif stat == '?':
-            text_renderer.set_property('foreground', '#AA5000')
-        elif stat == 'I':
-            text_renderer.set_property('foreground', 'black')
-        else:
-            text_renderer.set_property('foreground', 'black')
-
-
-    def _diff_file(self, stat, file):
-        def dodiff():
-            self.restore_cwd()
-            extdiff.dodiff(self.ui, self.repo, self.diffcmd, [self.diffopts],
-                            [file], self.opts)
-
-        thread = threading.Thread(target=dodiff, name='diff:'+file)
-        thread.setDaemon(True)
-        thread.start()
-
-
-    def _view_file(self, stat, file, force_left=False):
-        def doedit():
-            pathroot = self.repo.root
-            tmproot = None
-            copynode = None
-            try:
-                # if we aren't looking at the wc, copy the node...
-                if stat in 'R!' or force_left:
-                    copynode = self._node1
-                elif self._node2:
-                    copynode = self._node2
-
-                if copynode:
-                    tmproot = tempfile.mkdtemp(prefix='gtools.')
-                    copydir = extdiff.snapshot_node(self.ui, self.repo, [util.pconvert(file)],
-                                                     copynode, tmproot)
-                    pathroot = os.path.join(tmproot, copydir)
-
-                file_path = os.path.join(pathroot, file)
-                editor = (os.environ.get('HGEDITOR') or
-                        self.ui.config('gtools', 'editor') or
-                        self.ui.config('ui', 'editor') or
-                        os.environ.get('EDITOR', 'vi'))
-                util.system("%s \"%s\"" % (editor, file_path),
-                            environ={'HGUSER': self.ui.username()},
-                            onerr=util.Abort, errprefix=_('edit failed'))
-            finally:
-                if tmproot:
-                    shutil.rmtree(tmproot)
-
-        thread = threading.Thread(target=doedit, name='edit:'+file)
-        thread.setDaemon(True)
-        thread.start()
-
-
-    def _view_left_file(self, stat, file):
-        return self._view_file(stat, file, True)
-
-
-    def _remove_file(self, stat, file):
-        self._hg_remove([file])
-        return True
-
-
-    def _hg_remove(self, files):
-        if self.count_revs() > 1:
-            Prompt('Nothing Removed', 'Remove is not enabled when multiple revisions are specified.', self).run()
-            return
-
-        # Create new opts, so nothing unintented gets through
-        removeopts = self.merge_opts(commands.table['^remove|rm'][1], ('include', 'exclude'))
-        def dohgremove():
-            commands.remove(self.ui, self.repo, *files, **removeopts)
-        success, outtext = self._hg_call_wrapper('Remove', dohgremove)
-        if success:
-            self.reload_status()
-
-
-    def _tree_selection_changed(self, selection, force):
-        ''' Update the diff text '''
-        def dohgdiff():
-            self.restore_cwd()
-            difftext = StringIO.StringIO()
-            try:
-                if len(files) != 0:
-                    fns, matchfn, anypats = cmdutil.matchpats(self.repo, files, self.opts)
-                    patch.diff(self.repo, self._node1, self._node2, fns, match=matchfn,
-                               fp=difftext, opts=patch.diffopts(self.ui, self.opts))
-
-                buffer = gtk.TextBuffer()
-                buffer.create_tag('removed', foreground='#900000')
-                buffer.create_tag('added', foreground='#006400')
-                buffer.create_tag('position', foreground='#FF8000')
-                buffer.create_tag('header', foreground='#000090')
-
-                difftext.seek(0)
-                iter = buffer.get_start_iter()
-                for line in difftext:
-                    line = util.fromlocal(line)
-                    if line.startswith('---') or line.startswith('+++'):
-                        buffer.insert_with_tags_by_name(iter, line, 'header')
-                    elif line.startswith('-'):
-                        buffer.insert_with_tags_by_name(iter, line, 'removed')
-                    elif line.startswith('+'):
-                        buffer.insert_with_tags_by_name(iter, line, 'added')
-                    elif line.startswith('@@'):
-                        buffer.insert_with_tags_by_name(iter, line, 'position')
-                    else:
-                        buffer.insert(iter, line)
-
-                self.diff_text.set_buffer(buffer)
-            finally:
-                difftext.close()
-
-        if self.showdiff_toggle.get_active():
-            files = [self.model[iter][2] for iter in self.tree.get_selection().get_selected_rows()[1]]
-            if force or files != self._last_files:
-                self._last_files = files
-                self._hg_call_wrapper('Diff', dohgdiff)
-        return False
-
-
-    def _showdiff_toggled(self, togglebutton, data=None):
-        # prevent movement events while setting position
-        self._diffpane.handler_block(self._diffpane_moved_id)
-
-        if togglebutton.get_active():
-            self._tree_selection_changed(self.tree.get_selection(), True)
-            self._diffpane.set_position(self._setting_lastpos)
-        else:
-            self._setting_lastpos = self._diffpane.get_position()
-            self._diffpane.set_position(64000)
-            self.diff_text.set_buffer(gtk.TextBuffer())
-
-        self._diffpane.handler_unblock(self._diffpane_moved_id)
-        return True
-
-
-    def _diffpane_moved(self, paned, data=None):
-        # prevent toggle events while setting toolbar state
-        self.showdiff_toggle.handler_block(self._showdiff_toggled_id)
-        if self.diffbottom:
-            sizemax = self._diffpane.get_allocation().height
-        else:
-            sizemax = self._diffpane.get_allocation().width
-
-        if self.showdiff_toggle.get_active():
-            if paned.get_position() >=  sizemax - 55:
-                self.showdiff_toggle.set_active(False)
-                self.diff_text.set_buffer(gtk.TextBuffer())
-        elif paned.get_position() < sizemax - 55:
-            self.showdiff_toggle.set_active(True)
-            self._tree_selection_changed(self.tree.get_selection(), True)
-
-        self.showdiff_toggle.handler_unblock(self._showdiff_toggled_id)
-        return False
-        
-
-    def _refresh_clicked(self, toolbutton, data=None):
-        self.reload_status()
-        return True
-
-
-    def _revert_clicked(self, toolbutton, data=None):
-        revert_list = self._relevant_files('MAR!')
-        if len(revert_list) > 0:
-            self._hg_revert(revert_list)
-        else:
-            Prompt('Nothing Reverted', 'No revertable files selected', self).run()
-        return True
-
-
-    def _revert_file(self, stat, file):
-        self._hg_revert([file])
-        return True
-
-
-    def _log_file(self, stat, file):
-        # Might want to include 'rev' here... trying without
-        statopts = self.merge_opts(cmdtable['glog|ghistory'][1], ('include', 'exclude', 'git'))
-        dialog = GLog(self.ui, self.repo, [file], statopts, False)
-        dialog.display()
-        return True
-
-
-    def _hg_revert(self, files):
-        if self.count_revs() > 1:
-            Prompt('Nothing Reverted', 'Revert is not enabled when multiple revisions are specified.', self).run()
-            return
-
-        # Create new opts,  so nothing unintented gets through.
-        revertopts = self.merge_opts(commands.table['^revert'][1], ('include', 'exclude', 'rev'))
-        def dohgrevert():
-            commands.revert(self.ui, self.repo, *files, **revertopts)
-
-        # TODO: Ask which revision when multiple parents (currently just shows abort message)
-        # TODO: Don't need to prompt when reverting added or removed files
-        if self.count_revs() == 1:
-            # rev options needs extra tweaking since is not an array for revert command
-            revertopts['rev'] = revertopts['rev'][0]
-            dialog = Confirm('Revert', files, self, 'Revert files to revision ' + revertopts['rev'] + '?')
-        else:
-            dialog = Confirm('Revert', files, self)
-        if dialog.run() == gtk.RESPONSE_YES:
-            success, outtext = self._hg_call_wrapper('Revert', dohgrevert)
-            if success:
-                self.reload_status()
-
-    def _add_clicked(self, toolbutton, data=None):
-        add_list = self._relevant_files('?')
-        if len(add_list) > 0:
-            self._hg_add(add_list)
-        else:
-            Prompt('Nothing Added', 'No addable files selected', self).run()
-        return True
-
-
-    def _add_file(self, stat, file):
-        self._hg_add([file])
-        return True
-
-
-    def _hg_add(self, files):
-        # Create new opts, so nothing unintented gets through
-        addopts = self.merge_opts(commands.table['^add'][1], ('include', 'exclude'))
-        def dohgadd():
-            commands.add(self.ui, self.repo, *files, **addopts)
-        success, outtext = self._hg_call_wrapper('Add', dohgadd)
-        if success:
-            self.reload_status()
-
-
-    def _delete_clicked(self, toolbutton, data=None):
-        delete_list = self._relevant_files('?I')
-        if len(delete_list) > 0:
-            self._delete_files(delete_list)
-        else:
-            Prompt('Nothing Deleted', 'No deletable files selected', self).run()
-        return True
-
-
-    def _delete_file(self, stat, file):
-        self._delete_files([file])
-
-
-    def _delete_files(self, files):
-        dialog = Confirm('Delete', files, self)
-        if dialog.run() == gtk.RESPONSE_YES :
-            errors = ''
-            for file in files:
-                try: 
-                    os.unlink(self.repo.wjoin(file))
-                except Exception, inst:
-                    errors += str(inst) + '\n\n'
-
-            if errors:
-                errors = errors.replace('\\\\', '\\')
-                if len(errors) > 500:
-                    errors = errors[:errors.find('\n',500)] + '\n...'
-                Prompt('Delete Errors', errors, self).run()
-
-            self.reload_status()
-        return True
-
-
-    def _ignore_file(self, stat, file):
-        ignore = open(self.repo.wjoin('.hgignore'), 'a')
-        try:
-            try:
-                ignore.write('glob:' + util.pconvert(file) + '\n')
-            except IOError:
-                Prompt('Ignore Failed', 'Could not update .hgignore', self).run()
-        finally:
-            ignore.close()
-        self.reload_status()
-        return True
-
-
-    def _sel_desel_clicked(self, toolbutton, state):
-        for entry in self.model : entry[0] = state
-        return True
-
-
-    def _relevant_files(self, stats):
-        return [item[2] for item in self.model if item[0] and item[1] in stats]
-
-
-    def _context_menu_act(self, menuitem, handler):
-        selection = self.tree.get_selection()
-        assert(selection.count_selected_rows() == 1)
-
-        list, paths = selection.get_selected_rows() 
-        path = paths[0]
-        handler(list[path][1], list[path][2])
-        return True
-
-
-    def _tree_button_press(self, widget, event) :
-        # Set the flag to ignore the next activation when the shift/control keys are
-        # pressed. This avoids activations with multiple rows selected.
-        if event.type == gtk.gdk._2BUTTON_PRESS and  \
-          (event.state & (gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK)):
-            self._ignore_next_act = True
-        else:
-            self._ignore_next_act = False
-        return False
-
-
-    def _tree_button_release(self, widget, event) :
-        if event.button == 3 and not (event.state & (gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK)):
-            self._tree_popup_menu(widget, event.button, event.time)
-        return False
-
-
-    def _tree_popup_menu(self, widget, button=0, time=0) :
-        selection = self.tree.get_selection()
-        if selection.count_selected_rows() != 1:
-            return False
-
-        list, paths = selection.get_selected_rows() 
-        path = paths[0]
-        menu = self._menus[list[path][1]]
-        menu.popup(None, None, None, button, time)
-        return True
-
-
-    def _tree_key_press(self, tree, event):
-        if event.keyval == 32:
-            def toggler(list, path, iter):
-                list[path][0] = not list[path][0]
-
-            selection = self.tree.get_selection()
-            selection.selected_foreach(toggler)
-            return True
-        return False
-
-
-    def _tree_row_act(self, tree, path, column) :
-        """Default action is the first entry in the context menu
-        """
-        # Ignore activations (like double click) on the first column,
-        # and ignore all actions if the flag is set
-        if column.get_sort_column_id() == 0 or self._ignore_next_act:
-            self._ignore_next_act = False
-            return True
-
-        selection = self.tree.get_selection()
-        if selection.count_selected_rows() != 1:
-            return False
-
-        list, paths = selection.get_selected_rows() 
-        path = paths[0]
-        menu = self._menus[list[path][1]]
-        menu.get_children()[0].activate()
-        return True
-
-
-class GCommit(GStatus):
-    """GTK+ based dialog for displaying repository status and committing changes.
-
-    Also provides related operations like add, delete, remove, revert, refresh,
-    ignore, diff, and edit.
-    """
-
-    ### Overrides of base class methods ###
-
-    def parse_opts(self):
-        GStatus.parse_opts(self)
-
-        # Need an entry, because extdiff code expects it
-        if not self.test_opt('rev'):
-            self.opts['rev'] = ''
-
-        if self.test_opt('message'):
-            buffer = gtk.TextBuffer()
-            buffer.set_text(self.opts['message'])
-            self.text.set_buffer(buffer)
-
-        if self.test_opt('logfile'):
-            buffer = gtk.TextBuffer()
-            buffer.set_text('Comment will be read from file ' + self.opts['logfile'])
-            self.text.set_buffer(buffer)
-            self.text.set_sensitive(False)
-
-
-    def get_title(self):
-        return os.path.basename(self.repo.root) + ' commit ' + ' '.join(self.pats) + ' ' + self.opts['user'] + ' ' + self.opts['date']
-
-
-    def auto_check(self):
-        if self.test_opt('check'):
-            for entry in self.model : 
-                if entry[1] in 'MAR':
-                    entry[0] = True
-
-
-    def save_settings(self):
-        settings = GStatus.save_settings(self)
-        settings['gcommit'] = self._vpaned.get_position()
-        return settings
-
-
-    def load_settings(self, settings):
-        GStatus.load_settings(self, settings)
-        if settings:
-            self._setting_vpos = settings['gcommit']
-        else:
-            self._setting_vpos = -1
-
-
-    def get_tbbuttons(self):
-        tbbuttons = GStatus.get_tbbuttons(self)
-        tbbuttons.insert(2, self.make_toolbutton(gtk.STOCK_OK, '_commit', self._commit_clicked))
-        return tbbuttons
-
-
-    def get_body(self):
-        status_body = GStatus.get_body(self)
-
-        frame = gtk.Frame()
-        frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-        frame.add(scroller)
-        
-        self.text = gtk.TextView()
-        self.text.set_wrap_mode(gtk.WRAP_WORD)
-        self.text.modify_font(pango.FontDescription(self.fontcomment))
-        scroller.add(self.text)
-        
-        self._vpaned = gtk.VPaned()
-        self._vpaned.add1(frame)
-        self._vpaned.add2(status_body)
-        self._vpaned.set_position(self._setting_vpos)
-        return self._vpaned
-
-
-    def get_menu_info(self):
-        """Returns menu info in this order: merge, addrem, unknown, clean, ignored, deleted
-        """
-        merge, addrem, unknown, clean, ignored, deleted  = GStatus.get_menu_info(self)
-        return (merge + (('_commit', self._commit_file),),
-                addrem + (('_commit', self._commit_file),),
-                unknown + (('_commit', self._commit_file),),
-                clean,
-                ignored,
-                deleted + (('_commit', self._commit_file),))
-
-
-    def should_live(self, widget=None, event=None):
-        # If there are more than a few character typed into the commit
-        # message, ask if the exit should continue.
-        live = False
-        if self.text.get_buffer().get_char_count() > 10:
-            dialog = Confirm('Exit', [], self, 'Discard commit message and exit?')
-            if dialog.run() == gtk.RESPONSE_NO:
-                live = True
-        return live
-
-    ### End of overridable methods ###
-
-
-    def _commit_clicked(self, toolbutton, data=None):
-        if not self._ready_message():
-            return True
-
-        commitable = 'MAR'
-        addremove_list = self._relevant_files('?!')
-        if len(addremove_list) and self._should_addremove(addremove_list):
-            commitable += '?!'
-
-        commit_list = self._relevant_files(commitable)
-        if len(commit_list) > 0:
-            self._hg_commit(commit_list)
-        else:
-            Prompt('Nothing Commited', 'No committable files selected', self).run()
-        return True
-
-
-    def _commit_file(self, stat, file):
-        if self._ready_message():
-            if stat not in '?!' or self._should_addremove([file]):
-                self._hg_commit([file])
-        return True
-
-
-    def _should_addremove(self, files):
-        if self.test_opt('addremove'):
-            return True
-        else:
-            response = Confirm('Add/Remove', files, self).run() 
-            if response == gtk.RESPONSE_YES:
-                # This will stay set for further commits (meaning no more prompts). Problem?
-                self.opts['addremove'] = True
-                return True
-        return False
-
-
-    def _ready_message(self):
-        begin, end = self.text.get_buffer().get_bounds()
-        message = self.text.get_buffer().get_text(begin, end) 
-        if not self.test_opt('logfile') and not message:
-            Prompt('Nothing Commited', 'Please enter commit message', self).run()
-            self.text.grab_focus()
-            return False
-        else:
-            if not self.test_opt('logfile'):
-                self.opts['message'] = message
-            return True
-
-
-    def _hg_commit(self, files):
-        # In case new commit args are added in the future, merge the hg defaults
-        commitopts = self.merge_opts(commands.table['^commit|ci'][1], [name[1] for name in cmdtable['gcommit|gci'][1]])
-        def dohgcommit():
-            commands.commit(self.ui, self.repo, *files, **commitopts)
-        success, outtext = self._hg_call_wrapper('Commit', dohgcommit)
-        if success:
-            self.text.set_buffer(gtk.TextBuffer())
-            self.reload_status()
-
-
-class NativeSaveFileDialogWrapper:
-    """Wrap the windows file dialog, or display default gtk dialog if that isn't available"""
-    def __init__(self, InitialDir = None, Title = "Save File", Filter = {"All files": "*.*"}, FilterIndex = 1):
-        import os.path
-        if InitialDir == None:
-            InitialDir = os.path.expanduser("~")
-        self.InitialDir = InitialDir
-        self.Title = Title
-        self.Filter = Filter
-        self.FilterIndex = FilterIndex
-
-    def run(self):
-        """run the file dialog, either return a file name, or False if the user aborted the dialog"""
-        try:
-            import win32gui
-            if self.tortoiseHgIsInstalled(): #as of 20071021, the file dialog will hang if the tortoiseHg shell extension is installed. I have no clue why, yet - Tyberius Prime
-                   return self.runCompatible()
-            else:
-                    return self.runWindows()
-        except ImportError:
-            return self.runCompatible()
-
-    def tortoiseHgIsInstalled(self):
-        import _winreg
-        try:
-            hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,r"Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\Changed")
-            if hkey:
-                cls = _winreg.QueryValue(hkey,"")
-                return cls == "{102C6A24-5F38-4186-B64A-237011809FAB}"
-        except WindowsError: #reg key not found
-            pass
-        return False
-
-    def runWindows(self):
-        import win32gui, win32con, os
-        filter = ""
-        for name, pattern in self.Filter.items():
-            filter += name + "\0" + pattern + "\0"
-        customfilter = "\0"
-
-        fname, customfilter, flags=win32gui.GetSaveFileNameW(
-            InitialDir=self.InitialDir,
-            Flags=win32con.OFN_EXPLORER,
-            File='', DefExt='py',
-            Title=self.Title,
-            Filter="",
-            CustomFilter="",
-            FilterIndex=1)
-        if fname:
-            return fname
-        else:
-           return False
-
-    def runCompatible(self):
-        file_save =gtk.FileChooserDialog(self.Title,None,
-                gtk.FILE_CHOOSER_ACTION_SAVE
-                , (gtk.STOCK_CANCEL
-                    , gtk.RESPONSE_CANCEL
-                    , gtk.STOCK_SAVE
-                    , gtk.RESPONSE_OK))
-        file_save.set_default_response(gtk.RESPONSE_OK)
-        file_save.set_current_folder(self.InitialDir)
-        for name, pattern in self.Filter.items():
-            fi = gtk.FileFilter()
-            fi.set_name(name)
-            fi.add_pattern(pattern)
-            file_save.add_filter(fi)
-        if file_save.run() == gtk.RESPONSE_OK:
-            result = file_save.get_filename();
-        else:
-            result = False
-        file_save.destroy()
-        return result
-
-
-
-def findrepo():
-    p = os.getcwd()
-    while not os.path.isdir(os.path.join(p, '.hg')):
-        oldp, p = p, os.path.dirname(p)
-        if p == oldp:
-            return None
-    return p
-
-if __name__ == '__main__':
-    u = ui.ui()
-    u.updateopts(debug=False, traceback=False)
-    repo = hg.repository(u, findrepo())
-    gstatus(u, repo, all=False, clean=False, ignored=False, modified=True,
-           added=True, removed=True, deleted=True, unknown=True, rev=[],
-           exclude=[], include=[], debug=True,
-           verbose=True )
-#   logparams = {'follow_first': None, 'style': '', 'include': [], 'verbose': True,
-#               'only_merges': None, 'keyword': [], 'rev': [], 'copies': None, 'template': '',
-#               'patch': None, 'limit': 20, 'no_merges': None, 'exclude': [], 'date': '',
-#               'follow': None, 'removed': None, 'prune': [], 'verbose':True }
-#    glog(u, repo, **logparams )
-
diff --git a/mercurial-doc.patch b/mercurial-doc.patch
deleted file mode 100644
index 483f856..0000000
--- a/mercurial-doc.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- mercurial-3.5.2/mercurial/demandimport.py~	2015-10-01 19:06:55.000000000 +0200
-+++ mercurial-3.5.2/mercurial/demandimport.py	2015-10-27 10:27:30.377611999 +0100
-@@ -173,7 +173,8 @@ ignore = [
-     'rfc822',
-     'mimetools',
-     # setuptools 8 expects this module to explode early when not on windows
--    'distutils.msvc9compiler'
-+    'distutils.msvc9compiler',
-+    'gobject._gobject'
-     ]
- 
- def isenabled():
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/mercurial.git/commitdiff/c748309cdc47d6b31e08b4b65986ec7c0155184c



More information about the pld-cvs-commit mailing list