Commits

Markus Zapke-Gründemann committed 60c764e

Fixed problem with deeper symlinks and added more debugging.

Symlinks with backslashes in a deeper directory were not scanned for
backslashes and therefore not dereferenced.

Comments (0)

Files changed (2)

     return os.readlink(path).replace('\\', '/')
 
 
-def dereference_symlink(path, resolve=True):
+def dereference_symlink(path):
     """Returns a dereferenced symlink.
 
     If the symlink contains backslashes they are replaced with slashes.
     return os.path.join(os.path.dirname(path), linkto)
 
 
-def smartcopy(src, dst, node, ignore=None, exclude_path=None, no_errors=False):
+def smartcopy(ui, src, dst, node, ignore=None, exclude_path=None, no_errors=False):
     """Copies a node (recursively) from src to dst directory.
 
     If node is a file only the file is copied.
     if symlinks and is_symlink:
         if contains_backslashes(srcpath):
             symlinks = False
+            oldsrc = srcpath
             srcpath = dereference_symlink(srcpath)
+            ui.debug(_('dereferenced %s to %s\n') % (oldsrc, srcpath))
     if symlinks and is_symlink:
         linkto = os.readlink(srcpath)
+        ui.debug(_('creating symlink %s -> %s\n') % (dstpath, linkto))
         os.symlink(linkto, dstpath)
     else:
         try:
             if os.path.isdir(srcpath):
-                copytree(srcpath, dstpath, symlinks, ignore, exclude_path)
+                copytree(ui, srcpath, dstpath, symlinks, ignore, exclude_path)
             else:
+                ui.debug(_('copying %s to %s\n') % (srcpath, dstpath))
                 shutil.copy(srcpath, dstpath)
         except shutil.Error, err:
             errors = []
     return common_suffix
 
 
-def copytree(src, dst, symlinks=False, ignore=None, exclude_path=None):
+def copytree(ui, src, dst, symlinks=False, ignore=None, exclude_path=None):
     """Recursively copy an entire directory tree rooted at src. The destination
     directory, named by dst, must not already exist; it will be created as well
     as missing parent directories. Permissions and times of directories are
     else:
         ignored_names = set()
 
+    ui.debug(_('creating directory %s\n') % dst)
     os.makedirs(dst)
     errors = []
     for name in names:
                 continue
         try:
             is_symlink = os.path.islink(srcname)
-            if symlinks and is_symlink:
+            if is_symlink:
                 if contains_backslashes(srcname):
                     symlinks = False
+                    oldsrc = srcname
                     srcname = dereference_symlink(srcname)
+                    ui.debug(_('dereferenced %s to %s\n') % (oldsrc, srcname))
             if symlinks and is_symlink:
                 linkto = os.readlink(srcname)
+                ui.debug(_('creating symlink %s -> %s\n') % (dstname, linkto))
                 os.symlink(linkto, dstname)
             elif os.path.isdir(srcname):
-                copytree(srcname, dstname, symlinks, ignore, exclude_path)
+                copytree(ui, srcname, dstname, symlinks, ignore, exclude_path)
             else:
+                ui.debug(_('copying %s to %s\n') % (srcname, dstname))
                 shutil.copy2(srcname, dstname)
         except (IOError, os.error), why:
             errors.append((srcname, dstname, str(why)))
     # Copy all files into the repository.
     for sourcepath in sources:
         for node in os.listdir(sourcepath):
-            warnings = smartcopy(sourcepath, repo.root, node, ignore,
+            warnings = smartcopy(ui, sourcepath, repo.root, node, ignore,
                 exclude_path, opts.get('ignore_copy_errors'))
             if len(warnings) == 0:
                 continue

test-importfs-symlinks.t

   $ echo c3 > d1/d2/f3
   $ cd d1/d2
   $ ln -s "..\f1" f4
+  $ ln -s "..\d3" d4
   $ cd ../..
   $ cat d1/d2/f4
   cat: d1/d2/f4: No such file or directory
   [1]
+  $ ls d1/d2/d4/
+  ls: d1/d2/d4/: No such file or directory
+  [2]
   $ ln -s "d2\f3" d1/f6
   $ cat d1/f6
   cat: d1/f6: No such file or directory
 
 Now run the import:
 
-  $ hg importfs r3 d1
+  $ hg importfs --debug r3 d1
   created repository $TESTTMP/r3
+  resolving manifests
+   overwrite True partial False
+   ancestor 000000000000+ local 000000000000+ remote 000000000000
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  creating directory $TESTTMP/r3/d3
+  creating symlink $TESTTMP/r3/d3/f5 -> ../f1
+  copying d1/f2 to $TESTTMP/r3/f2
+  copying d1/f1 to $TESTTMP/r3/f1
+  creating directory $TESTTMP/r3/d2
+  dereferenced d1/d2/f4 to d1/d2/../f1
+  copying d1/d2/../f1 to $TESTTMP/r3/d2/f4
+  copying d1/d2/f3 to $TESTTMP/r3/d2/f3
+  dereferenced d1/d2/d4 to d1/d2/../d3
+  creating directory $TESTTMP/r3/d2/d4
+  copying d1/d2/../d3/f5 to $TESTTMP/r3/d2/d4/f5
+  dereferenced d1/f6 to d1/d2/f3
+  copying d1/d2/f3 to $TESTTMP/r3/f6
+  adding d2/d4/f5
   adding d2/f3
   adding d2/f4
   adding d3/f5
   adding f1
   adding f2
   adding f6
+  searching for exact renames: 0/7 (0.00%)
+  searching for exact renames: 1/7 (14.29%)
+  searching for exact renames: 2/7 (28.57%)
+  searching for exact renames: 3/7 (42.86%)
+  searching for exact renames: 4/7 (57.14%)
+  searching for exact renames: 5/7 (71.43%)
+  searching for exact renames: 6/7 (85.71%)
+  d2/d4/f5
+  d2/f3
+  d2/f4
+  d3/f5
+  f1
+  f2
+  f6
+  committed changeset 0:???????????????????????????????????????? (glob)
 
 The backslashes are replaced and the symlinks containing them before are dereferenced:
 
   $ hg manifest -v -R r3
+  644   d2/d4/f5
   644   d2/f3
   644   d2/f4
   644 @ d3/f5