changeset 87:b033d74be76b

fetch_command: in stupid non-diffy mode, take changed paths in account Former code was checkouting all branch files for every converted revision when diffs were not available in stupid mode. Now, only changed items are requested.
author Patrick Mezard <pmezard@gmail.com>
date Fri, 14 Nov 2008 16:18:24 -0600
parents 6ecdbd22eb1d
children 3b60f223893a
files fetch_command.py svnwrap/svn_swig_wrapper.py
diffstat 2 files changed, 42 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/fetch_command.py
+++ b/fetch_command.py
@@ -295,20 +295,42 @@ def stupid_fetch_branchrev(svn, hg_edito
     in the branch at the given revision, and 'filectxfn' is a memctx compatible
     callable to retrieve individual file information.
     """
-    files = []
-    try:
-        for path, kind in svn.list_files(branchpath, r.revnum):
-            if kind == 'f':
-                files.append(path)
-    except IOError:
+    parentctx = hg_editor.repo[parentid]
+    kind = svn.checkpath(branchpath, r.revnum)
+    if kind is None:
         # Branch does not exist at this revision. Get parent revision and
         # remove everything.
-        parentctx = hg_editor.repo[parentid]
         files = parentctx.manifest().keys()
         def filectxfn(repo, memctx, path):
             raise IOError()
         return files, filectxfn
 
+    files = []
+    branchprefix = branchpath + '/'
+    for path, e in r.paths.iteritems():
+        if not path.startswith(branchprefix):
+            continue
+        kind = svn.checkpath(path, r.revnum)
+        path = path[len(branchprefix):]
+        if kind == 'f':
+            files.append(path)
+        elif kind == 'd':
+            if e.action == 'M':
+                # Ignore property changes for now
+                continue
+            dirpath = branchprefix + path
+            for child, k in svn.list_files(dirpath, r.revnum):
+                if k == 'f':
+                    files.append(path + '/' + child)
+        else:
+            if path in parentctx:
+                files.append(path)
+                continue
+            # Assume it's a deleted directory
+            path = path + '/'
+            deleted = [f for f in parentctx if f.startswith(path)]
+            files += deleted        
+
     copies = getcopies(svn, hg_editor, branch, branchpath, r, files, parentid)
     
     linkprefix = 'link '
--- a/svnwrap/svn_swig_wrapper.py
+++ b/svnwrap/svn_swig_wrapper.py
@@ -87,6 +87,11 @@ class Revision(object):
     def __str__(self):
         return 'r%d by %s' % (self.revnum, self.author)
 
+_svntypes = {
+    core.svn_node_dir: 'd',
+    core.svn_node_file: 'f',
+    }
+
 class SubversionRepo(object):
     """Wrapper for a Subversion repository.
 
@@ -452,10 +457,6 @@ class SubversionRepo(object):
         pool = core.Pool()
         rpath = '/'.join([self.svn_url, dirpath]).strip('/')
         rev = optrev(revision)
-        types = {
-            core.svn_node_dir: 'd',
-            core.svn_node_file: 'f',
-            }
         try:
             entries = client.ls(rpath, rev, True, self.client_context, pool)
         except core.SubversionException, e:
@@ -463,9 +464,16 @@ class SubversionRepo(object):
                 raise IOError('%s cannot be found at r%d' % (dirpath, revision))
             raise
         for path, e in entries.iteritems():
-            kind = types.get(e.kind)
+            kind = _svntypes.get(e.kind)
             yield path, kind
 
+    def checkpath(self, path, revision):
+        """Return the entry type at the given revision, 'f', 'd' or None
+        if the entry does not exist.
+        """
+        kind = ra.check_path(self.ra, path.strip('/'), revision)
+        return _svntypes.get(kind)
+
 class SubversionRepoCanNotReplay(Exception):
     """Exception raised when the svn server is too old to have replay.
     """