# HG changeset patch # User Patrick Mezard # Date 2008-01-26 18:55:04 # Node ID e495f3f35b2d8f0aa825519a323061711542be50 # Parent 5df7cb799baf19be9d695c3fc31ee0641dc49bb8 convert: hg.clonebranches must pull missing parents (issue941) diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -167,12 +167,11 @@ class converter_sink(object): tags: {tagname: sink_rev_id, ...}""" raise NotImplementedError() - def setbranch(self, branch, pbranch, parents): + def setbranch(self, branch, pbranches): """Set the current branch name. Called before the first putfile on the branch. branch: branch name for subsequent commits - pbranch: branch name of parent commit - parents: destination revisions of parent""" + pbranches: (converted parent revision, parent branch) tuples""" pass def setfilemapmode(self, active): diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py --- a/hgext/convert/convcmd.py +++ b/hgext/convert/convcmd.py @@ -222,15 +222,14 @@ class converter(object): self.mapentry(rev, dest) return files, copies = changes - parents = [self.map[r] for r in commit.parents] + pbranches = [] if commit.parents: - prev = commit.parents[0] - if prev not in self.commitcache: - self.cachecommit(prev) - pbranch = self.commitcache[prev].branch - else: - pbranch = None - self.dest.setbranch(commit.branch, pbranch, parents) + for prev in commit.parents: + if prev not in self.commitcache: + self.cachecommit(prev) + pbranches.append((self.map[prev], + self.commitcache[prev].branch)) + self.dest.setbranch(commit.branch, pbranches) for f, v in files: filenames.append(f) try: @@ -246,6 +245,7 @@ class converter(object): # Merely marks that a copy happened. self.dest.copyfile(copyf, f) + parents = [b[0] for b in pbranches] newnode = self.dest.putcommit(filenames, parents, commit) self.mapentry(rev, newnode) diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -80,30 +80,43 @@ class mercurial_sink(converter_sink): except OSError: pass - def setbranch(self, branch, pbranch, parents): - if (not self.clonebranches) or (branch == self.lastbranch): + def setbranch(self, branch, pbranches): + if not self.clonebranches: return + setbranch = (branch != self.lastbranch) self.lastbranch = branch - self.after() if not branch: branch = 'default' - if not pbranch: - pbranch = 'default' + pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches] + pbranch = pbranches and pbranches[0][1] or 'default' branchpath = os.path.join(self.path, branch) - try: - self.repo = hg.repository(self.ui, branchpath) - except: - if not parents: + if setbranch: + self.after() + try: + self.repo = hg.repository(self.ui, branchpath) + except: self.repo = hg.repository(self.ui, branchpath, create=True) - else: - self.ui.note(_('cloning branch %s to %s\n') % (pbranch, branch)) - hg.clone(self.ui, os.path.join(self.path, pbranch), - branchpath, rev=parents, update=False, - stream=True) - self.repo = hg.repository(self.ui, branchpath) - self.before() + self.before() + + # pbranches may bring revisions from other branches (merge parents) + # Make sure we have them, or pull them. + missings = {} + for b in pbranches: + try: + self.repo.lookup(b[0]) + except: + missings.setdefault(b[1], []).append(b[0]) + + if missings: + self.after() + for pbranch, heads in missings.iteritems(): + pbranchpath = os.path.join(self.path, pbranch) + prepo = hg.repository(self.ui, pbranchpath) + self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch)) + self.repo.pull(prepo, [prepo.lookup(h) for h in heads]) + self.before() def putcommit(self, files, parents, commit): seen = {} diff --git a/tests/test-convert-clonebranches b/tests/test-convert-clonebranches new file mode 100755 --- /dev/null +++ b/tests/test-convert-clonebranches @@ -0,0 +1,54 @@ +#!/bin/sh + +echo "[extensions]" >> $HGRCPATH +echo "hgext.convert = " >> $HGRCPATH +echo "[convert]" >> $HGRCPATH +echo "hg.tagsbranch=0" >> $HGRCPATH + +hg init source +cd source +echo a > a +hg ci -qAm adda +# Add a merge with one parent in the same branch +echo a >> a +hg ci -qAm changea +hg up -qC 0 +hg branch branch0 +echo b > b +hg ci -qAm addb +hg up -qC +hg merge +hg ci -qm mergeab +hg tag -ql mergeab +cd .. + +# Miss perl... sometimes +cat > filter.py < file1 +hg ci -qAm c1 +hg up -qC mergeab +hg branch branch2 +echo a > file2 +hg ci -qAm c2 +hg merge branch1 +hg branch branch3 +hg ci -qAm c3 +cd .. + +echo % incremental conversion +hg convert -v --config convert.hg.clonebranches=1 source dest | + python filter.py + diff --git a/tests/test-convert-clonebranches.out b/tests/test-convert-clonebranches.out new file mode 100644 --- /dev/null +++ b/tests/test-convert-clonebranches.out @@ -0,0 +1,29 @@ +marked working directory as branch branch0 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +% convert +3 adda +2 addb +pulling from default into branch0 +1 changesets found +1 changea +0 mergeab +pulling from default into branch0 +1 changesets found +marked working directory as branch branch1 +marked working directory as branch branch2 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +marked working directory as branch branch3 +% incremental conversion +2 c1 +pulling from branch0 into branch1 +2 changesets found +1 c2 +pulling from branch0 into branch2 +2 changesets found +0 c3 +pulling from branch2 into branch3 +3 changesets found +pulling from branch1 into branch3 +1 changesets found