diff --git a/docs/settings.rst b/docs/settings.rst index ffcddc7a..97662cce 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -72,6 +72,9 @@ Setting name (default value) What doe generating new files. This can be useful in preventing older, unnecessary files from persisting in your output. However, **this is a destructive setting and should be handled with extreme care.** +`OUTPUT_RETENTION` (``()``) A tuple of filenames that should be retained and not deleted from the + output directory. One use case would be the preservation of version + control data. For example: ``(".hg", ".git", ".bzr")`` `JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. `JINJA_FILTERS` (``{}``) A list of custom Jinja2 filters you want to use. The dictionary should map the filtername to the filter function. diff --git a/pelican/__init__.py b/pelican/__init__.py index 1739aae3..53216421 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -49,6 +49,7 @@ class Pelican(object): self.markup = settings['MARKUP'] self.ignore_files = settings['IGNORE_FILES'] self.delete_outputdir = settings['DELETE_OUTPUT_DIRECTORY'] + self.output_retention = settings['OUTPUT_RETENTION'] self.init_path() self.init_plugins() @@ -175,7 +176,7 @@ class Pelican(object): # explicitely asked if (self.delete_outputdir and not os.path.realpath(self.path).startswith(self.output_path)): - clean_output_dir(self.output_path) + clean_output_dir(self.output_path, self.output_retention) writer = self.get_writer() diff --git a/pelican/settings.py b/pelican/settings.py index c6cc6c3c..1c9b48c3 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -54,6 +54,7 @@ DEFAULT_CONFIG = { 'NEWEST_FIRST_ARCHIVES': True, 'REVERSE_CATEGORY_ORDER': False, 'DELETE_OUTPUT_DIRECTORY': False, + 'OUTPUT_RETENTION': (), 'ARTICLE_URL': '{slug}.html', 'ARTICLE_SAVE_AS': '{slug}.html', 'ARTICLE_LANG_URL': '{slug}-{lang}.html', diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index 0713e5ed..ab35d991 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -193,28 +193,31 @@ class TestUtils(LoggedTestCase): shutil.rmtree(empty_path, True) def test_clean_output_dir(self): + retention = () test_directory = os.path.join(os.path.dirname(__file__), 'clean_output') content = os.path.join(os.path.dirname(__file__), 'content') shutil.copytree(content, test_directory) - utils.clean_output_dir(test_directory) + utils.clean_output_dir(test_directory, retention) self.assertTrue(os.path.isdir(test_directory)) self.assertListEqual([], os.listdir(test_directory)) shutil.rmtree(test_directory) def test_clean_output_dir_not_there(self): + retention = () test_directory = os.path.join(os.path.dirname(__file__), 'does_not_exist') - utils.clean_output_dir(test_directory) + utils.clean_output_dir(test_directory, retention) self.assertFalse(os.path.exists(test_directory)) def test_clean_output_dir_is_file(self): + retention = () test_directory = os.path.join(os.path.dirname(__file__), 'this_is_a_file') f = open(test_directory, 'w') f.write('') f.close() - utils.clean_output_dir(test_directory) + utils.clean_output_dir(test_directory, retention) self.assertFalse(os.path.exists(test_directory)) def test_strftime(self): diff --git a/pelican/utils.py b/pelican/utils.py index fea7b953..2c70ae8c 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -298,8 +298,8 @@ def copy(path, source, destination, destination_path=None, overwrite=False): logger.warning('skipped copy %s to %s' % (source_, destination_)) -def clean_output_dir(path): - """Remove all the files from the output directory""" +def clean_output_dir(path, retention): + """Remove all files from output directory except those in retention list""" if not os.path.exists(path): logger.debug("Directory already removed: %s" % path) @@ -312,10 +312,13 @@ def clean_output_dir(path): logger.error("Unable to delete file %s; %s" % (path, str(e))) return - # remove all the existing content from the output folder + # remove existing content from output folder unless in retention list for filename in os.listdir(path): file = os.path.join(path, filename) - if os.path.isdir(file): + if any(filename == retain for retain in retention): + logger.debug("Skipping deletion; %s is on retention list: %s" \ + % (filename, file)) + elif os.path.isdir(file): try: shutil.rmtree(file) logger.debug("Deleted directory %s" % file)