ANN/RFC: extension that shows evolution of a range of lines in a file

Peter Arrenbrecht peter.arrenbrecht at gmail.com
Wed Apr 14 14:45:12 CDT 2010


I wrote a little extension that shows you the evolution (or maybe
devolution as it's backwards currently) of a range of lines in a file.
As an example, you can find the evolution of checkbranch() in
localrepo.py below. The extension is attached.

This is just a rough draft to get feedback. I'm thinking that it might
be good to have this as part of graphlog as it currently does not
indicate forks and joins. This might be non-trivial as when we start
omitting nodes, we have to somehow keep track of and properly show
node relationships. Or else it would have to only follow linear
history (for instance by always choosing parent 1).

Also, I think it could really shine as part of TortoiseHg. You view a
file, select a range of lines and say "show me the evolution" (that's
presuming THg gets a proper manifest/source view to select the lines
in). Then THg shows you a tree of all revs where the lines were
changed. Select nodes in the tree and you see both the diff introduced
at this node, as well as the current state of the lines at this node.

Thoughts?
-parren


Example session:

$ hg evolution --diff mercurial/localrepo.py 1525 1551

working copy
===================
        def checkbranch(lheads, rheads, branchname=None):
            '''
            check whether there are more local heads than remote heads on
            a specific branch.

            lheads: local branch heads
            rheads: remote branch heads
            '''
            newlheads = [n for n in lheads if n in outgoingnodeset]
            formerrheads = [n for n in rheads if n in nolongeraheadnodeset]
            if len(newlheads) > len(formerrheads):
                # we add more new heads than we demote former heads to non-head
                if branchname is not None:
                    msg = _("abort: push creates new remote heads"
                            " on branch '%s'!\n") % branchname
                else:
                    msg = _("abort: push creates new remote heads!\n")
                self.ui.warn(msg)
                if len(lheads) > len(rheads):
                    self.ui.status(_("(did you forget to merge?"
                                     " use push -f to force)\n"))
                else:
                    self.ui.status(_("(you should pull and merge or"
                                     " use push -f to force)\n"))
                return False
            return True
===================
changeset:   10990:dc097666de01
user:        Peter Arrenbrecht <peter.arrenbrecht at gmail.com>
date:        Thu Apr 08 17:21:42 2010 +0200
summary:     localrepo: refactor prepush logic

===================
@@ -6,33 +6,10 @@
             lheads: local branch heads
             rheads: remote branch heads
             '''
-
-            warn = 0
-
-            if len(lheads) > len(rheads):
-                warn = 1
-            else:
-                # add local heads involved in the push
-                updatelheads = [self.changelog.heads(x, lheads)
-                                for x in update]
-                newheads = set(sum(updatelheads, [])) & set(lheads)
-
-                if not newheads:
-                    return True
-
-                # add heads we don't have or that are not involved in the push
-                for r in rheads:
-                    if r in self.changelog.nodemap:
-                        desc = self.changelog.heads(r, heads)
-                        l = [h for h in heads if h in desc]
-                        if not l:
-                            newheads.add(r)
-                    else:
-                        newheads.add(r)
-                if len(newheads) > len(rheads):
-                    warn = 1
-
-            if warn:
+            newlheads = [n for n in lheads if n in outgoingnodeset]
+            formerrheads = [n for n in rheads if n in nolongeraheadnodeset]
+            if len(newlheads) > len(formerrheads):
+                # we add more new heads than we demote former heads to non-head
                 if branchname is not None:
                     msg = _("abort: push creates new remote heads"
                             " on branch '%s'!\n") % branchname

===================
changeset:   10988:a9702c47a19f
branch:      stable
user:        Sune Foldager <cryo at cyanite.org>
date:        Thu Apr 08 19:46:47 2010 +0200
summary:     partial backout of 1e819576e926 and add tests (issue2131)

===================
@@ -12,8 +12,15 @@
             if len(lheads) > len(rheads):
                 warn = 1
             else:
+                # add local heads involved in the push
+                updatelheads = [self.changelog.heads(x, lheads)
+                                for x in update]
+                newheads = set(sum(updatelheads, [])) & set(lheads)
+
+                if not newheads:
+                    return True
+
                 # add heads we don't have or that are not involved in the push
-                newheads = set(lheads)
                 for r in rheads:
                     if r in self.changelog.nodemap:
                         desc = self.changelog.heads(r, heads)

===================
changeset:   10857:1e819576e926
branch:      stable
user:        Sune Foldager <cryo at cyanite.org>
date:        Fri Mar 26 17:02:49 2010 +0100
summary:     push: refactor and optimize prepush

===================
@@ -1,27 +1,19 @@
-        def checkbranch(lheads, rheads, updatelb, branchname=None):
+        def checkbranch(lheads, rheads, branchname=None):
             '''
             check whether there are more local heads than remote heads on
             a specific branch.

             lheads: local branch heads
             rheads: remote branch heads
-            updatelb: outgoing local branch bases
             '''

             warn = 0

-            if not revs and len(lheads) > len(rheads):
+            if len(lheads) > len(rheads):
                 warn = 1
             else:
-                # add local heads involved in the push
-                updatelheads = [self.changelog.heads(x, lheads)
-                                for x in updatelb]
-                newheads = set(sum(updatelheads, [])) & set(lheads)
-
-                if not newheads:
-                    return True
-
                 # add heads we don't have or that are not involved in the push
+                newheads = set(lheads)
                 for r in rheads:
                     if r in self.changelog.nodemap:
                         desc = self.changelog.heads(r, heads)

===================
changeset:   10502:1c50a954a524
parent:      10500:400ffd5f2f14
parent:      10501:e553a425751d
user:        Patrick Mezard <pmezard at gmail.com>
date:        Sat Feb 13 02:06:13 2010 +0100
summary:     Merge with crew-stable

===================
@@ -1,4 +1,4 @@
-        def checkbranch(lheads, rheads, updatelb):
+        def checkbranch(lheads, rheads, updatelb, branchname=None):
             '''
             check whether there are more local heads than remote heads on
             a specific branch.
@@ -34,14 +34,17 @@
                     warn = 1

             if warn:
-                if not rheads: # new branch requires --force
-                    self.ui.warn(_("abort: push creates new"
-                                   " remote branch '%s'!\n") %
-                                   self[lheads[0]].branch())
+                if branchname is not None:
+                    msg = _("abort: push creates new remote heads"
+                            " on branch '%s'!\n") % branchname
                 else:
-                    self.ui.warn(_("abort: push creates new remote heads!\n"))
-
-                self.ui.status(_("(did you forget to merge?"
-                                 " use push -f to force)\n"))
+                    msg = _("abort: push creates new remote heads!\n")
+                self.ui.warn(msg)
+                if len(lheads) > len(rheads):
+                    self.ui.status(_("(did you forget to merge?"
+                                     " use push -f to force)\n"))
+                else:
+                    self.ui.status(_("(you should pull and merge or"
+                                     " use push -f to force)\n"))
                 return False
             return True
===================
changeset:   9977:d6a307719ccb
branch:      stable
parent:      9975:5b149c88d9e8
user:        Sune Foldager <cryo at cyanite.org>
date:        Mon Nov 30 14:58:52 2009 +0100
summary:     fix bug in prepush logic involving merge changesets

===================
@@ -37,7 +37,7 @@
                 if not rheads: # new branch requires --force
                     self.ui.warn(_("abort: push creates new"
                                    " remote branch '%s'!\n") %
-                                   self[updatelb[0]].branch())
+                                   self[lheads[0]].branch())
                 else:
                     self.ui.warn(_("abort: push creates new remote heads!\n"))


===================
changeset:   9479:f3569d95c2ab
parent:      9475:c295a82a020b
user:        Sune Foldager <cryo at cyanite.org>
date:        Wed Sep 23 18:56:09 2009 +0200
summary:     push: fix subtle bug in prepush logic

===================
@@ -1,11 +1,11 @@
-        def checkbranch(lheads, rheads, updatelh):
+        def checkbranch(lheads, rheads, updatelb):
             '''
             check whether there are more local heads than remote heads on
             a specific branch.

             lheads: local branch heads
             rheads: remote branch heads
-            updatelh: outgoing local branch heads
+            updatelb: outgoing local branch bases
             '''

             warn = 0
@@ -13,13 +13,15 @@
             if not revs and len(lheads) > len(rheads):
                 warn = 1
             else:
+                # add local heads involved in the push
                 updatelheads = [self.changelog.heads(x, lheads)
-                                for x in updatelh]
+                                for x in updatelb]
                 newheads = set(sum(updatelheads, [])) & set(lheads)

                 if not newheads:
                     return True

+                # add heads we don't have or that are not involved in the push
                 for r in rheads:
                     if r in self.changelog.nodemap:
                         desc = self.changelog.heads(r, heads)
@@ -35,7 +37,7 @@
                 if not rheads: # new branch requires --force
                     self.ui.warn(_("abort: push creates new"
                                    " remote branch '%s'!\n") %
-                                   self[updatelh[0]].branch())
+                                   self[updatelb[0]].branch())
                 else:
                     self.ui.warn(_("abort: push creates new remote heads!\n"))


===================
changeset:   8916:3df8dbf706b0
parent:      8915:c57336de5c12
parent:      8879:d0a3eadfbdb3
user:        Martin Geisler <mg at lazybytes.net>
date:        Sun Jun 21 19:06:57 2009 +0200
summary:     merged with crew

===================
@@ -34,8 +34,8 @@
             if warn:
                 if not rheads: # new branch requires --force
                     self.ui.warn(_("abort: push creates new"
-                                   " remote branch '%s'!\n" %
-                                   self[updatelh[0]].branch()))
+                                   " remote branch '%s'!\n") %
+                                   self[updatelh[0]].branch())
                 else:
                     self.ui.warn(_("abort: push creates new remote heads!\n"))


===================
-------------- next part --------------
A non-text attachment was scrubbed...
Name: evolution.py
Type: application/octet-stream
Size: 4004 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial/attachments/20100414/a6962f20/attachment.obj>


More information about the Mercurial mailing list