diff --git a/pelican/generators.py b/pelican/generators.py index 09541191..5a560b05 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -554,8 +554,12 @@ class StaticGenerator(Generator): final_path=None): """Copy all the paths from source to destination""" for path in paths: - copy(path, source, os.path.join(output_path, destination), - final_path) + if final_path: + copy(os.path.join(source, path), + os.path.join(output_path, destination, final_path)) + else: + copy(os.path.join(source, path), + os.path.join(output_path, destination, path)) def generate_context(self): self.staticfiles = [] @@ -597,7 +601,7 @@ class SourceFileGenerator(Generator): output_path, _ = os.path.splitext(obj.save_as) dest = os.path.join(self.output_path, output_path + self.output_extension) - copy('', obj.source_path, dest) + copy(obj.source_path, dest) def generate_output(self, writer=None): logger.info(' Generating source files...') diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index a8de7216..f6f96a1c 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -323,6 +323,87 @@ class TestUtils(LoggedTestCase): locale.setlocale(locale.LC_TIME, old_locale) +class TestCopy(unittest.TestCase): + '''Tests the copy utility''' + + def setUp(self): + self.root_dir = mkdtemp(prefix='pelicantests.') + + def tearDown(self): + shutil.rmtree(self.root_dir) + + def _create_file(self, *path): + with open(os.path.join(self.root_dir, *path), 'w') as f: + f.write('42\n') + + def _create_dir(self, *path): + os.makedirs(os.path.join(self.root_dir, *path)) + + def _exist_file(self, *path): + path = os.path.join(self.root_dir, *path) + self.assertTrue(os.path.isfile(path), 'File does not exist: %s' % path) + + def _exist_dir(self, *path): + path = os.path.join(self.root_dir, *path) + self.assertTrue(os.path.exists(path), + 'Directory does not exist: %s' % path) + + def test_copy_file_same_path(self): + self._create_file('a.txt') + utils.copy(os.path.join(self.root_dir, 'a.txt'), + os.path.join(self.root_dir, 'b.txt')) + self._exist_file('b.txt') + + def test_copy_file_different_path(self): + self._create_dir('a') + self._create_dir('b') + self._create_file('a', 'a.txt') + utils.copy(os.path.join(self.root_dir, 'a', 'a.txt'), + os.path.join(self.root_dir, 'b', 'b.txt')) + self._exist_dir('b') + self._exist_file('b', 'b.txt') + + def test_copy_file_create_dirs(self): + self._create_file('a.txt') + utils.copy(os.path.join(self.root_dir, 'a.txt'), + os.path.join(self.root_dir, 'b0', 'b1', 'b2', 'b3', 'b.txt')) + self._exist_dir('b0') + self._exist_dir('b0', 'b1') + self._exist_dir('b0', 'b1', 'b2') + self._exist_dir('b0', 'b1', 'b2', 'b3') + self._exist_file('b0', 'b1', 'b2', 'b3', 'b.txt') + + def test_copy_dir_same_path(self): + self._create_dir('a') + self._create_file('a', 'a.txt') + utils.copy(os.path.join(self.root_dir, 'a'), + os.path.join(self.root_dir, 'b')) + self._exist_dir('b') + self._exist_file('b', 'a.txt') + + def test_copy_dir_different_path(self): + self._create_dir('a0') + self._create_dir('a0', 'a1') + self._create_file('a0', 'a1', 'a.txt') + self._create_dir('b0') + utils.copy(os.path.join(self.root_dir, 'a0', 'a1'), + os.path.join(self.root_dir, 'b0', 'b1')) + self._exist_dir('b0', 'b1') + self._exist_file('b0', 'b1', 'a.txt') + + def test_copy_dir_create_dirs(self): + self._create_dir('a') + self._create_file('a', 'a.txt') + utils.copy(os.path.join(self.root_dir, 'a'), + os.path.join(self.root_dir, 'b0', 'b1', 'b2', 'b3', 'b')) + self._exist_dir('b0') + self._exist_dir('b0', 'b1') + self._exist_dir('b0', 'b1', 'b2') + self._exist_dir('b0', 'b1', 'b2', 'b3') + self._exist_dir('b0', 'b1', 'b2', 'b3', 'b') + self._exist_file('b0', 'b1', 'b2', 'b3', 'b', 'a.txt') + + class TestDateFormatter(unittest.TestCase): '''Tests that the output of DateFormatter jinja filter is same as utils.strftime''' diff --git a/pelican/utils.py b/pelican/utils.py index 4b25ec7f..822e50e9 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -256,24 +256,21 @@ def slugify(value, substitutions=()): return value.decode('ascii') -def copy(path, source, destination, destination_path=None): - """Copy path from origin to destination. +def copy(source, destination): + """Recursively copy source into destination. + + If source is a file, destination has to be a file as well. The function is able to copy either files or directories. - :param path: the path to be copied from the source to the destination - :param source: the source dir - :param destination: the destination dir - :param destination_path: the destination path (optional) + :param source: the source file or directory + :param destination: the destination file or directory """ - if not destination_path: - destination_path = path - source_ = os.path.abspath(os.path.expanduser(os.path.join(source, path))) - destination_ = os.path.abspath( - os.path.expanduser(os.path.join(destination, destination_path))) + source_ = os.path.abspath(os.path.expanduser(source)) + destination_ = os.path.abspath(os.path.expanduser(destination)) - if not os.path.exists(destination_): + if not os.path.exists(destination_) and not os.path.isfile(source_): os.makedirs(destination_) def recurse(source, destination):