# HG changeset patch # User Constantine Linnick # Date 2013-03-23 17:06:52 # Node ID 05acdf8e1f233a24917ff9d65fd1b3f323287a28 # Parent a0bff3d4f67b6b6c8e81074672533e0ee3f17d05 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. diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py --- a/hgext/convert/__init__.py +++ b/hgext/convert/__init__.py @@ -61,6 +61,10 @@ def convert(ui, src, dest=None, revmapfi --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 (``/.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 @@ cmdtable = { _('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, diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -145,6 +145,11 @@ class converter_source(object): """ 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(). diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py --- a/hgext/convert/convcmd.py +++ b/hgext/convert/convcmd.py @@ -227,6 +227,14 @@ class converter(object): 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 @@ class converter(object): 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 @@ def convert(ui, src, dest=None, revmapfi 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: diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -386,6 +386,9 @@ class mercurial_source(converter_source) def hasnativeorder(self): return True + def hasnativeclose(self): + return True + def lookuprev(self, rev): try: return hex(self.repo.lookup(rev)) diff --git a/tests/test-convert-datesort.t b/tests/test-convert-datesort.t --- a/tests/test-convert-datesort.t +++ b/tests/test-convert-datesort.t @@ -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 @@ convert with datesort 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 @@ convert with datesort (default mode) 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 @@ graph converted repo |/ 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" + diff --git a/tests/test-convert.t b/tests/test-convert.t --- a/tests/test-convert.t +++ b/tests/test-convert.t @@ -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 ("/.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