# HG changeset patch # User Patrick Mezard # Date 1328909653 -3600 # Node ID d75aa756149bfd54b1f7f84b86072b3c1a50d683 # Parent ebaa0aa749e26289e2644c006fba924bd61faf74 convert: use splicemap entries when sorting revisions (issue1748) When sorting revisions before converting them, we have to edit the revision graph using splicemap entries. Otherwise, a spliced revision may be converted before its synthetic parents. Invalid splicemap revisions are now detected before starting the conversion. diff -r ebaa0aa749e2 -r d75aa756149b hgext/convert/common.py --- a/hgext/convert/common.py Fri Feb 10 22:25:49 2012 +0100 +++ b/hgext/convert/common.py Fri Feb 10 22:34:13 2012 +0100 @@ -245,6 +245,10 @@ """ pass + def hascommit(self, rev): + """Return True if the sink contains rev""" + raise NotImplementedError() + class commandline(object): def __init__(self, ui, command): self.ui = ui diff -r ebaa0aa749e2 -r d75aa756149b hgext/convert/convcmd.py --- a/hgext/convert/convcmd.py Fri Feb 10 22:25:49 2012 +0100 +++ b/hgext/convert/convcmd.py Fri Feb 10 22:34:13 2012 +0100 @@ -142,6 +142,29 @@ return parents + def mergesplicemap(self, parents, splicemap): + """A splicemap redefines child/parent relationships. Check the + map contains valid revision identifiers and merge the new + links in the source graph. + """ + for c in splicemap: + if c not in parents: + if not self.dest.hascommit(self.map.get(c, c)): + # Could be in source but not converted during this run + self.ui.warn(_('splice map revision %s is not being ' + 'converted, ignoring\n') % c) + continue + pc = [] + for p in splicemap[c]: + # We do not have to wait for nodes already in dest. + if self.dest.hascommit(self.map.get(p, p)): + continue + # Parent is not in dest and not being converted, not good + if p not in parents: + raise util.Abort(_('unknown splice map parent: %s') % p) + pc.append(p) + parents[c] = pc + def toposort(self, parents, sortmode): '''Return an ordering such that every uncommitted changeset is preceeded by all its uncommitted ancestors.''' @@ -340,6 +363,7 @@ self.ui.status(_("scanning source...\n")) heads = self.source.getheads() parents = self.walktree(heads) + self.mergesplicemap(parents, self.splicemap) self.ui.status(_("sorting...\n")) t = self.toposort(parents, sortmode) num = len(t) diff -r ebaa0aa749e2 -r d75aa756149b hgext/convert/hg.py --- a/hgext/convert/hg.py Fri Feb 10 22:25:49 2012 +0100 +++ b/hgext/convert/hg.py Fri Feb 10 22:34:13 2012 +0100 @@ -223,6 +223,12 @@ self.repo._bookmarks[bookmark] = bin(updatedbookmark[bookmark]) bookmarks.write(self.repo) + def hascommit(self, rev): + if not rev in self.repo and self.clonebranches: + raise util.Abort(_('revision %s not be found in destination ' + 'repository (lookups with clonebranches=true ' + 'are not implemented)') % rev) + return rev in self.repo class mercurial_source(converter_source): def __init__(self, ui, path, rev=None): diff -r ebaa0aa749e2 -r d75aa756149b hgext/convert/subversion.py --- a/hgext/convert/subversion.py Fri Feb 10 22:25:49 2012 +0100 +++ b/hgext/convert/subversion.py Fri Feb 10 22:34:13 2012 +0100 @@ -1187,3 +1187,12 @@ def puttags(self, tags): self.ui.warn(_('writing Subversion tags is not yet implemented\n')) return None, None + + def hascommit(self, rev): + # This is not correct as one can convert to an existing subversion + # repository and childmap would not list all revisions. Too bad. + if rev in self.childmap: + return True + raise util.Abort(_('splice map revision %s not found in subversion ' + 'child map (revision lookups are not implemented') + % rev) diff -r ebaa0aa749e2 -r d75aa756149b tests/test-convert-splicemap.t --- a/tests/test-convert-splicemap.t Fri Feb 10 22:25:49 2012 +0100 +++ b/tests/test-convert-splicemap.t Fri Feb 10 22:34:13 2012 +0100 @@ -4,7 +4,8 @@ $ echo 'graphlog =' >> $HGRCPATH $ glog() > { - > hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@" + > hg glog --template '{rev}:{node|short} "{desc|firstline}"\ + > files: {files}\n' "$@" > } $ hg init repo1 $ cd repo1 @@ -21,6 +22,14 @@ adding c $ PARENTID2=`hg id --debug -i` $ cd .. + $ glog -R repo1 + @ 2:e55c719b85b6 "addc" files: c + | + o 1:6d4c2037ddc2 "addb" files: a b + | + o 0:07f494440405 "adda" files: a + + $ hg init repo2 $ cd repo2 $ echo b > a @@ -36,6 +45,13 @@ $ hg ci -Am adde adding e $ cd .. + $ glog -R repo2 + @ 2:a39b65753b0a "adde" files: e + | + o 1:e4ea00df9189 "changed" files: d + | + o 0:527cdedf31fb "addaandd" files: a d + test invalid splicemap @@ -49,9 +65,12 @@ splice repo2 on repo1 $ cat > splicemap < $CHILDID1 $PARENTID1 + > $CHILDID1 $PARENTID1 > $CHILDID2 $PARENTID2,$CHILDID1 > EOF + $ cat splicemap + 527cdedf31fbd5ea708aa14eeecf53d4676f38db 6d4c2037ddc2cb2627ac3a244ecce35283268f8e + e4ea00df91897da3079a10fab658c1eddba6617b e55c719b85b60e5102fac26110ba626e7cb6b7dc,527cdedf31fbd5ea708aa14eeecf53d4676f38db $ hg clone repo1 target1 updating to branch default 3 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -65,15 +84,137 @@ spliced in ['e55c719b85b60e5102fac26110ba626e7cb6b7dc', '527cdedf31fbd5ea708aa14eeecf53d4676f38db'] as parents of e4ea00df91897da3079a10fab658c1eddba6617b 0 adde $ glog -R target1 - o 5 "adde" files: e + o 5:16bc847b02aa "adde" files: e + | + o 4:e30e4fee3418 "changed" files: d + |\ + | o 3:e673348c3a3c "addaandd" files: a d + | | + @ | 2:e55c719b85b6 "addc" files: c + |/ + o 1:6d4c2037ddc2 "addb" files: a b | - o 4 "changed" files: d + o 0:07f494440405 "adda" files: a + + + + +Test splicemap and conversion order + + $ hg init ordered + $ cd ordered + $ echo a > a + $ hg ci -Am adda + adding a + $ hg branch branch + marked working directory as branch branch + (branches are permanent and global, did you want a bookmark?) + $ echo a >> a + $ hg ci -Am changea + $ echo a >> a + $ hg ci -Am changeaagain + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo b > b + $ hg ci -Am addb + adding b + +We want 2 to depend on 1 and 3. Since 3 is always converted after 2, +the bug should be exhibited with all conversion orders. + + $ cat > ../splicemap < $(hg id -r 2 -i --debug) $(hg id -r 1 -i --debug),$(hg id -r 3 -i --debug) + > EOF + $ cd .. + $ cat splicemap + 7c364e7fa7d70ae525610c016317ed717b519d97 717d54d67e6c31fd75ffef2ff3042bdd98418437,102a90ea7b4a3361e4082ed620918c261189a36a + +Test regular conversion + + $ hg convert --splicemap splicemap ordered ordered-hg1 + initializing destination ordered-hg1 repository + scanning source... + sorting... + converting... + 3 adda + 2 changea + 1 addb + 0 changeaagain + spliced in ['717d54d67e6c31fd75ffef2ff3042bdd98418437', '102a90ea7b4a3361e4082ed620918c261189a36a'] as parents of 7c364e7fa7d70ae525610c016317ed717b519d97 + $ glog -R ordered-hg1 + o 3:4cb04b9afbf2 "changeaagain" files: a |\ - | o 3 "addaandd" files: a d + | o 2:102a90ea7b4a "addb" files: b | | - @ | 2 "addc" files: c + o | 1:717d54d67e6c "changea" files: a |/ - o 1 "addb" files: a b - | - o 0 "adda" files: a + o 0:07f494440405 "adda" files: a + +Test conversion with parent revisions already in dest, using source +and destination identifiers. Test unknown splicemap target. + + $ hg convert -r1 ordered ordered-hg2 + initializing destination ordered-hg2 repository + scanning source... + sorting... + converting... + 1 adda + 0 changea + $ hg convert -r3 ordered ordered-hg2 + scanning source... + sorting... + converting... + 0 addb + $ cat > splicemap < $(hg -R ordered id -r 2 -i --debug) \ + > $(hg -R ordered-hg2 id -r 1 -i --debug),\ + > $(hg -R ordered-hg2 id -r 2 -i --debug) + > deadbeef102a90ea7b4a3361e4082ed620918c26 deadbeef102a90ea7b4a3361e4082ed620918c27 + > EOF + $ hg convert --splicemap splicemap ordered ordered-hg2 + scanning source... + splice map revision deadbeef102a90ea7b4a3361e4082ed620918c26 is not being converted, ignoring + sorting... + converting... + 0 changeaagain + spliced in ['717d54d67e6c31fd75ffef2ff3042bdd98418437', '102a90ea7b4a3361e4082ed620918c261189a36a'] as parents of 7c364e7fa7d70ae525610c016317ed717b519d97 + $ glog -R ordered-hg2 + o 3:4cb04b9afbf2 "changeaagain" files: a + |\ + | o 2:102a90ea7b4a "addb" files: b + | | + o | 1:717d54d67e6c "changea" files: a + |/ + o 0:07f494440405 "adda" files: a + + +Test empty conversion + + $ hg convert --splicemap splicemap ordered ordered-hg2 + scanning source... + splice map revision deadbeef102a90ea7b4a3361e4082ed620918c26 is not being converted, ignoring + sorting... + converting... + +Test clonebranches + + $ hg --config convert.hg.clonebranches=true convert \ + > --splicemap splicemap ordered ordered-hg3 + initializing destination ordered-hg3 repository + scanning source... + abort: revision 717d54d67e6c31fd75ffef2ff3042bdd98418437 not be found in destination repository (lookups with clonebranches=true are not implemented) + [255] + +Test invalid dependency + + $ cat > splicemap < $(hg -R ordered id -r 2 -i --debug) \ + > deadbeef102a90ea7b4a3361e4082ed620918c26,\ + > $(hg -R ordered-hg2 id -r 2 -i --debug) + > EOF + $ hg convert --splicemap splicemap ordered ordered-hg4 + initializing destination ordered-hg4 repository + scanning source... + abort: unknown splice map parent: deadbeef102a90ea7b4a3361e4082ed620918c26 + [255]