changeset 39:b3c7b844b782

Some more fixes of cases discovered in the melange repo. If anyone knows how I can reproduce a "replaced" state in Subversion, I'd love to be able to make a real test case for this code.
author Augie Fackler <durin42@gmail.com>
date Sun, 26 Oct 2008 22:06:13 -0500
parents 9ee7ce0505eb
children 9952f03ddfbe
files fetch_command.py hg_delta_editor.py push_cmd.py util.py
diffstat 4 files changed, 30 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/fetch_command.py
+++ b/fetch_command.py
@@ -394,7 +394,16 @@ def stupid_svn_server_pull_rev(ui, svn, 
                 used_diff = False
                 shutil.rmtree(our_tempdir)
                 os.makedirs(our_tempdir)
-                svn.fetch_all_files_to_dir(diff_path, r.revnum, our_tempdir)
+                try:
+                    svn.fetch_all_files_to_dir(diff_path, r.revnum, our_tempdir)
+                except core.SubversionException, e:
+                    # apr_err 21 means that we couldn't rename a file to be a dir.
+                    # This happens only in the case (at least right now) of a file
+                    # located in brances or tags, which we don't support anyway.
+                    if e.apr_err == 21:
+                        continue
+                    else:
+                        raise
             except core.SubversionException, e:
                 if e.apr_err == 170000 or (e.message.startswith("URL '")
                      and e.message.endswith("' doesn't exist")):
--- a/hg_delta_editor.py
+++ b/hg_delta_editor.py
@@ -468,9 +468,13 @@ class HgChangeReceiver(delta.Editor):
                 if br_path != '':
                     br_path2 = br_path + '/'
                 # assuming it is a directory
-                for f in ctx:
-                    if f.startswith(br_path2):
-                        f_p = '%s/%s' % (path, f[len(br_path2):])
+                def delete_x(x):
+                    self.deleted_files[x] = True
+                map(delete_x, [pat for pat in self.current_files.iterkeys()
+                               if pat.startswith(path)])
+                for f in ctx.walk(our_util.PrefixMatch(br_path2)):
+                    f_p = '%s/%s' % (path, f[len(br_path2):])
+                    if f_p not in self.current_files:
                         self.deleted_files[f_p] = True
                         self.current_files[f_p] = ''
                         self.ui.status('D %s\n' % f_p)
@@ -550,6 +554,8 @@ class HgChangeReceiver(delta.Editor):
                 self.current_files[fp_c] = fctx.data()
                 self.current_files_exec[fp_c] = 'x' in fctx.flags()
                 self.current_files_symlink[fp_c] = 'l' in fctx.flags()
+                if fp_c in self.deleted_files:
+                    del self.deleted_files[fp_c]
                 # TODO(augie) tag copies from files
 
     @stash_exception_on_self
--- a/push_cmd.py
+++ b/push_cmd.py
@@ -65,15 +65,6 @@ def push_revisions_to_subversion(ui, rep
                                                               svn_commit_hashes)
     return 0
 
-class PrefixMatch(object):
-    def __init__(self, prefix):
-        self.p = prefix
-    
-    def files(self):
-        return []
-    
-    def __call__(self, fn):
-        return fn.startswith(self.p)
 
 def commit_from_rev(ui, repo, rev_ctx, hg_editor, svn_url, base_revision):
     """Build and send a commit from Mercurial to Subversion.
@@ -106,7 +97,7 @@ def commit_from_rev(ui, repo, rev_ctx, h
                 action = 'add'
                 dirname = '/'.join(file.split('/')[:-1] + [''])
                 # check for new directories
-                if not list(parent.walk(PrefixMatch(dirname))):
+                if not list(parent.walk(util.PrefixMatch(dirname))):
                     # check and see if the dir exists svn-side.
                     try:
                         assert svn.list_dir('%s/%s' % (branch_path, dirname))
--- a/util.py
+++ b/util.py
@@ -55,3 +55,13 @@ def parse_revmap(revmap_filename):
             raise NotImplementedError
     return revmap
 
+
+class PrefixMatch(object):
+    def __init__(self, prefix):
+        self.p = prefix
+    
+    def files(self):
+        return []
+    
+    def __call__(self, fn):
+        return fn.startswith(self.p)