topics: take locks and start transaction before calling _changetopics
authorPulkit Goyal <7895pulkit@gmail.com>
Mon, 14 Aug 2017 11:39:06 +0530
changeset 2850 a0d6741d4bb8
parent 2849 95470e817c00
child 2851 a13acecbc850
topics: take locks and start transaction before calling _changetopics This will help us in calling _changetopics in other transactions which already started. Currently the _changetopics creates its own transaction and hence can't be used it a same transaction with any other function or logic.
hgext3rd/topic/__init__.py
--- a/hgext3rd/topic/__init__.py	Mon Aug 21 19:44:23 2017 +0200
+++ b/hgext3rd/topic/__init__.py	Mon Aug 14 11:39:06 2017 +0530
@@ -356,7 +356,18 @@
             raise error.Abort('changing topic requires a topic name or --clear')
         if any(not c.mutable() for c in repo.set('%r and public()', rev)):
             raise error.Abort("can't change topic of a public change")
-        return _changetopics(ui, repo, rev, topic)
+        wl = l = txn = None
+        try:
+            wl = repo.wlock()
+            l = repo.lock()
+            txn = repo.transaction('rewrite-topics')
+            rewrote = _changetopics(ui, repo, rev, topic)
+            txn.close()
+        finally:
+            lock.release(txn, l, wl)
+            repo.invalidate()
+            ui.status('changed topic on %d changes\n' % rewrote)
+        return
 
     if clear:
         return _changecurrenttopic(repo, None)
@@ -397,72 +408,66 @@
             repo.vfs.unlink('topic')
 
 def _changetopics(ui, repo, revset, newtopic):
+    """ Changes topic to newtopic of all the revisions in the revset and return
+    the count of revisions whose topic has been changed.
+    """
     rewrote = 0
-    wl = l = txn = None
-    try:
-        wl = repo.wlock()
-        l = repo.lock()
-        txn = repo.transaction('rewrite-topics')
-        p1 = None
-        p2 = None
-        successors = {}
-        for c in repo.set('%r', revset):
-            def filectxfn(repo, ctx, path):
-                try:
-                    return c[path]
-                except error.ManifestLookupError:
-                    return None
-            fixedextra = dict(c.extra())
-            ui.debug('old node id is %s\n' % node.hex(c.node()))
-            ui.debug('origextra: %r\n' % fixedextra)
-            oldtopic = fixedextra.get(constants.extrakey, None)
-            if oldtopic == newtopic:
-                continue
-            if newtopic is None:
-                del fixedextra[constants.extrakey]
-            else:
-                fixedextra[constants.extrakey] = newtopic
-            fixedextra[constants.changekey] = c.hex()
-            if 'amend_source' in fixedextra:
-                # TODO: right now the commitctx wrapper in
-                # topicrepo overwrites the topic in extra if
-                # amend_source is set to support 'hg commit
-                # --amend'. Support for amend should be adjusted
-                # to not be so invasive.
-                del fixedextra['amend_source']
-            ui.debug('changing topic of %s from %s to %s\n' % (
-                c, oldtopic, newtopic))
-            ui.debug('fixedextra: %r\n' % fixedextra)
-            # While changing topic of set of linear commits, make sure that
-            # we base our commits on new parent rather than old parent which
-            # was obsoleted while changing the topic
-            p1 = c.p1().node()
-            p2 = c.p2().node()
-            if p1 in successors:
-                p1 = successors[p1]
-            if p2 in successors:
-                p2 = successors[p2]
-            mc = context.memctx(
-                repo, (p1, p2), c.description(),
-                c.files(), filectxfn,
-                user=c.user(), date=c.date(), extra=fixedextra)
-            newnode = repo.commitctx(mc)
-            successors[c.node()] = newnode
-            ui.debug('new node id is %s\n' % node.hex(newnode))
-            obsolete.createmarkers(repo, [(c, (repo[newnode],))])
-            rewrote += 1
-        # move the working copy too
-        wctx = repo[None]
-        # in-progress merge is a bit too complex for now.
-        if len(wctx.parents()) == 1:
-            newid = successors.get(wctx.p1().node())
-            if newid is not None:
-                hg.update(repo, newid, quietempty=True)
-        txn.close()
-    finally:
-        lock.release(txn, l, wl)
-        repo.invalidate()
-    ui.status('changed topic on %d changes\n' % rewrote)
+    p1 = None
+    p2 = None
+    successors = {}
+    for c in repo.set('%r', revset):
+        def filectxfn(repo, ctx, path):
+            try:
+                return c[path]
+            except error.ManifestLookupError:
+                return None
+        fixedextra = dict(c.extra())
+        ui.debug('old node id is %s\n' % node.hex(c.node()))
+        ui.debug('origextra: %r\n' % fixedextra)
+        oldtopic = fixedextra.get(constants.extrakey, None)
+        if oldtopic == newtopic:
+            continue
+        if newtopic is None:
+            del fixedextra[constants.extrakey]
+        else:
+            fixedextra[constants.extrakey] = newtopic
+        fixedextra[constants.changekey] = c.hex()
+        if 'amend_source' in fixedextra:
+            # TODO: right now the commitctx wrapper in
+            # topicrepo overwrites the topic in extra if
+            # amend_source is set to support 'hg commit
+            # --amend'. Support for amend should be adjusted
+            # to not be so invasive.
+            del fixedextra['amend_source']
+        ui.debug('changing topic of %s from %s to %s\n' % (
+            c, oldtopic, newtopic))
+        ui.debug('fixedextra: %r\n' % fixedextra)
+        # While changing topic of set of linear commits, make sure that
+        # we base our commits on new parent rather than old parent which
+        # was obsoleted while changing the topic
+        p1 = c.p1().node()
+        p2 = c.p2().node()
+        if p1 in successors:
+            p1 = successors[p1]
+        if p2 in successors:
+            p2 = successors[p2]
+        mc = context.memctx(
+            repo, (p1, p2), c.description(),
+            c.files(), filectxfn,
+            user=c.user(), date=c.date(), extra=fixedextra)
+        newnode = repo.commitctx(mc)
+        successors[c.node()] = newnode
+        ui.debug('new node id is %s\n' % node.hex(newnode))
+        obsolete.createmarkers(repo, [(c, (repo[newnode],))])
+        rewrote += 1
+    # move the working copy too
+    wctx = repo[None]
+    # in-progress merge is a bit too complex for now.
+    if len(wctx.parents()) == 1:
+        newid = successors.get(wctx.p1().node())
+        if newid is not None:
+            hg.update(repo, newid, quietempty=True)
+    return rewrote
 
 def _listtopics(ui, repo, opts):
     fm = ui.formatter('topics', opts)