Delib. overriding and overwrite detect. Fixes #938

Make deliberate overriding (*) works with overwrites detection.

(*) first introduced by d0e9c52410

The following are decided to be deliberate override:
 - articles using the `save_as` metadata
 - pages using the `save_as` metadata
 - template pages (always)

Pelican now exits in the following 2 cases:
 - at least 2 not deliberate writes to the same file name (behaviour introduced
   by the overwrite detection feature ff7410ce2a)
 - at least 2 deliberate writes to the same file name (new behaviour)

Also added info logging when deliberate overrides are performed.

Switched to StandardError instead of IOError, thanks to @ametaireau and
@russkel.
This commit is contained in:
Rogdham 2013-06-22 14:49:48 +01:00
commit a495527e2b
2 changed files with 33 additions and 12 deletions

View file

@ -168,7 +168,8 @@ class TemplatePagesGenerator(Generator):
try:
template = self.env.get_template(source)
rurls = self.settings['RELATIVE_URLS']
writer.write_file(dest, template, self.context, rurls)
writer.write_file(dest, template, self.context, rurls,
override_output=True)
finally:
del self.env.loader.loaders[0]
@ -262,7 +263,8 @@ class ArticlesGenerator(Generator):
"""Generate the articles."""
for article in chain(self.translations, self.articles):
write(article.save_as, self.get_template(article.template),
self.context, article=article, category=article.category)
self.context, article=article, category=article.category,
override_output=hasattr(article, 'override_save_as'))
def generate_period_archives(self, write):
"""Generate per-year, per-month, and per-day archives."""
@ -533,7 +535,8 @@ class PagesGenerator(Generator):
self.hidden_translations, self.hidden_pages):
writer.write_file(page.save_as, self.get_template(page.template),
self.context, page=page,
relative_urls=self.settings['RELATIVE_URLS'])
relative_urls=self.settings['RELATIVE_URLS'],
override_output=hasattr(page, 'override_save_as'))
class StaticGenerator(Generator):

View file

@ -24,6 +24,7 @@ class Writer(object):
self.reminder = dict()
self.settings = settings or {}
self._written_files = set()
self._overridden_files = set()
def _create_new_feed(self, feed_type, context):
feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed
@ -49,13 +50,26 @@ class Writer(object):
pubdate=set_date_tzinfo(item.date,
self.settings.get('TIMEZONE', None)))
def _open_w(self, filename, encoding):
def _open_w(self, filename, encoding, override=False):
"""Open a file to write some content to it.
Exit if we have already written to that file.
Exit if we have already written to that file, unless one (and no more
than one) of the writes has the override parameter set to True.
"""
if filename in self._written_files:
raise IOError('File %s is to be overwritten' % filename)
if filename in self._overridden_files:
if override:
raise StandardError('File %s is set to be overridden twice'
% filename)
else:
logger.info('skipping %s' % filename)
filename = os.devnull
elif filename in self._written_files:
if override:
logger.info('overwriting %s' % filename)
else:
raise StandardError('File %s is to be overwritten' % filename)
if override:
self._overridden_files.add(filename)
self._written_files.add(filename)
return open(filename, 'w', encoding=encoding)
@ -103,7 +117,7 @@ class Writer(object):
locale.setlocale(locale.LC_ALL, old_locale)
def write_file(self, name, template, context, relative_urls=False,
paginated=None, **kwargs):
paginated=None, override_output=False, **kwargs):
"""Render the template and write the file.
:param name: name of the file to output
@ -112,6 +126,9 @@ class Writer(object):
:param relative_urls: use relative urls or absolutes ones
:param paginated: dict of article list to paginate - must have the
same length (same list in different orders)
:param override_output: boolean telling if we can override previous
output with the same name (and if next files written with the same
name should be skipped to keep that one)
:param **kwargs: additional variables to pass to the templates
"""
@ -121,7 +138,7 @@ class Writer(object):
# other stuff, just return for now
return
def _write_file(template, localcontext, output_path, name):
def _write_file(template, localcontext, output_path, name, override):
"""Render the template write the file."""
old_locale = locale.setlocale(locale.LC_ALL)
locale.setlocale(locale.LC_ALL, str('C'))
@ -134,7 +151,7 @@ class Writer(object):
os.makedirs(os.path.dirname(path))
except Exception:
pass
with self._open_w(path, 'utf-8') as f:
with self._open_w(path, 'utf-8', override=override) as f:
f.write(output)
logger.info('writing {}'.format(path))
@ -180,7 +197,8 @@ class Writer(object):
'%s_next_page' % key: next_page})
_write_file(template, paginated_localcontext, self.output_path,
page.save_as)
page.save_as, override_output)
else:
# no pagination
_write_file(template, localcontext, self.output_path, name)
_write_file(template, localcontext, self.output_path, name,
override_output)