changeset 18819:05acdf8e1f23

convert: add closesort algorithm to mercurial sources If you actively work with branches, sometimes you need to close old branches which last commited hundreds revisions ago. After close you will see long lines in graph visually spoiling history. This sort only moves closed revisions as close as possible to parents and does not increase storage size as datesort do.
author Constantine Linnick <theaspect@gmail.com>
date Sun, 24 Mar 2013 00:06:52 +0700
parents a0bff3d4f67b
children a45e44d76c81
files hgext/convert/__init__.py hgext/convert/common.py hgext/convert/convcmd.py hgext/convert/hg.py tests/test-convert-datesort.t tests/test-convert.t
diffstat 6 files changed, 159 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/convert/__init__.py	Sun Mar 24 16:43:25 2013 -0700
+++ b/hgext/convert/__init__.py	Sun Mar 24 00:06:52 2013 +0700
@@ -61,6 +61,10 @@
     --sourcesort  try to preserve source revisions order, only
                   supported by Mercurial sources.
 
+    --closesort   try to move closed revisions as close as possible
+                  to parent branches, only supported by Mercurial
+                  sources.
+
     If ``REVMAP`` isn't given, it will be put in a default location
     (``<dest>/.hg/shamap`` by default). The ``REVMAP`` is a simple
     text file that maps each source commit ID to the destination ID
@@ -318,7 +322,8 @@
            _('change branch names while converting'), _('FILE')),
           ('', 'branchsort', None, _('try to sort changesets by branches')),
           ('', 'datesort', None, _('try to sort changesets by date')),
-          ('', 'sourcesort', None, _('preserve source changesets order'))],
+          ('', 'sourcesort', None, _('preserve source changesets order')),
+          ('', 'closesort', None, _('try to reorder closed revisions'))],
          _('hg convert [OPTION]... SOURCE [DEST [REVMAP]]')),
     "debugsvnlog":
         (debugsvnlog,
--- a/hgext/convert/common.py	Sun Mar 24 16:43:25 2013 -0700
+++ b/hgext/convert/common.py	Sun Mar 24 00:06:52 2013 +0700
@@ -145,6 +145,11 @@
         """
         return False
 
+    def hasnativeclose(self):
+        """Return true if this source has ability to close branch.
+        """
+        return False
+
     def lookuprev(self, rev):
         """If rev is a meaningful revision reference in source, return
         the referenced identifier in the same format used by getcommit().
--- a/hgext/convert/convcmd.py	Sun Mar 24 16:43:25 2013 -0700
+++ b/hgext/convert/convcmd.py	Sun Mar 24 00:06:52 2013 +0700
@@ -227,6 +227,14 @@
                 return sorted(nodes, key=keyfn)[0]
             return picknext
 
+        def makeclosesorter():
+            """Close order sort."""
+            keyfn = lambda n: ('close' not in self.commitcache[n].extra,
+                               self.commitcache[n].sortkey)
+            def picknext(nodes):
+                return sorted(nodes, key=keyfn)[0]
+            return picknext
+
         def makedatesorter():
             """Sort revisions by date."""
             dates = {}
@@ -246,6 +254,8 @@
             picknext = makedatesorter()
         elif sortmode == 'sourcesort':
             picknext = makesourcesorter()
+        elif sortmode == 'closesort':
+            picknext = makeclosesorter()
         else:
             raise util.Abort(_('unknown sort mode: %s') % sortmode)
 
@@ -446,13 +456,15 @@
             shutil.rmtree(path, True)
         raise
 
-    sortmodes = ('branchsort', 'datesort', 'sourcesort')
+    sortmodes = ('branchsort', 'datesort', 'sourcesort', 'closesort')
     sortmode = [m for m in sortmodes if opts.get(m)]
     if len(sortmode) > 1:
         raise util.Abort(_('more than one sort mode specified'))
     sortmode = sortmode and sortmode[0] or defaultsort
     if sortmode == 'sourcesort' and not srcc.hasnativeorder():
         raise util.Abort(_('--sourcesort is not supported by this data source'))
+    if sortmode == 'closesort' and not srcc.hasnativeclose():
+        raise util.Abort(_('--closesort is not supported by this data source'))
 
     fmap = opts.get('filemap')
     if fmap:
--- a/hgext/convert/hg.py	Sun Mar 24 16:43:25 2013 -0700
+++ b/hgext/convert/hg.py	Sun Mar 24 00:06:52 2013 +0700
@@ -386,6 +386,9 @@
     def hasnativeorder(self):
         return True
 
+    def hasnativeclose(self):
+        return True
+
     def lookuprev(self, rev):
         try:
             return hex(self.repo.lookup(rev))
--- a/tests/test-convert-datesort.t	Sun Mar 24 16:43:25 2013 -0700
+++ b/tests/test-convert-datesort.t	Sun Mar 24 00:06:52 2013 +0700
@@ -38,6 +38,26 @@
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo b >> b
   $ hg ci -m b1 -d '9 0'
+  $ hg up -C 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo c >> c
+  $ hg branch branchc
+  marked working directory as branch branchc
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -Am c0 -d '10 0'
+  adding c
+  $ hg up -C brancha
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg ci --close-branch -m a7x -d '11 0'
+  $ hg up -C branchb
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg ci --close-branch -m b2x -d '12 0'
+  $ hg up -C branchc
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg merge branchb
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m c1 -d '13 0'
   $ cd ..
 
 convert with datesort
@@ -47,27 +67,39 @@
   scanning source...
   sorting...
   converting...
-  8 a0
-  7 a1
-  6 a2
-  5 a3
-  4 a4
-  3 b0
-  2 a5
-  1 a6
-  0 b1
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 a4
+  7 b0
+  6 a5
+  5 a6
+  4 b1
+  3 c0
+  2 a7x
+  1 b2x
+  0 c1
 
 graph converted repo
 
   $ hg -R t-datesort glog --template '{rev} "{desc}"\n'
-  o  8 "b1"
-  |
-  | o  7 "a6"
+  o    12 "c1"
+  |\
+  | o  11 "b2x"
   | |
-  | o  6 "a5"
-  | |
-  o |  5 "b0"
-  | |
+  | | o  10 "a7x"
+  | | |
+  o | |  9 "c0"
+  | | |
+  | o |  8 "b1"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | o |  5 "b0"
+  |/ /
   | o  4 "a4"
   | |
   | o  3 "a3"
@@ -86,29 +118,41 @@
   scanning source...
   sorting...
   converting...
-  8 a0
-  7 a1
-  6 a2
-  5 a3
-  4 b0
-  3 a4
-  2 a5
-  1 a6
-  0 b1
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 b0
+  7 a4
+  6 a5
+  5 a6
+  4 b1
+  3 c0
+  2 a7x
+  1 b2x
+  0 c1
 
 graph converted repo
 
   $ hg -R t-sourcesort glog --template '{rev} "{desc}"\n'
-  o  8 "b1"
-  |
-  | o  7 "a6"
+  o    12 "c1"
+  |\
+  | o  11 "b2x"
   | |
-  | o  6 "a5"
-  | |
-  | o  5 "a4"
-  | |
-  o |  4 "b0"
-  | |
+  | | o  10 "a7x"
+  | | |
+  o | |  9 "c0"
+  | | |
+  | o |  8 "b1"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | | o  5 "a4"
+  | | |
+  | o |  4 "b0"
+  |/ /
   | o  3 "a3"
   | |
   | o  2 "a2"
@@ -117,3 +161,54 @@
   |/
   o  0 "a0"
   
+
+convert with closesort
+
+  $ hg convert --closesort t t-closesort
+  initializing destination t-closesort repository
+  scanning source...
+  sorting...
+  converting...
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 b0
+  7 a4
+  6 a5
+  5 a6
+  4 a7x
+  3 b1
+  2 b2x
+  1 c0
+  0 c1
+
+graph converted repo
+
+  $ hg -R t-closesort glog --template '{rev} "{desc}"\n'
+  o    12 "c1"
+  |\
+  | o  11 "c0"
+  | |
+  o |  10 "b2x"
+  | |
+  o |  9 "b1"
+  | |
+  | | o  8 "a7x"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | | o  5 "a4"
+  | | |
+  o | |  4 "b0"
+  |/ /
+  | o  3 "a3"
+  | |
+  | o  2 "a2"
+  | |
+  | o  1 "a1"
+  |/
+  o  0 "a0"
+  
--- a/tests/test-convert.t	Sun Mar 24 16:43:25 2013 -0700
+++ b/tests/test-convert.t	Sun Mar 24 00:06:52 2013 +0700
@@ -46,6 +46,8 @@
                     larger than the same ones generated by --branchsort.
       --sourcesort  try to preserve source revisions order, only supported by
                     Mercurial sources.
+      --closesort   try to move closed revisions as close as possible to parent
+                    branches, only supported by Mercurial sources.
   
       If "REVMAP" isn't given, it will be put in a default location
       ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
@@ -268,6 +270,7 @@
       --branchsort       try to sort changesets by branches
       --datesort         try to sort changesets by date
       --sourcesort       preserve source changesets order
+      --closesort        try to reorder closed revisions
   
   use "hg -v help convert" to show the global options
   $ hg init a