Ver Fonte

Deconflict file names in build directory

Closes gh-156
Closes gh-157
Thomas Kluyver há 6 anos atrás
pai
commit
7872ad293a

+ 20 - 11
nsist/__init__.py

@@ -374,9 +374,23 @@ if __name__ == '__main__':
         """Copy a list of files into the build directory, and add them to
         install_files or install_dirs as appropriate.
         """
+        # Create installer.nsi, so that a data file with the same name will
+        # automatically be renamed installer.1.nsi. All the other files needed
+        # in the build directory should already be in place.
+        Path(self.nsi_file).touch()
+
         for file, destination in self.extra_files:
             file = file.rstrip('/\\')
-            basename = os.path.basename(file)
+            in_build_dir = Path(self.build_dir, os.path.basename(file))
+
+            # Find an unused name in the build directory,
+            # similar to the source filename, e.g. foo.1.txt, foo.2.txt, ...
+            stem, suffix = in_build_dir.stem, in_build_dir.suffix
+            n = 1
+            while in_build_dir.exists():
+                name = '{}.{}{}'.format(stem, n, suffix)
+                in_build_dir = in_build_dir.with_name(name)
+                n += 1
 
             if destination:
                 # Normalize destination paths to Windows-style
@@ -385,22 +399,17 @@ if __name__ == '__main__':
                 destination = '$INSTDIR'
 
             if os.path.isdir(file):
-                target_name = pjoin(self.build_dir, basename)
-                if os.path.isdir(target_name):
-                    shutil.rmtree(target_name)
-                elif os.path.exists(target_name):
-                    os.unlink(target_name)
                 if self.exclude:
-                    shutil.copytree(file, target_name,
+                    shutil.copytree(file, str(in_build_dir),
                                     ignore=self.copytree_ignore_callback)
                 else:
                     # Don't use our exclude callback if we don't need to,
                     # as it slows things down.
-                    shutil.copytree(file, target_name)
-                self.install_dirs.append((basename, destination))
+                    shutil.copytree(file, str(in_build_dir))
+                self.install_dirs.append((in_build_dir.name, destination))
             else:
-                shutil.copy2(file, self.build_dir)
-                self.install_files.append((basename, destination))
+                shutil.copy2(file, str(in_build_dir))
+                self.install_files.append((in_build_dir.name, destination))
 
     def write_nsi(self):
         """Write the NSI file to define the NSIS installer.

+ 1 - 0
nsist/tests/data_files/dir1/installer.nsi

@@ -0,0 +1 @@
+;For testing name conflicts - the name installer.nsi is used by Pynsist

+ 14 - 3
nsist/tests/test_installerbuilder.py

@@ -41,7 +41,7 @@ class TestInstallerBuilder(unittest.TestCase):
         
         assert preamble_contents in contents
 
-    def test_copy_files(self):
+    def test_copy_extra_files(self):
         files = [
             (pjoin(test_dir, 'data_files', 'dir1', 'eg-data.txt'), '$INSTDIR'),
             (pjoin(test_dir, 'data_files', 'dir2', 'eg-data.txt'), '$INSTDIR\\foo'),
@@ -53,8 +53,8 @@ class TestInstallerBuilder(unittest.TestCase):
         ib.copy_extra_files()
 
         build_dir_files = set(os.listdir(self.target))
-        self.assertEqual(build_dir_files,
-                         {'eg-data.txt', 'eg-data.1.txt', 'subdir', 'subdir.1'})
+        for file in ['eg-data.txt', 'eg-data.1.txt', 'subdir', 'subdir.1']:
+            self.assertIn(file, build_dir_files)
 
         self.assertEqual(ib.install_dirs, [
             ('subdir', '$INSTDIR'),
@@ -64,3 +64,14 @@ class TestInstallerBuilder(unittest.TestCase):
             ('eg-data.txt', '$INSTDIR'),
             ('eg-data.1.txt', '$INSTDIR\\foo'),
         ])
+
+    def test_copy_installer_nsi(self):
+        files = [
+            (pjoin(test_dir, 'data_files', 'dir1', 'installer.nsi'), None),
+        ]
+        ib = InstallerBuilder("Test App", "1.0", {}, extra_files=files,
+                              build_dir=self.target)
+        ib.copy_extra_files()
+
+        assert_is_file(pjoin(self.target, 'installer.1.nsi'))
+        self.assertEqual(ib.install_files, [('installer.1.nsi', '$INSTDIR')])