convert: prevent svn branches to leave the root module tree
authorPatrick Mezard <pmezard@gmail.com>
Sat, 26 Jan 2008 14:45:04 +0100
changeset 5957 971a17af5982
parent 5956 094638b3cbed
child 5958 59dce24933ad
convert: prevent svn branches to leave the root module tree
hgext/convert/subversion.py
tests/test-convert-svn-move
tests/test-convert-svn-move.out
--- a/hgext/convert/subversion.py	Sat Jan 26 14:45:04 2008 +0100
+++ b/hgext/convert/subversion.py	Sat Jan 26 14:45:04 2008 +0100
@@ -182,6 +182,7 @@
             self.ctx = self.transport.client
             self.base = svn.ra.get_repos_root(self.ra)
             self.module = self.url[len(self.base):]
+            self.rootmodule = self.module
             self.commits = {}
             self.paths = {}
             self.uuid = svn.ra.get_uuid(self.ra).decode(self.encoding)
@@ -201,6 +202,9 @@
             pass
 
         self.head = self.latest(self.module, latest)
+        if not self.head:
+            raise util.Abort(_('no revision found in module %s') %
+                             self.module.encode(self.encoding))
         self.last_changed = self.revnum(self.head)
         
         self._changescache = None
@@ -253,6 +257,9 @@
             oldmodule = self.module or ''
             self.module += '/' + trunk
             self.head = self.latest(self.module, self.last_changed)
+            if not self.head:
+                raise util.Abort(_('no revision found in module %s') %
+                                 self.module.encode(self.encoding))
 
         # First head in the list is the module's head
         self.heads = [self.head]
@@ -266,6 +273,10 @@
             for branch in branchnames.keys():
                 module = '%s/%s/%s' % (oldmodule, branches, branch)
                 brevid = self.latest(module, self.last_changed)
+                if not brevid:
+                    self.ui.note(_('ignoring empty branch %s\n') %
+                                   branch.encode(self.encoding))
+                    continue
                 self.ui.note('found branch %s at %d\n' % 
                              (branch, self.revnum(brevid)))
                 self.heads.append(brevid)
@@ -380,7 +391,8 @@
     def latest(self, path, stop=0):
         """Find the latest revid affecting path, up to stop. It may return
         a revision in a different module, since a branch may be moved without
-        a change being reported.
+        a change being reported. Return None if computed module does not
+        belong to rootmodule subtree.
         """
         if not stop:
             stop = svn.ra.get_latest_revnum(self.ra)
@@ -414,6 +426,9 @@
         finally:
             stream.close()
 
+        if not path.startswith(self.rootmodule):
+            self.ui.debug(_('ignoring foreign branch %r\n') % path)
+            return None
         return self.revid(dirent.created_rev, path)
 
     def get_blacklist(self):
@@ -645,23 +660,26 @@
             self.ui.debug("parsing revision %d (%d changes)\n" %
                           (revnum, len(orig_paths)))
 
+            branched = False
             rev = self.revid(revnum)
             # branch log might return entries for a parent we already have
 
             if (rev in self.commits or revnum < to_revnum):
-                return None, False
+                return None, branched
 
             parents = []
             # check whether this revision is the start of a branch
             if self.module in orig_paths:
                 ent = orig_paths[self.module]
                 if ent.copyfrom_path:
+                    branched = True
                     # ent.copyfrom_rev may not be the actual last revision
                     previd = self.latest(ent.copyfrom_path, ent.copyfrom_rev)
-                    parents = [previd]
-                    prevmodule, prevnum = self.revsplit(previd)[1:]
-                    self.ui.note('found parent of branch %s at %d: %s\n' %
-                                 (self.module, prevnum, prevmodule))
+                    if previd is not None:
+                        parents = [previd]
+                        prevmodule, prevnum = self.revsplit(previd)[1:]
+                        self.ui.note('found parent of branch %s at %d: %s\n' %
+                                     (self.module, prevnum, prevmodule))
                 else:
                     self.ui.debug("No copyfrom path, don't know what to do.\n")
 
@@ -703,13 +721,14 @@
             if self.child_cset and not self.child_cset.parents:
                 self.child_cset.parents[:] = [rev]
             self.child_cset = cset
-            return cset, len(parents) > 0
+            return cset, branched
 
         self.ui.note('fetching revision log for "%s" from %d to %d\n' %
                      (self.module, from_revnum, to_revnum))
 
         try:
             firstcset = None
+            branched = False
             stream = get_log(self.url, [self.module], from_revnum, to_revnum)
             try:
                 for entry in stream:
@@ -730,7 +749,7 @@
             finally:
                 stream.close()
 
-            if firstcset and not firstcset.parents:
+            if not branched and firstcset and not firstcset.parents:
                 # The first revision of the sequence (the last fetched one)
                 # has invalid parents if not a branch root. Find the parent
                 # revision now, if any.
@@ -738,7 +757,8 @@
                     firstrevnum = self.revnum(firstcset.rev)
                     if firstrevnum > 1:
                         latest = self.latest(self.module, firstrevnum - 1)
-                        firstcset.parents.append(latest)
+                        if latest:
+                            firstcset.parents.append(latest)
                 except util.Abort:
                     pass
         except SubversionException, (inst, num):
--- a/tests/test-convert-svn-move	Sat Jan 26 14:45:04 2008 +0100
+++ b/tests/test-convert-svn-move	Sat Jan 26 14:45:04 2008 +0100
@@ -25,8 +25,10 @@
 mkdir projA
 cd projA
 mkdir trunk
+echo a > trunk/a
 mkdir trunk/d1
 echo b > trunk/d1/b
+echo c > trunk/d1/c
 cd ..
 
 svnurl=file://$svnpath/svn-repo/projA
@@ -36,6 +38,9 @@
 echo % update svn repository
 svn co $svnurl A | fix_path
 cd A
+echo a >> trunk/a
+echo c >> trunk/d1/c
+svn ci -m commitbeforemove
 svn mv $svnurl/trunk $svnurl/subproject -m movedtrunk
 svn up
 mkdir subproject/trunk
--- a/tests/test-convert-svn-move.out	Sat Jan 26 14:45:04 2008 +0100
+++ b/tests/test-convert-svn-move.out	Sat Jan 26 14:45:04 2008 +0100
@@ -1,46 +1,56 @@
 % initial svn import
 Adding         projA/trunk
+Adding         projA/trunk/a
 Adding         projA/trunk/d1
 Adding         projA/trunk/d1/b
+Adding         projA/trunk/d1/c
 
 Committed revision 1.
 % update svn repository
 A    A/trunk
+A    A/trunk/a
 A    A/trunk/d1
 A    A/trunk/d1/b
+A    A/trunk/d1/c
 Checked out revision 1.
+Sending        trunk/a
+Sending        trunk/d1/c
+Transmitting file data ..
+Committed revision 2.
 
-Committed revision 2.
+Committed revision 3.
 D    trunk
 A    subproject
+A    subproject/a
 A    subproject/d1
 A    subproject/d1/b
-Updated to revision 2.
+A    subproject/d1/c
+Updated to revision 3.
 A         subproject/trunk
 Adding         subproject/trunk
 
-Committed revision 3.
+Committed revision 4.
 A         subproject/branches
 Adding         subproject/branches
 
-Committed revision 4.
+Committed revision 5.
 
-Committed revision 5.
+Committed revision 6.
 A    subproject/trunk/d1
 A    subproject/trunk/d1/b
+A    subproject/trunk/d1/c
 D    subproject/d1
-Updated to revision 5.
+Updated to revision 6.
 Sending        subproject/trunk/d1/b
 Transmitting file data .
-Committed revision 6.
+Committed revision 7.
 
-Committed revision 7.
+Committed revision 8.
 % convert trunk and branches
 initializing destination A-hg repository
 scanning source...
 sorting...
 converting...
-7 init projA
 6 createtrunk
 5 moved1
 4 moved1
@@ -48,21 +58,19 @@
 2 changeb
 1 moved1again
 0 moved1again
-o  7 moved1again files: d1/b
+o  6 moved1again files: d1/b d1/c
 |
-| o  6 moved1again files:
+| o  5 moved1again files:
 | |
-o |  5 changeb files: d1/b
+o |  4 changeb files: d1/b
 | |
-| o  4 changeb files: b
+| o  3 changeb files: b
 | |
-o |  3 moved1 files: d1/b
-| |
-| o  2 moved1 files:
+o |  2 moved1 files: d1/b d1/c
 | |
-o |  1 createtrunk files:
- /
-o  0 init projA files: b
+| o  1 moved1 files: b c
+|
+o  0 createtrunk files:
 
-default                        7:
-d1                             6:
+default                        6:
+d1                             5: