changeset 1020:298b07a899b5

bake: Fix overriding issues between theme and user pages for index pages.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 05 Dec 2017 22:26:25 -0800
parents bd544b65cfad
children 22e767899e52
files piecrust/pipelines/_pagebaker.py piecrust/pipelines/_pagerecords.py piecrust/pipelines/page.py tests/test_baking_baker.py
diffstat 4 files changed, 74 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/pipelines/_pagebaker.py	Wed Nov 29 21:36:11 2017 -0800
+++ b/piecrust/pipelines/_pagebaker.py	Tue Dec 05 22:26:25 2017 -0800
@@ -107,7 +107,8 @@
             if bake_status == STATUS_CLEAN:
                 cur_sub_entry['render_info'] = copy.deepcopy(
                     prev_sub_entry['render_info'])
-                cur_sub_entry['flags'] = SubPageFlags.FLAG_NONE
+                cur_sub_entry['flags'] = \
+                    SubPageFlags.FLAG_COLLAPSED_FROM_LAST_RUN
 
                 if prev_entry.num_subs >= cur_sub + 1:
                     cur_sub += 1
--- a/piecrust/pipelines/_pagerecords.py	Wed Nov 29 21:36:11 2017 -0800
+++ b/piecrust/pipelines/_pagerecords.py	Tue Dec 05 22:26:25 2017 -0800
@@ -10,6 +10,7 @@
     FLAG_FORCED_BY_PREVIOUS_ERRORS = 2**3
     FLAG_FORCED_BY_GENERAL_FORCE = 2**4
     FLAG_RENDER_CACHE_INVALIDATED = 2**5
+    FLAG_COLLAPSED_FROM_LAST_RUN = 2**6
 
 
 def create_subpage_job_result(out_uri, out_path):
@@ -146,7 +147,8 @@
     SubPageFlags.FLAG_FORCED_BY_NO_PREVIOUS: 'forced b/c new',
     SubPageFlags.FLAG_FORCED_BY_PREVIOUS_ERRORS: 'forced by errors',
     SubPageFlags.FLAG_FORCED_BY_GENERAL_FORCE: 'manually forced',
-    SubPageFlags.FLAG_RENDER_CACHE_INVALIDATED: 'cache invalidated'
+    SubPageFlags.FLAG_RENDER_CACHE_INVALIDATED: 'cache invalidated',
+    SubPageFlags.FLAG_COLLAPSED_FROM_LAST_RUN: 'from last run'
 }
 
 
--- a/piecrust/pipelines/page.py	Wed Nov 29 21:36:11 2017 -0800
+++ b/piecrust/pipelines/page.py	Tue Dec 05 22:26:25 2017 -0800
@@ -35,11 +35,14 @@
         self._pagebaker.startWriterQueue()
 
     def createJobs(self, ctx):
-        if ctx.pass_num == 0:
+        pass_num = ctx.pass_num
+        if pass_num == 0:
             return self._createLoadJobs(ctx)
-        if ctx.pass_num == 1:
+        if pass_num == 1:
             return self._createSecondPassJobs(ctx)
-        return self._createThirdPassJobs(ctx)
+        if pass_num == 2:
+            return self._createThirdPassJobs(ctx)
+        raise Exception("Unexpected pipeline pass: %d" % pass_num)
 
     def _createLoadJobs(self, ctx):
         # Here we load all the pages in the source, making sure they all
@@ -77,11 +80,15 @@
             if cur.flags & PagePipelineRecordEntry.FLAG_IS_DRAFT:
                 continue
 
-            # Skip pages that are known to use other sources... we'll
-            # schedule them in the second pass.
+            # For pages that are known to use other sources, we make a dummy
+            # job that will effectively get directly passed on to the next
+            # step.
             if prev:
                 usn1, usn2 = prev.getAllUsedSourceNames()
                 if usn1 or usn2:
+                    jobs.append(create_job(self, cur.item_spec,
+                                           pass_num=pass_num,
+                                           uses_sources=True))
                     continue
 
             # Check if this item has been overriden by a previous pipeline
@@ -167,6 +174,8 @@
         step_num = ctx.step_num
 
         if pass_num == 0:
+            # Just went through a "load page" job. Let's create a record
+            # entry with the information we got from the worker.
             new_entry = self.createRecordEntry(result['item_spec'])
             new_entry.flags = result['flags']
             new_entry.config = result['config']
@@ -174,6 +183,7 @@
             new_entry.timestamp = result['timestamp']
             ctx.record.addEntry(new_entry)
         else:
+            # Update the entry with the new information.
             existing = ctx.record_entry
             merge_job_result_into_record_entry(existing, result)
 
@@ -234,6 +244,11 @@
             result['flags'] |= PagePipelineRecordEntry.FLAG_IS_DRAFT
 
     def _renderOrPostpone(self, job, ctx, result):
+        # See if we should immediately kick this job off to the next step.
+        if job.get('uses_sources', False):
+            result['next_step_job'] = create_job(self, job['job_spec'][1])
+            return
+
         # Here our job is to render the page's segments so that they're
         # cached in memory and on disk... unless we detect that the page
         # is using some other sources, in which case we abort and we'll try
--- a/tests/test_baking_baker.py	Wed Nov 29 21:36:11 2017 -0800
+++ b/tests/test_baking_baker.py	Tue Dec 05 22:26:25 2017 -0800
@@ -46,21 +46,68 @@
         assert structure['2017']['01']['01']['first.html'] == 'something 1'
         assert structure['2017']['01']['02']['second.html'] == 'something 2'
 
+        print("\n\n\n")
+        fs.runChef('bake')
+        structure = fs.getStructure('kitchen/_counter')
+        assert structure['index.html'] == 'Second\nFirst\n'
+        assert structure['2017']['01']['01']['first.html'] == 'something 1'
+        assert structure['2017']['01']['02']['second.html'] == 'something 2'
+
+        print("\n\n\n")
+        fs.runChef('bake')
+        structure = fs.getStructure('kitchen/_counter')
+        assert structure['index.html'] == 'Second\nFirst\n'
+        assert structure['2017']['01']['01']['first.html'] == 'something 1'
+        assert structure['2017']['01']['02']['second.html'] == 'something 2'
+
+        print("\n\n\n")
         fs.runChef('bake')
         structure = fs.getStructure('kitchen/_counter')
         assert structure['index.html'] == 'Second\nFirst\n'
         assert structure['2017']['01']['01']['first.html'] == 'something 1'
         assert structure['2017']['01']['02']['second.html'] == 'something 2'
 
+
+def test_bake_four_times_again():
+    fs = (mock_fs()
+          .withConfig({'site': {
+              'default_format': 'none',
+              'default_page_layout': 'none',
+              'default_post_layout': 'none',
+          }})
+          .withPage('pages/_index.html', {'layout': 'none', 'format': 'none'},
+                    "{% for p in pagination.posts -%}\n"
+                    "{{p.title}} : {{p.content}}\n"
+                    "{% endfor %}")
+          .withPage('posts/2017-01-01_first.html', {'title': "First"},
+                    "something 1")
+          .withPage('posts/2017-01-02_second.html', {'title': "Second"},
+                    "something 2"))
+    with mock_fs_scope(fs):
         fs.runChef('bake')
         structure = fs.getStructure('kitchen/_counter')
-        assert structure['index.html'] == 'Second\nFirst\n'
+        assert structure['index.html'] == 'Second : something 2\nFirst : something 1\n'
         assert structure['2017']['01']['01']['first.html'] == 'something 1'
         assert structure['2017']['01']['02']['second.html'] == 'something 2'
 
+        print("\n\n\n")
         fs.runChef('bake')
         structure = fs.getStructure('kitchen/_counter')
-        assert structure['index.html'] == 'Second\nFirst\n'
+        assert structure['index.html'] == 'Second : something 2\nFirst : something 1\n'
         assert structure['2017']['01']['01']['first.html'] == 'something 1'
         assert structure['2017']['01']['02']['second.html'] == 'something 2'
 
+        print("\n\n\n")
+        fs.runChef('bake')
+        structure = fs.getStructure('kitchen/_counter')
+        assert structure['index.html'] == 'Second : something 2\nFirst : something 1\n'
+        assert structure['2017']['01']['01']['first.html'] == 'something 1'
+        assert structure['2017']['01']['02']['second.html'] == 'something 2'
+
+        print("\n\n\n")
+        fs.runChef('bake')
+        structure = fs.getStructure('kitchen/_counter')
+        assert structure['index.html'] == 'Second : something 2\nFirst : something 1\n'
+        assert structure['2017']['01']['01']['first.html'] == 'something 1'
+        assert structure['2017']['01']['02']['second.html'] == 'something 2'
+