From c7842dda37b2c99f02818ff4adca7ad598d0d8ea Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 18 Jun 2015 18:56:01 -0400
Subject: [PATCH] Update llmanifest.LLManifest.copy_action() to handle symlinks
 for directories as well as for files.

---
 indra/lib/python/indra/util/llmanifest.py | 56 ++++++++++++-----------
 1 file changed, 29 insertions(+), 27 deletions(-)

diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 1d85aa29780..62bd09471a3 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -512,11 +512,7 @@ def copy_action(self, src, dst):
             # ensure that destination path exists
             self.cmakedirs(os.path.dirname(dst))
             self.created_paths.append(dst)
-            if not os.path.isdir(src):
-                self.ccopy(src,dst)
-            else:
-                # src is a dir
-                self.ccopytree(src,dst)
+            self.ccopymumble(src, dst)
         else:
             print "Doesn't exist:", src
 
@@ -595,28 +591,38 @@ def remove(self, *paths):
                 else:
                     os.remove(path)
 
-    def ccopy(self, src, dst):
-        """ Copy a single file or symlink.  Uses filecmp to skip copying for existing files."""
+    def ccopymumble(self, src, dst):
+        """Copy a single symlink, file or directory."""
         if os.path.islink(src):
             linkto = os.readlink(src)
-            if os.path.islink(dst) or os.path.exists(dst):
+            if os.path.islink(dst) or os.path.isfile(dst):
                 os.remove(dst)  # because symlinking over an existing link fails
+            elif os.path.isdir(dst):
+                shutil.rmtree(dst)
             os.symlink(linkto, dst)
+        elif os.path.isdir(src):
+            self.ccopytree(src, dst)
         else:
-            # Don't recopy file if it's up-to-date.
-            # If we seem to be not not overwriting files that have been
-            # updated, set the last arg to False, but it will take longer.
-            if os.path.exists(dst) and filecmp.cmp(src, dst, True):
-                return
-            # only copy if it's not excluded
-            if self.includes(src, dst):
-                try:
-                    os.unlink(dst)
-                except OSError, err:
-                    if err.errno != errno.ENOENT:
-                        raise
-
-                shutil.copy2(src, dst)
+            self.ccopyfile(src, dst)
+            # XXX What about devices, sockets etc.?
+            # YYY would we put such things into a viewer package?!
+
+    def ccopyfile(self, src, dst):
+        """ Copy a single file.  Uses filecmp to skip copying for existing files."""
+        # Don't recopy file if it's up-to-date.
+        # If we seem to be not not overwriting files that have been
+        # updated, set the last arg to False, but it will take longer.
+        if os.path.exists(dst) and filecmp.cmp(src, dst, True):
+            return
+        # only copy if it's not excluded
+        if self.includes(src, dst):
+            try:
+                os.unlink(dst)
+            except OSError, err:
+                if err.errno != errno.ENOENT:
+                    raise
+
+            shutil.copy2(src, dst)
 
     def ccopytree(self, src, dst):
         """Direct copy of shutil.copytree with the additional
@@ -632,11 +638,7 @@ def ccopytree(self, src, dst):
             srcname = os.path.join(src, name)
             dstname = os.path.join(dst, name)
             try:
-                if os.path.isdir(srcname):
-                    self.ccopytree(srcname, dstname)
-                else:
-                    self.ccopy(srcname, dstname)
-                    # XXX What about devices, sockets etc.?
+                self.ccopymumble(srcname, dstname)
             except (IOError, os.error), why:
                 errors.append((srcname, dstname, why))
         if errors:
-- 
GitLab