Commits

Steve Borho committed 14a6962

partialcommit: move partialcommit function into an extension module

partialcommit.py is a TortoiseHg specific Mercurial extension which wraps the
commit command and adds a --partials option. This gives us proper hook support
and makes the implementation much cleaner.

  • Participants
  • Parent commits 7902461

Comments (0)

Files changed (3)

File tortoisehg/hgqt/commit.py

 from tortoisehg.hgqt.i18n import _
 from tortoisehg.hgqt.messageentry import MessageEntry
 from tortoisehg.hgqt import qtlib, qscilib, status, cmdui, branchop, revpanel
-from tortoisehg.hgqt import hgrcutil, mqutil, lfprompt, i18n
+from tortoisehg.hgqt import hgrcutil, mqutil, lfprompt, i18n, partialcommit
 
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
                    '--user', user, '--message='+msg]
         cmdline += dcmd + brcmd
 
-        if 0 and self.stwidget.partials:
-            cmdline[0] = 'partialcommit'
+        if self.stwidget.partials:
+            partialcommit.uisetup(repo.ui)
             cmdline.append('--partials')
             cmdline.append(self.stwidget.partials)
+            # TODO: --subrepos will likely not be supported
             assert not amend
 
         if self.opts.get('recurseinsubrepos'):
         if not self.files and canemptycommit and not merge:
             # make sure to commit empty changeset by excluding all files
             cmdline.extend(['--exclude', repo.root])
+            assert not self.stwidget.partials
 
         cmdline.append('--')
         cmdline.extend([repo.wjoin(f) for f in self.files])

File tortoisehg/hgqt/partialcommit.py

+# partialcommit.py - commit extension for partial commits (change selection)
+#
+# Copyright 2013 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 cStringIO
+
+from mercurial.i18n import _
+from mercurial import patch, hg, commands, extensions
+
+def partialcommit(orig, ui, repo, *pats, **opts):
+    if 'partials' not in opts:
+        return orig(ui, repo, *pats, **opts)
+
+    partials = opts['partials']
+    fp = cStringIO.StringIO()
+    patchfiles = []
+    for changes in partials.values():
+        patchfiles.append(changes.filename())
+        changes.write(fp)
+        for chunk in changes.hunks:
+            if not chunk.excluded:
+                chunk.write(fp)
+    fp.seek(0)
+
+    # TODO: --close-branch and other options
+
+    repo = hg.repository(ui, repo.root, False)
+    store = patch.filestore()
+    newrev = None
+    try:
+        pctx = repo['.']
+
+        # patch files in tmp directory
+        try:
+            patch.patchrepo(ui, repo, pctx, store, fp, 1, partials.keys())
+        except patch.PatchError, e:
+            raise util.Abort(str(e))
+
+        # create new revision from memory
+        memctx = patch.makememctx(repo, (pctx.node(), None),
+                                    opts['message'],
+                                    opts.get('user'),
+                                    opts.get('date'),
+                                    repo[None].branch(), 
+                                    files,
+                                    store,
+                                    editor=None)
+        newrev = memctx.commit()
+    finally:
+        store.close()
+
+    # move working directory to new revision
+    if newrev:
+        wlock = repo.wlock()
+        try:
+            repo.setparents(newrev)
+            ctx = repo[newrev]
+            repo.dirstate.rebuild(ctx.node(), ctx.manifest())
+            return 0
+        finally:
+            wlock.release()
+    return 1
+
+# We're not using Mercurial's extension loader (so partialcommit will not
+# show up in the list of extensions on traceback), so we must protect ourselves
+# from multiple registrations
+
+registered = False
+def uisetup(ui):
+    'Replace commit with a decorator to provide --partials option'
+    if registered:
+        return
+    entry = extensions.wrapcommand(commands.table, 'commit', partialcommit)
+    entry[1].append(('', 'partials', [],
+                     _("selected patch chunks (internal use only)")))
+    registered = True

File tortoisehg/hgqt/thread.py

-# thread.py - A seprated thread to run Mercurial command
+# thread.py - A separate thread to run Mercurial commands
 #
 # Copyright 2009 Steve Borho <steve@borho.org>
 # Copyright 2010 Yuki KODAMA <endflow.net@gmail.com>
 
 import os
 import Queue
-import cStringIO
 import time
 import urllib2
 import socket
                 text = None
             self.responseq.put(text)
 
-    def partialcommit(self, _ui, cmdline):
-        'special commit which uses patch and memctx for partial selection'
-        # TODO: parse cmdline into opts, files, partials
-        opts = {}
-        files = ()
-        partials = {}
-
-        fp = cStringIO.StringIO()
-        patchfiles = []
-        for changes in partials.values():
-            patchfiles.append(changes.filename())
-            changes.write(fp)
-            for chunk in changes.hunks:
-                if not chunk.excluded:
-                    chunk.write(fp)
-        fp.seek(0)
-
-        newrev = None
-        repo = hg.repository(_ui, self.root, False)
-        store = patch.filestore()
-        contenders = set(files + patchfiles)
-        try:
-            pctx = repo['.']
-
-            # patch files in tmp directory
-            try:
-                patch.patchrepo(_ui, repo, pctx, store, fp, 1, patchfiles)
-            except patch.PatchError, e:
-                raise util.Abort(str(e))
-
-            # create new revision from memory
-            memctx = patch.makememctx(repo, (pctx.node(), None),
-                                      opts['message'],
-                                      opts.get('user'),
-                                      opts.get('date'),
-                                      repo[None].branch(), 
-                                      contenders,
-                                      store,
-                                      editor=None)
-            newrev = memctx.commit()
-        finally:
-            store.close()
-
-        # move working directory to new revision
-        if newrev:
-            wlock = repo.wlock()
-            try:
-                repo.setparents(newrev)
-                ctx = repo[newrev]
-                repo.dirstate.rebuild(ctx.node(), ctx.manifest())
-                return 0
-            finally:
-                wlock.release()
-        return 1
-
     def run(self):
         ui = QtUi(responseq=self.responseq)
         ui.sig.writeSignal.connect(self.output_handler,
         ui.sig.interactSignal.connect(self.interact_handler,
                 Qt.QueuedConnection)
 
-        if self.cmdline[0] == 'partialcommit':
-            cmd = '%% hg partialcommit\n'
+        if self.cmdline[0] == 'commit' and '--partials' in self.cmdline:
+            cmd = '%% hg commit --partials\n'
         elif self.display:
             cmd = '%% hg %s\n' % self.display
         else:
             for k, v in ui.configitems('defaults'):
                 ui.setconfig('defaults', k, '')
             self.ret = 255
-            if self.cmdline[0] == 'partialcommit':
-                self.ret = self.partialcommit(ui, self.cmdline) or 0
-            else:
-                self.ret = hglib.dispatch(ui, self.cmdline) or 0
+            self.ret = hglib.dispatch(ui, self.cmdline) or 0
         except util.Abort, e:
             ui.write_err(local._('abort: ') + str(e) + '\n')
             if e.hint: