# HG changeset patch # User Ludovic Chabant # Date 1523942574 25200 # Node ID 3bcb2d4463974ce0edafeddc4fec10c23d613e4d # Parent 32f71dbf5cb1abfcfe8ecdab49414ddb39daf8be fix: Correctly invalidate pages that use dirtied sources. diff -r 32f71dbf5cb1 -r 3bcb2d446397 piecrust/pipelines/_pagebaker.py --- a/piecrust/pipelines/_pagebaker.py Wed Feb 28 20:44:23 2018 -0800 +++ b/piecrust/pipelines/_pagebaker.py Mon Apr 16 22:22:54 2018 -0700 @@ -69,12 +69,14 @@ with open(out_path, 'w', encoding='utf8') as fp: fp.write(content) - def bake(self, page, prev_entry, force=False): + def bake(self, page, prev_entry, + force_segments=False, force_layout=False): cur_sub = 1 has_more_subs = True app = self.app out_dir = self.out_dir - force_bake = self.force or force + force_segments = self.force or force_segments + force_layout = self.force or force_layout pretty_urls = page.config.get('pretty_urls', self.pretty_urls) rendered_subs = [] @@ -99,7 +101,8 @@ pass # Figure out if we need to bake this page. - bake_status = _get_bake_status(page, out_path, force_bake, + bake_status = _get_bake_status(page, out_path, + force_segments, force_layout, prev_sub_entry, cur_sub_entry) # If this page didn't bake because it's already up-to-date. @@ -207,20 +210,19 @@ STATUS_INVALIDATE_AND_BAKE = 2 -def _get_bake_status(page, out_path, force, prev_sub_entry, cur_sub_entry): +def _get_bake_status(page, out_path, force_segments, force_layout, + prev_sub_entry, cur_sub_entry): + # Easy tests. + if force_segments: + return STATUS_INVALIDATE_AND_BAKE + if force_layout: + return STATUS_BAKE + # Figure out if we need to invalidate or force anything. status = _compute_force_flags(prev_sub_entry, cur_sub_entry) if status != STATUS_CLEAN: return status - # Easy test. - if force: - cur_sub_entry['flags'] |= \ - SubPageFlags.FLAG_FORCED_BY_GENERAL_FORCE - # We need to invalidate any cache we have on this page because - # it's being forced, so something important has changed somehow. - return STATUS_INVALIDATE_AND_BAKE - # Check for up-to-date outputs. in_path_time = page.content_mtime try: diff -r 32f71dbf5cb1 -r 3bcb2d446397 piecrust/pipelines/page.py --- a/piecrust/pipelines/page.py Wed Feb 28 20:44:23 2018 -0800 +++ b/piecrust/pipelines/page.py Mon Apr 16 22:22:54 2018 -0700 @@ -37,6 +37,7 @@ def createJobs(self, ctx): pass_num = ctx.pass_num if pass_num == 0: + ctx.current_record.user_data['dirty_source_names'] = set() return self._createLoadJobs(ctx) if pass_num == 1: return self._createSecondPassJobs(ctx) @@ -68,8 +69,6 @@ history.build() pass_num = ctx.pass_num - record = ctx.current_record - record.user_data['dirty_source_names'] = set() for prev, cur in history.diffs: # Ignore pages that disappeared since last bake. @@ -151,12 +150,16 @@ if cur.was_any_sub_baked: continue if prev: - if any(map( - lambda usn: usn in dirty_source_names, - prev.getAllUsedSourceNames()[0])): + usn1, usn2 = prev.getAllUsedSourceNames() + force_segments = any(map(lambda u: u in dirty_source_names, + usn1)) + force_layout = any(map(lambda u: u in dirty_source_names, + usn2)) + if force_segments or force_layout: jobs.append(create_job(self, prev.item_spec, pass_num=pass_num, - force_bake=True)) + force_segments=force_segments, + force_layout=force_layout)) else: # This page uses other sources, but no source was dirty # this time around (it was a null build, maybe). We @@ -182,13 +185,17 @@ new_entry.route_params = result['route_params'] new_entry.timestamp = result['timestamp'] ctx.record.addEntry(new_entry) + + # If this page was modified, flag its entire source as "dirty", + # so any pages using that source can be re-baked. + if (new_entry.flags & PagePipelineRecordEntry.FLAG_SOURCE_MODIFIED): + ctx.record.user_data['dirty_source_names'].add( + self.source.name) else: # Update the entry with the new information. existing = ctx.record_entry if not result.get('postponed', False): merge_job_result_into_record_entry(existing, result) - if existing.was_any_sub_baked: - ctx.record.user_data['dirty_source_names'].add(self.source.name) def run(self, job, ctx, result): pass_num = job.get('pass_num', 0) @@ -284,8 +291,10 @@ logger.debug("Full render for: %s" % content_item.spec) page = self.app.getPage(self.source, content_item) prev_entry = ctx.previous_entry - rdr_subs = self._pagebaker.bake(page, prev_entry, - force=job.get('force_bake')) + rdr_subs = self._pagebaker.bake( + page, prev_entry, + force_segments=job.get('force_segments'), + force_layout=job.get('force_layout')) add_page_job_result(result) result['subs'] = rdr_subs