nanoc 4.7.3 → 4.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -5
- data/NEWS.md +7 -0
- data/lib/nanoc/base/entities.rb +1 -1
- data/lib/nanoc/base/entities/{rule_memory.rb → action_sequence.rb} +19 -1
- data/lib/nanoc/base/entities/outdatedness_reasons.rb +12 -4
- data/lib/nanoc/base/entities/outdatedness_status.rb +1 -1
- data/lib/nanoc/base/repos.rb +1 -1
- data/lib/nanoc/base/repos/{rule_memory_store.rb → action_sequence_store.rb} +12 -12
- data/lib/nanoc/base/repos/checksum_store.rb +3 -3
- data/lib/nanoc/base/services/action_provider.rb +1 -9
- data/lib/nanoc/base/services/checksummer.rb +4 -2
- data/lib/nanoc/base/services/compiler.rb +11 -11
- data/lib/nanoc/base/services/compiler/phases/recalculate.rb +3 -3
- data/lib/nanoc/base/services/compiler/stages/cleanup.rb +1 -1
- data/lib/nanoc/base/services/compiler/stages/compile_reps.rb +3 -3
- data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +7 -2
- data/lib/nanoc/base/services/compiler_loader.rb +3 -3
- data/lib/nanoc/base/services/item_rep_builder.rb +4 -2
- data/lib/nanoc/base/services/item_rep_router.rb +7 -2
- data/lib/nanoc/base/services/outdatedness_checker.rb +30 -7
- data/lib/nanoc/base/services/outdatedness_rule.rb +7 -4
- data/lib/nanoc/base/services/outdatedness_rules.rb +9 -161
- data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +34 -0
- data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +26 -0
- data/lib/nanoc/base/services/outdatedness_rules/configuration_modified.rb +23 -0
- data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +15 -0
- data/lib/nanoc/base/services/outdatedness_rules/not_written.rb +11 -0
- data/lib/nanoc/base/services/outdatedness_rules/paths_modified.rb +20 -0
- data/lib/nanoc/base/services/outdatedness_rules/rules_modified.rb +13 -0
- data/lib/nanoc/base/services/outdatedness_rules/uses_always_outdated_filter.rb +20 -0
- data/lib/nanoc/rule_dsl.rb +1 -1
- data/lib/nanoc/rule_dsl/action_provider.rb +7 -11
- data/lib/nanoc/rule_dsl/{rule_memory_calculator.rb → action_sequence_calculator.rb} +21 -39
- data/lib/nanoc/rule_dsl/recording_executor.rb +7 -7
- data/lib/nanoc/spec.rb +7 -7
- data/lib/nanoc/version.rb +1 -1
- data/spec/nanoc/base/checksummer_spec.rb +20 -0
- data/spec/nanoc/base/compiler_spec.rb +7 -10
- data/spec/nanoc/base/entities/action_sequence_spec.rb +278 -0
- data/spec/nanoc/base/repos/checksum_store_spec.rb +22 -2
- data/spec/nanoc/base/services/compiler/stages/cleanup_spec.rb +2 -2
- data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +5 -9
- data/spec/nanoc/base/services/executor_spec.rb +5 -5
- data/spec/nanoc/base/services/item_rep_router_spec.rb +36 -18
- data/spec/nanoc/base/services/outdatedness_checker_spec.rb +74 -30
- data/spec/nanoc/base/services/outdatedness_rules_spec.rb +78 -18
- data/spec/nanoc/helpers/rendering_spec.rb +4 -4
- data/spec/nanoc/rule_dsl/{rule_memory_calculator_spec.rb → action_sequence_calculator_spec.rb} +6 -61
- data/spec/nanoc/rule_dsl/recording_executor_spec.rb +45 -45
- data/test/base/test_outdatedness_checker.rb +1 -1
- data/test/rule_dsl/test_action_provider.rb +3 -3
- metadata +15 -7
- data/spec/nanoc/base/entities/rule_memory_spec.rb +0 -167
| @@ -3,8 +3,11 @@ describe Nanoc::Int::ChecksumStore do | |
| 3 3 |  | 
| 4 4 | 
             
              let(:objects) { [item, code_snippet] }
         | 
| 5 5 |  | 
| 6 | 
            -
              let(:item) { Nanoc::Int::Item.new('asdf',  | 
| 7 | 
            -
              let(:other_item) { Nanoc::Int::Item.new('asdf',  | 
| 6 | 
            +
              let(:item) { Nanoc::Int::Item.new('asdf', item_attributes, '/foo.md') }
         | 
| 7 | 
            +
              let(:other_item) { Nanoc::Int::Item.new('asdf', other_item_attributes, '/sneaky.md') }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              let(:item_attributes) { {} }
         | 
| 10 | 
            +
              let(:other_item_attributes) { {} }
         | 
| 8 11 |  | 
| 9 12 | 
             
              let(:code_snippet) { Nanoc::Int::CodeSnippet.new('def hi ; end', 'lib/foo.rb') }
         | 
| 10 13 | 
             
              let(:other_code_snippet) { Nanoc::Int::CodeSnippet.new('def ho ; end', 'lib/bar.rb') }
         | 
| @@ -90,6 +93,15 @@ describe Nanoc::Int::ChecksumStore do | |
| 90 93 |  | 
| 91 94 | 
             
                it 'has attributes checksum' do
         | 
| 92 95 | 
             
                  expect(store.attributes_checksum_for(item)).not_to be_nil
         | 
| 96 | 
            +
                  expect(store.attributes_checksum_for(item)).to eq({})
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                context 'item has attributes' do
         | 
| 100 | 
            +
                  let(:item_attributes) { { animal: 'donkey' } }
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  it 'has attribute checksum for specified attribute' do
         | 
| 103 | 
            +
                    expect(store.attributes_checksum_for(item)).to have_key(:animal)
         | 
| 104 | 
            +
                  end
         | 
| 93 105 | 
             
                end
         | 
| 94 106 |  | 
| 95 107 | 
             
                context 'after storing and loading' do
         | 
| @@ -119,6 +131,14 @@ describe Nanoc::Int::ChecksumStore do | |
| 119 131 | 
             
                  expect(store.attributes_checksum_for(other_item)).not_to be_nil
         | 
| 120 132 | 
             
                end
         | 
| 121 133 |  | 
| 134 | 
            +
                context 'item has attributes' do
         | 
| 135 | 
            +
                  let(:other_item_attributes) { { location: 'Bernauer Str.' } }
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  it 'has attribute checksum for specified attribute' do
         | 
| 138 | 
            +
                    expect(store.attributes_checksum_for(other_item)).to have_key(:location)
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 122 142 | 
             
                context 'after storing and loading' do
         | 
| 123 143 | 
             
                  before do
         | 
| 124 144 | 
             
                    store.store
         | 
| @@ -57,8 +57,8 @@ describe Nanoc::Int::Compiler::Stages::Cleanup do | |
| 57 57 | 
             
                  it_behaves_like 'an old store'
         | 
| 58 58 | 
             
                end
         | 
| 59 59 |  | 
| 60 | 
            -
                context 'tmp/ | 
| 61 | 
            -
                  let(:store_name) { ' | 
| 60 | 
            +
                context 'tmp/action_sequence' do
         | 
| 61 | 
            +
                  let(:store_name) { 'action_sequence' }
         | 
| 62 62 | 
             
                  it_behaves_like 'an old store'
         | 
| 63 63 | 
             
                end
         | 
| 64 64 |  | 
| @@ -3,7 +3,7 @@ describe Nanoc::Int::Compiler::Stages::CompileReps do | |
| 3 3 | 
             
                described_class.new(
         | 
| 4 4 | 
             
                  outdatedness_store: outdatedness_store,
         | 
| 5 5 | 
             
                  dependency_store: dependency_store,
         | 
| 6 | 
            -
                   | 
| 6 | 
            +
                  action_sequences: action_sequences,
         | 
| 7 7 | 
             
                  compilation_context: compilation_context,
         | 
| 8 8 | 
             
                  compiled_content_cache: compiled_content_cache,
         | 
| 9 9 | 
             
                )
         | 
| @@ -20,6 +20,7 @@ describe Nanoc::Int::Compiler::Stages::CompileReps do | |
| 20 20 | 
             
              end
         | 
| 21 21 |  | 
| 22 22 | 
             
              let(:action_provider) { double(:action_provider) }
         | 
| 23 | 
            +
              let(:action_sequences) { double(:action_sequences) }
         | 
| 23 24 | 
             
              let(:reps) { Nanoc::Int::ItemRepRepo.new }
         | 
| 24 25 | 
             
              let(:compiled_content_cache) { Nanoc::Int::CompiledContentCache.new(items: items) }
         | 
| 25 26 | 
             
              let(:snapshot_repo) { Nanoc::Int::SnapshotRepo.new }
         | 
| @@ -59,7 +60,7 @@ describe Nanoc::Int::Compiler::Stages::CompileReps do | |
| 59 60 | 
             
                    Nanoc::Int::ProcessingActions::Snapshot.new([:last], []),
         | 
| 60 61 | 
             
                  ]
         | 
| 61 62 |  | 
| 62 | 
            -
                Nanoc::Int:: | 
| 63 | 
            +
                Nanoc::Int::ActionSequence.new(nil, actions: actions)
         | 
| 63 64 | 
             
              end
         | 
| 64 65 |  | 
| 65 66 | 
             
              before do
         | 
| @@ -70,18 +71,13 @@ describe Nanoc::Int::Compiler::Stages::CompileReps do | |
| 70 71 | 
             
                  rep.snapshot_defs << Nanoc::Int::SnapshotDef.new(:last, binary: false)
         | 
| 71 72 | 
             
                end
         | 
| 72 73 |  | 
| 73 | 
            -
                allow( | 
| 74 | 
            -
                allow( | 
| 74 | 
            +
                allow(action_sequences).to receive(:[]).with(rep).and_return(memory)
         | 
| 75 | 
            +
                allow(action_sequences).to receive(:[]).with(other_rep).and_return(memory)
         | 
| 75 76 | 
             
              end
         | 
| 76 77 |  | 
| 77 78 | 
             
              describe '#compile_reps' do
         | 
| 78 79 | 
             
                subject { stage.run }
         | 
| 79 80 |  | 
| 80 | 
            -
                before do
         | 
| 81 | 
            -
                  allow(action_provider).to receive(:snapshots_defs_for).with(rep).and_return(snapshot_defs_for_rep)
         | 
| 82 | 
            -
                  allow(action_provider).to receive(:snapshots_defs_for).with(other_rep).and_return(snapshot_defs_for_rep)
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
             | 
| 85 81 | 
             
                let(:snapshot_defs_for_rep) do
         | 
| 86 82 | 
             
                  [Nanoc::Int::SnapshotDef.new(:last, binary: false)]
         | 
| 87 83 | 
             
                end
         | 
| @@ -407,8 +407,8 @@ describe Nanoc::Int::Executor do | |
| 407 407 | 
             
                  )
         | 
| 408 408 | 
             
                end
         | 
| 409 409 |  | 
| 410 | 
            -
                let(: | 
| 411 | 
            -
                  Nanoc::Int:: | 
| 410 | 
            +
                let(:action_sequence) do
         | 
| 411 | 
            +
                  Nanoc::Int::ActionSequence.new(rep).tap do |mem|
         | 
| 412 412 | 
             
                    mem.add_filter(:erb, {})
         | 
| 413 413 | 
             
                  end
         | 
| 414 414 | 
             
                end
         | 
| @@ -422,7 +422,7 @@ describe Nanoc::Int::Executor do | |
| 422 422 | 
             
                  allow(compilation_context).to receive(:assigns_for).with(rep, dependency_tracker) { assigns }
         | 
| 423 423 | 
             
                  allow(compilation_context).to receive(:create_view_context).with(dependency_tracker).and_return(view_context)
         | 
| 424 424 |  | 
| 425 | 
            -
                  allow(action_provider).to receive(: | 
| 425 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(layout).and_return(action_sequence)
         | 
| 426 426 | 
             
                end
         | 
| 427 427 |  | 
| 428 428 | 
             
                subject { executor.layout('/default.*') }
         | 
| @@ -532,8 +532,8 @@ describe Nanoc::Int::Executor do | |
| 532 532 | 
             
                end
         | 
| 533 533 |  | 
| 534 534 | 
             
                context 'no filter specified' do
         | 
| 535 | 
            -
                  let(: | 
| 536 | 
            -
                    Nanoc::Int:: | 
| 535 | 
            +
                  let(:action_sequence) do
         | 
| 536 | 
            +
                    Nanoc::Int::ActionSequence.new(rep)
         | 
| 537 537 | 
             
                  end
         | 
| 538 538 |  | 
| 539 539 | 
             
                  it 'raises' do
         | 
| @@ -18,44 +18,62 @@ describe(Nanoc::Int::ItemRepRouter) do | |
| 18 18 | 
             
                  ]
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 | 
            -
                let(: | 
| 22 | 
            -
                   | 
| 23 | 
            -
                    [ | 
| 24 | 
            -
             | 
| 21 | 
            +
                let(:memory_without_paths) do
         | 
| 22 | 
            +
                  actions =
         | 
| 23 | 
            +
                    [
         | 
| 24 | 
            +
                      Nanoc::Int::ProcessingActions::Filter.new(:erb, {}),
         | 
| 25 | 
            +
                      Nanoc::Int::ProcessingActions::Snapshot.new([], []),
         | 
| 26 | 
            +
                    ]
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  Nanoc::Int::ActionSequence.new(nil, actions: actions)
         | 
| 25 29 | 
             
                end
         | 
| 26 30 |  | 
| 27 | 
            -
                let(: | 
| 28 | 
            -
                   | 
| 29 | 
            -
                    [ | 
| 30 | 
            -
             | 
| 31 | 
            +
                let(:action_sequence_for_default) do
         | 
| 32 | 
            +
                  actions =
         | 
| 33 | 
            +
                    [
         | 
| 34 | 
            +
                      Nanoc::Int::ProcessingActions::Filter.new(:erb, {}),
         | 
| 35 | 
            +
                      Nanoc::Int::ProcessingActions::Snapshot.new([:last], ['/foo/index.html']),
         | 
| 36 | 
            +
                    ]
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  Nanoc::Int::ActionSequence.new(nil, actions: actions)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                let(:action_sequence_for_csv) do
         | 
| 42 | 
            +
                  actions =
         | 
| 43 | 
            +
                    [
         | 
| 44 | 
            +
                      Nanoc::Int::ProcessingActions::Filter.new(:erb, {}),
         | 
| 45 | 
            +
                      Nanoc::Int::ProcessingActions::Snapshot.new([:last], ['/foo.csv']),
         | 
| 46 | 
            +
                    ]
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  Nanoc::Int::ActionSequence.new(nil, actions: actions)
         | 
| 31 49 | 
             
                end
         | 
| 32 50 |  | 
| 33 51 | 
             
                example do
         | 
| 34 | 
            -
                  allow(action_provider).to receive(: | 
| 35 | 
            -
                  allow(action_provider).to receive(: | 
| 52 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(reps[0]).and_return(action_sequence_for_default)
         | 
| 53 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(reps[1]).and_return(action_sequence_for_csv)
         | 
| 36 54 |  | 
| 37 55 | 
             
                  subject
         | 
| 38 56 |  | 
| 39 57 | 
             
                  expect(reps[0].raw_paths).to eql(last: ['output/foo/index.html'])
         | 
| 40 58 | 
             
                  expect(reps[0].paths).to eql(last: ['/foo/'])
         | 
| 41 59 |  | 
| 42 | 
            -
                  expect(reps[1].raw_paths).to eql(last: ['output/ | 
| 43 | 
            -
                  expect(reps[1].paths).to eql(last: ['/ | 
| 60 | 
            +
                  expect(reps[1].raw_paths).to eql(last: ['output/foo.csv'])
         | 
| 61 | 
            +
                  expect(reps[1].paths).to eql(last: ['/foo.csv'])
         | 
| 44 62 | 
             
                end
         | 
| 45 63 |  | 
| 46 64 | 
             
                it 'picks the paths last returned' do
         | 
| 47 | 
            -
                   | 
| 48 | 
            -
             | 
| 49 | 
            -
                   | 
| 50 | 
            -
             | 
| 65 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(reps[0])
         | 
| 66 | 
            +
                    .and_return(memory_without_paths, action_sequence_for_default)
         | 
| 67 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(reps[1])
         | 
| 68 | 
            +
                    .and_return(memory_without_paths, action_sequence_for_csv)
         | 
| 51 69 |  | 
| 52 70 | 
             
                  subject
         | 
| 53 71 |  | 
| 54 72 | 
             
                  expect(reps[0].raw_paths).to eql(last: ['output/foo/index.html'])
         | 
| 55 73 | 
             
                  expect(reps[0].paths).to eql(last: ['/foo/'])
         | 
| 56 74 |  | 
| 57 | 
            -
                  expect(reps[1].raw_paths).to eql(last: ['output/ | 
| 58 | 
            -
                  expect(reps[1].paths).to eql(last: ['/ | 
| 75 | 
            +
                  expect(reps[1].raw_paths).to eql(last: ['output/foo.csv'])
         | 
| 76 | 
            +
                  expect(reps[1].paths).to eql(last: ['/foo.csv'])
         | 
| 59 77 | 
             
                end
         | 
| 60 78 | 
             
              end
         | 
| 61 79 |  | 
| @@ -4,7 +4,7 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 4 4 | 
             
                  site: site,
         | 
| 5 5 | 
             
                  checksum_store: checksum_store,
         | 
| 6 6 | 
             
                  dependency_store: dependency_store,
         | 
| 7 | 
            -
                   | 
| 7 | 
            +
                  action_sequence_store: action_sequence_store,
         | 
| 8 8 | 
             
                  action_provider: action_provider,
         | 
| 9 9 | 
             
                  reps: reps,
         | 
| 10 10 | 
             
                )
         | 
| @@ -26,17 +26,17 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 26 26 | 
             
                )
         | 
| 27 27 | 
             
              end
         | 
| 28 28 |  | 
| 29 | 
            -
              let(: | 
| 30 | 
            -
                Nanoc::Int:: | 
| 29 | 
            +
              let(:action_sequence_store) do
         | 
| 30 | 
            +
                Nanoc::Int::ActionSequenceStore.new
         | 
| 31 31 | 
             
              end
         | 
| 32 32 |  | 
| 33 | 
            -
              let(: | 
| 34 | 
            -
                Nanoc::Int:: | 
| 33 | 
            +
              let(:old_action_sequence_for_item_rep) do
         | 
| 34 | 
            +
                Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 35 35 | 
             
                  mem.add_filter(:erb, {})
         | 
| 36 36 | 
             
                end
         | 
| 37 37 | 
             
              end
         | 
| 38 38 |  | 
| 39 | 
            -
              let(: | 
| 39 | 
            +
              let(:new_action_sequence_for_item_rep) { old_action_sequence_for_item_rep }
         | 
| 40 40 |  | 
| 41 41 | 
             
              let(:action_provider) { double(:action_provider) }
         | 
| 42 42 |  | 
| @@ -51,9 +51,9 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 51 51 |  | 
| 52 52 | 
             
              before do
         | 
| 53 53 | 
             
                reps << item_rep
         | 
| 54 | 
            -
                 | 
| 54 | 
            +
                action_sequence_store[item_rep] = old_action_sequence_for_item_rep.serialize
         | 
| 55 55 |  | 
| 56 | 
            -
                allow(action_provider).to receive(: | 
| 56 | 
            +
                allow(action_provider).to receive(:action_sequence_for).with(item_rep).and_return(new_action_sequence_for_item_rep)
         | 
| 57 57 | 
             
              end
         | 
| 58 58 |  | 
| 59 59 | 
             
              describe '#basic_outdatedness_reason_for' do
         | 
| @@ -73,9 +73,9 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 73 73 | 
             
                context 'with item' do
         | 
| 74 74 | 
             
                  let(:obj) { item }
         | 
| 75 75 |  | 
| 76 | 
            -
                  context ' | 
| 77 | 
            -
                    let(: | 
| 78 | 
            -
                      Nanoc::Int:: | 
| 76 | 
            +
                  context 'action sequence differs' do
         | 
| 77 | 
            +
                    let(:new_action_sequence_for_item_rep) do
         | 
| 78 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 79 79 | 
             
                        mem.add_filter(:super_erb, {})
         | 
| 80 80 | 
             
                      end
         | 
| 81 81 | 
             
                    end
         | 
| @@ -91,9 +91,9 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 91 91 | 
             
                context 'with item rep' do
         | 
| 92 92 | 
             
                  let(:obj) { item_rep }
         | 
| 93 93 |  | 
| 94 | 
            -
                  context ' | 
| 95 | 
            -
                    let(: | 
| 96 | 
            -
                      Nanoc::Int:: | 
| 94 | 
            +
                  context 'action sequence differs' do
         | 
| 95 | 
            +
                    let(:new_action_sequence_for_item_rep) do
         | 
| 96 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 97 97 | 
             
                        mem.add_filter(:super_erb, {})
         | 
| 98 98 | 
             
                      end
         | 
| 99 99 | 
             
                    end
         | 
| @@ -123,22 +123,22 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 123 123 |  | 
| 124 124 | 
             
                let(:objects) { [item, other_item] }
         | 
| 125 125 |  | 
| 126 | 
            -
                let(: | 
| 127 | 
            -
                  Nanoc::Int:: | 
| 126 | 
            +
                let(:old_action_sequence_for_other_item_rep) do
         | 
| 127 | 
            +
                  Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 128 128 | 
             
                    mem.add_filter(:erb, {})
         | 
| 129 129 | 
             
                  end
         | 
| 130 130 | 
             
                end
         | 
| 131 131 |  | 
| 132 | 
            -
                let(: | 
| 132 | 
            +
                let(:new_action_sequence_for_other_item_rep) { old_action_sequence_for_other_item_rep }
         | 
| 133 133 |  | 
| 134 134 | 
             
                before do
         | 
| 135 135 | 
             
                  reps << other_item_rep
         | 
| 136 | 
            -
                   | 
| 136 | 
            +
                  action_sequence_store[other_item_rep] = old_action_sequence_for_other_item_rep.serialize
         | 
| 137 137 | 
             
                  checksum_store.add(item)
         | 
| 138 138 | 
             
                  checksum_store.add(other_item)
         | 
| 139 139 | 
             
                  checksum_store.add(config)
         | 
| 140 140 |  | 
| 141 | 
            -
                  allow(action_provider).to receive(: | 
| 141 | 
            +
                  allow(action_provider).to receive(:action_sequence_for).with(other_item_rep).and_return(new_action_sequence_for_other_item_rep)
         | 
| 142 142 | 
             
                  allow(site).to receive(:code_snippets).and_return([])
         | 
| 143 143 | 
             
                  allow(site).to receive(:config).and_return(config)
         | 
| 144 144 | 
             
                end
         | 
| @@ -150,8 +150,8 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 150 150 | 
             
                  before do
         | 
| 151 151 | 
             
                    reps << distant_item_rep
         | 
| 152 152 | 
             
                    checksum_store.add(distant_item)
         | 
| 153 | 
            -
                     | 
| 154 | 
            -
                    allow(action_provider).to receive(: | 
| 153 | 
            +
                    action_sequence_store[distant_item_rep] = old_action_sequence_for_other_item_rep.serialize
         | 
| 154 | 
            +
                    allow(action_provider).to receive(:action_sequence_for).with(distant_item_rep).and_return(new_action_sequence_for_other_item_rep)
         | 
| 155 155 | 
             
                  end
         | 
| 156 156 |  | 
| 157 157 | 
             
                  context 'on attribute + attribute' do
         | 
| @@ -217,7 +217,7 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 217 217 | 
             
                  end
         | 
| 218 218 | 
             
                end
         | 
| 219 219 |  | 
| 220 | 
            -
                context 'only attribute dependency' do
         | 
| 220 | 
            +
                context 'only generic attribute dependency' do
         | 
| 221 221 | 
             
                  before do
         | 
| 222 222 | 
             
                    dependency_store.record_dependency(item, other_item, attributes: true)
         | 
| 223 223 | 
             
                  end
         | 
| @@ -239,8 +239,52 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 239 239 | 
             
                  end
         | 
| 240 240 |  | 
| 241 241 | 
             
                  context 'path changed' do
         | 
| 242 | 
            -
                    let(: | 
| 243 | 
            -
                      Nanoc::Int:: | 
| 242 | 
            +
                    let(:new_action_sequence_for_other_item_rep) do
         | 
| 243 | 
            +
                      Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 244 | 
            +
                        mem.add_filter(:erb, {})
         | 
| 245 | 
            +
                        mem.add_snapshot(:donkey, '/giraffe.txt')
         | 
| 246 | 
            +
                      end
         | 
| 247 | 
            +
                    end
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                    it { is_expected.not_to be }
         | 
| 250 | 
            +
                  end
         | 
| 251 | 
            +
                end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                context 'only specific attribute dependency' do
         | 
| 254 | 
            +
                  before do
         | 
| 255 | 
            +
                    dependency_store.record_dependency(item, other_item, attributes: [:title])
         | 
| 256 | 
            +
                  end
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                  context 'attribute changed' do
         | 
| 259 | 
            +
                    before { other_item.attributes[:title] = 'omg new title' }
         | 
| 260 | 
            +
                    it { is_expected.to be }
         | 
| 261 | 
            +
                  end
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                  context 'other attribute changed' do
         | 
| 264 | 
            +
                    before { other_item.attributes[:subtitle] = 'tagline here' }
         | 
| 265 | 
            +
                    it { is_expected.not_to be }
         | 
| 266 | 
            +
                  end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                  context 'raw content changed' do
         | 
| 269 | 
            +
                    before { other_item.content = Nanoc::Int::TextualContent.new('omg new content') }
         | 
| 270 | 
            +
                    it { is_expected.not_to be }
         | 
| 271 | 
            +
                  end
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                  context 'attribute + raw content changed' do
         | 
| 274 | 
            +
                    before { other_item.attributes[:title] = 'omg new title' }
         | 
| 275 | 
            +
                    before { other_item.content = Nanoc::Int::TextualContent.new('omg new content') }
         | 
| 276 | 
            +
                    it { is_expected.to be }
         | 
| 277 | 
            +
                  end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                  context 'other attribute + raw content changed' do
         | 
| 280 | 
            +
                    before { other_item.attributes[:subtitle] = 'tagline here' }
         | 
| 281 | 
            +
                    before { other_item.content = Nanoc::Int::TextualContent.new('omg new content') }
         | 
| 282 | 
            +
                    it { is_expected.not_to be }
         | 
| 283 | 
            +
                  end
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                  context 'path changed' do
         | 
| 286 | 
            +
                    let(:new_action_sequence_for_other_item_rep) do
         | 
| 287 | 
            +
                      Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 244 288 | 
             
                        mem.add_filter(:erb, {})
         | 
| 245 289 | 
             
                        mem.add_snapshot(:donkey, '/giraffe.txt')
         | 
| 246 290 | 
             
                      end
         | 
| @@ -272,8 +316,8 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 272 316 | 
             
                  end
         | 
| 273 317 |  | 
| 274 318 | 
             
                  context 'path changed' do
         | 
| 275 | 
            -
                    let(: | 
| 276 | 
            -
                      Nanoc::Int:: | 
| 319 | 
            +
                    let(:new_action_sequence_for_other_item_rep) do
         | 
| 320 | 
            +
                      Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 277 321 | 
             
                        mem.add_filter(:erb, {})
         | 
| 278 322 | 
             
                        mem.add_snapshot(:donkey, '/giraffe.txt')
         | 
| 279 323 | 
             
                      end
         | 
| @@ -299,8 +343,8 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 299 343 | 
             
                  end
         | 
| 300 344 |  | 
| 301 345 | 
             
                  context 'path changed' do
         | 
| 302 | 
            -
                    let(: | 
| 303 | 
            -
                      Nanoc::Int:: | 
| 346 | 
            +
                    let(:new_action_sequence_for_other_item_rep) do
         | 
| 347 | 
            +
                      Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 304 348 | 
             
                        mem.add_filter(:erb, {})
         | 
| 305 349 | 
             
                        mem.add_snapshot(:donkey, '/giraffe.txt')
         | 
| 306 350 | 
             
                      end
         | 
| @@ -332,8 +376,8 @@ describe Nanoc::Int::OutdatednessChecker do | |
| 332 376 | 
             
                  end
         | 
| 333 377 |  | 
| 334 378 | 
             
                  context 'rules changed' do
         | 
| 335 | 
            -
                    let(: | 
| 336 | 
            -
                      Nanoc::Int:: | 
| 379 | 
            +
                    let(:new_action_sequence_for_other_item_rep) do
         | 
| 380 | 
            +
                      Nanoc::Int::ActionSequence.new(other_item_rep).tap do |mem|
         | 
| 337 381 | 
             
                        mem.add_filter(:erb, {})
         | 
| 338 382 | 
             
                        mem.add_filter(:donkey, {})
         | 
| 339 383 | 
             
                      end
         | 
| @@ -9,7 +9,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 9 9 | 
             
                    site: site,
         | 
| 10 10 | 
             
                    checksum_store: checksum_store,
         | 
| 11 11 | 
             
                    dependency_store: dependency_store,
         | 
| 12 | 
            -
                     | 
| 12 | 
            +
                    action_sequence_store: action_sequence_store,
         | 
| 13 13 | 
             
                    action_provider: action_provider,
         | 
| 14 14 | 
             
                    reps: reps,
         | 
| 15 15 | 
             
                  )
         | 
| @@ -33,7 +33,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 33 33 | 
             
                let(:action_provider) { double(:action_provider) }
         | 
| 34 34 | 
             
                let(:reps) { Nanoc::Int::ItemRepRepo.new }
         | 
| 35 35 | 
             
                let(:dependency_store) { Nanoc::Int::DependencyStore.new(dependency_store_objects) }
         | 
| 36 | 
            -
                let(: | 
| 36 | 
            +
                let(:action_sequence_store) { Nanoc::Int::ActionSequenceStore.new }
         | 
| 37 37 | 
             
                let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: objects) }
         | 
| 38 38 |  | 
| 39 39 | 
             
                let(:dependency_store_objects) { [item] }
         | 
| @@ -213,8 +213,58 @@ describe Nanoc::Int::OutdatednessRules do | |
| 213 213 |  | 
| 214 214 | 
             
                    context 'checksum available, but attributes different' do
         | 
| 215 215 | 
             
                      let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 216 | 
            +
             | 
| 216 217 | 
             
                      before { checksum_store.add(old_item) }
         | 
| 218 | 
            +
             | 
| 217 219 | 
             
                      it { is_expected.to be }
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                      it 'has the one changed attribute' do
         | 
| 222 | 
            +
                        expect(subject.attributes).to contain_exactly(:greeting)
         | 
| 223 | 
            +
                      end
         | 
| 224 | 
            +
                    end
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                    context 'attribute kept identical' do
         | 
| 227 | 
            +
                      let(:item)     { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 228 | 
            +
                      let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                      before { checksum_store.add(old_item) }
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                      it 'has the one changed attribute' do
         | 
| 233 | 
            +
                        expect(subject).to be_nil
         | 
| 234 | 
            +
                      end
         | 
| 235 | 
            +
                    end
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                    context 'attribute changed' do
         | 
| 238 | 
            +
                      let(:item)     { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 239 | 
            +
                      let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'ho' }, '/foo.md') }
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                      before { checksum_store.add(old_item) }
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                      it 'has the one changed attribute' do
         | 
| 244 | 
            +
                        expect(subject.attributes).to contain_exactly(:greeting)
         | 
| 245 | 
            +
                      end
         | 
| 246 | 
            +
                    end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                    context 'attribute deleted' do
         | 
| 249 | 
            +
                      let(:item)     { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 250 | 
            +
                      let(:old_item) { Nanoc::Int::Item.new('stuff', {}, '/foo.md') }
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                      before { checksum_store.add(old_item) }
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                      it 'has the one changed attribute' do
         | 
| 255 | 
            +
                        expect(subject.attributes).to contain_exactly(:greeting)
         | 
| 256 | 
            +
                      end
         | 
| 257 | 
            +
                    end
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                    context 'attribute added' do
         | 
| 260 | 
            +
                      let(:item)     { Nanoc::Int::Item.new('stuff', {}, '/foo.md') }
         | 
| 261 | 
            +
                      let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                      before { checksum_store.add(old_item) }
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                      it 'has the one changed attribute' do
         | 
| 266 | 
            +
                        expect(subject.attributes).to contain_exactly(:greeting)
         | 
| 267 | 
            +
                      end
         | 
| 218 268 | 
             
                    end
         | 
| 219 269 | 
             
                  end
         | 
| 220 270 |  | 
| @@ -238,8 +288,14 @@ describe Nanoc::Int::OutdatednessRules do | |
| 238 288 |  | 
| 239 289 | 
             
                    context 'checksum available, but attributes different' do
         | 
| 240 290 | 
             
                      let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
         | 
| 291 | 
            +
             | 
| 241 292 | 
             
                      before { checksum_store.add(old_item) }
         | 
| 293 | 
            +
             | 
| 242 294 | 
             
                      it { is_expected.to be }
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                      it 'has the one changed attribute' do
         | 
| 297 | 
            +
                        expect(subject.attributes).to contain_exactly(:greeting)
         | 
| 298 | 
            +
                      end
         | 
| 243 299 | 
             
                    end
         | 
| 244 300 | 
             
                  end
         | 
| 245 301 | 
             
                end
         | 
| @@ -248,14 +304,14 @@ describe Nanoc::Int::OutdatednessRules do | |
| 248 304 | 
             
                  let(:rule_class) { Nanoc::Int::OutdatednessRules::RulesModified }
         | 
| 249 305 |  | 
| 250 306 | 
             
                  let(:old_mem) do
         | 
| 251 | 
            -
                    Nanoc::Int:: | 
| 307 | 
            +
                    Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 252 308 | 
             
                      mem.add_filter(:erb, {})
         | 
| 253 309 | 
             
                    end
         | 
| 254 310 | 
             
                  end
         | 
| 255 311 |  | 
| 256 312 | 
             
                  before do
         | 
| 257 | 
            -
                     | 
| 258 | 
            -
                    allow(action_provider).to receive(: | 
| 313 | 
            +
                    action_sequence_store[item_rep] = old_mem.serialize
         | 
| 314 | 
            +
                    allow(action_provider).to receive(:action_sequence_for).with(item_rep).and_return(new_mem)
         | 
| 259 315 | 
             
                  end
         | 
| 260 316 |  | 
| 261 317 | 
             
                  context 'memory is the same' do
         | 
| @@ -265,7 +321,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 265 321 |  | 
| 266 322 | 
             
                  context 'memory is different' do
         | 
| 267 323 | 
             
                    let(:new_mem) do
         | 
| 268 | 
            -
                      Nanoc::Int:: | 
| 324 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 269 325 | 
             
                        mem.add_filter(:erb, {})
         | 
| 270 326 | 
             
                        mem.add_filter(:donkey, {})
         | 
| 271 327 | 
             
                      end
         | 
| @@ -279,12 +335,12 @@ describe Nanoc::Int::OutdatednessRules do | |
| 279 335 | 
             
                  let(:rule_class) { Nanoc::Int::OutdatednessRules::PathsModified }
         | 
| 280 336 |  | 
| 281 337 | 
             
                  before do
         | 
| 282 | 
            -
                    allow(action_provider).to receive(: | 
| 338 | 
            +
                    allow(action_provider).to receive(:action_sequence_for).with(item_rep).and_return(new_mem)
         | 
| 283 339 | 
             
                  end
         | 
| 284 340 |  | 
| 285 341 | 
             
                  context 'old mem does not exist' do
         | 
| 286 342 | 
             
                    let(:new_mem) do
         | 
| 287 | 
            -
                      Nanoc::Int:: | 
| 343 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 288 344 | 
             
                        mem.add_snapshot(:donkey, '/foo.md')
         | 
| 289 345 | 
             
                        mem.add_filter(:asdf, {})
         | 
| 290 346 | 
             
                      end
         | 
| @@ -295,19 +351,19 @@ describe Nanoc::Int::OutdatednessRules do | |
| 295 351 |  | 
| 296 352 | 
             
                  context 'old mem exists' do
         | 
| 297 353 | 
             
                    let(:old_mem) do
         | 
| 298 | 
            -
                      Nanoc::Int:: | 
| 354 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 299 355 | 
             
                        mem.add_filter(:erb, {})
         | 
| 300 356 | 
             
                        mem.add_snapshot(:donkey, '/foo.md')
         | 
| 301 357 | 
             
                      end
         | 
| 302 358 | 
             
                    end
         | 
| 303 359 |  | 
| 304 360 | 
             
                    before do
         | 
| 305 | 
            -
                       | 
| 361 | 
            +
                      action_sequence_store[item_rep] = old_mem.serialize
         | 
| 306 362 | 
             
                    end
         | 
| 307 363 |  | 
| 308 364 | 
             
                    context 'paths in memory are the same' do
         | 
| 309 365 | 
             
                      let(:new_mem) do
         | 
| 310 | 
            -
                        Nanoc::Int:: | 
| 366 | 
            +
                        Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 311 367 | 
             
                          mem.add_snapshot(:donkey, '/foo.md')
         | 
| 312 368 | 
             
                          mem.add_filter(:asdf, {})
         | 
| 313 369 | 
             
                        end
         | 
| @@ -318,7 +374,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 318 374 |  | 
| 319 375 | 
             
                    context 'paths in memory are different' do
         | 
| 320 376 | 
             
                      let(:new_mem) do
         | 
| 321 | 
            -
                        Nanoc::Int:: | 
| 377 | 
            +
                        Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 322 378 | 
             
                          mem.add_filter(:erb, {})
         | 
| 323 379 | 
             
                          mem.add_snapshot(:donkey, '/foo.md')
         | 
| 324 380 | 
             
                          mem.add_filter(:donkey, {})
         | 
| @@ -382,8 +438,10 @@ describe Nanoc::Int::OutdatednessRules do | |
| 382 438 | 
             
                        before { checksum_store.add(stored_obj) }
         | 
| 383 439 |  | 
| 384 440 | 
             
                        context 'but checksum data afterwards' do
         | 
| 441 | 
            +
                          # NOTE: ignored for attributes!
         | 
| 442 | 
            +
             | 
| 385 443 | 
             
                          let(:new_obj) { klass.new('a', {}, '/foo.md', checksum_data: 'cs-data-new') }
         | 
| 386 | 
            -
                          it { is_expected.to eql([true,  | 
| 444 | 
            +
                          it { is_expected.to eql([true, false]) }
         | 
| 387 445 | 
             
                        end
         | 
| 388 446 |  | 
| 389 447 | 
             
                        context 'and unchanged' do
         | 
| @@ -415,6 +473,8 @@ describe Nanoc::Int::OutdatednessRules do | |
| 415 473 | 
             
                    end
         | 
| 416 474 |  | 
| 417 475 | 
             
                    context 'attributes_checksum_data' do
         | 
| 476 | 
            +
                      # NOTE: attributes_checksum_data is ignored!
         | 
| 477 | 
            +
             | 
| 418 478 | 
             
                      let(:stored_obj) { klass.new('a', {}, '/foo.md', attributes_checksum_data: 'cs-data') }
         | 
| 419 479 | 
             
                      let(:new_obj)    { stored_obj }
         | 
| 420 480 |  | 
| @@ -427,7 +487,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 427 487 |  | 
| 428 488 | 
             
                        context 'but checksum data afterwards' do
         | 
| 429 489 | 
             
                          let(:new_obj) { klass.new('a', {}, '/foo.md', attributes_checksum_data: 'cs-data-new') }
         | 
| 430 | 
            -
                          it { is_expected.to eql([false,  | 
| 490 | 
            +
                          it { is_expected.to eql([false, false]) }
         | 
| 431 491 | 
             
                        end
         | 
| 432 492 |  | 
| 433 493 | 
             
                        context 'and unchanged' do
         | 
| @@ -454,12 +514,12 @@ describe Nanoc::Int::OutdatednessRules do | |
| 454 514 | 
             
                  let(:rule_class) { Nanoc::Int::OutdatednessRules::UsesAlwaysOutdatedFilter }
         | 
| 455 515 |  | 
| 456 516 | 
             
                  before do
         | 
| 457 | 
            -
                    allow(action_provider).to receive(: | 
| 517 | 
            +
                    allow(action_provider).to receive(:action_sequence_for).with(item_rep).and_return(mem)
         | 
| 458 518 | 
             
                  end
         | 
| 459 519 |  | 
| 460 520 | 
             
                  context 'unknown filter' do
         | 
| 461 521 | 
             
                    let(:mem) do
         | 
| 462 | 
            -
                      Nanoc::Int:: | 
| 522 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 463 523 | 
             
                        mem.add_snapshot(:donkey, '/foo.md')
         | 
| 464 524 | 
             
                        mem.add_filter(:asdf, {})
         | 
| 465 525 | 
             
                      end
         | 
| @@ -470,7 +530,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 470 530 |  | 
| 471 531 | 
             
                  context 'known filter, not always outdated' do
         | 
| 472 532 | 
             
                    let(:mem) do
         | 
| 473 | 
            -
                      Nanoc::Int:: | 
| 533 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 474 534 | 
             
                        mem.add_snapshot(:donkey, '/foo.md')
         | 
| 475 535 | 
             
                        mem.add_filter(:erb, {})
         | 
| 476 536 | 
             
                      end
         | 
| @@ -481,7 +541,7 @@ describe Nanoc::Int::OutdatednessRules do | |
| 481 541 |  | 
| 482 542 | 
             
                  context 'known filter, always outdated' do
         | 
| 483 543 | 
             
                    let(:mem) do
         | 
| 484 | 
            -
                      Nanoc::Int:: | 
| 544 | 
            +
                      Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
         | 
| 485 545 | 
             
                        mem.add_snapshot(:donkey, '/foo.md')
         | 
| 486 546 | 
             
                        mem.add_filter(:xsl, {})
         | 
| 487 547 | 
             
                      end
         |