nanoc 4.7.7 → 4.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -5
  3. data/NEWS.md +12 -0
  4. data/lib/nanoc/base/entities.rb +1 -0
  5. data/lib/nanoc/base/entities/action_sequence.rb +8 -36
  6. data/lib/nanoc/base/entities/checksum_collection.rb +31 -0
  7. data/lib/nanoc/base/entities/directed_graph.rb +35 -11
  8. data/lib/nanoc/base/errors.rb +3 -1
  9. data/lib/nanoc/base/repos/checksum_store.rb +1 -0
  10. data/lib/nanoc/base/services.rb +1 -0
  11. data/lib/nanoc/base/services/action_sequence_builder.rb +45 -0
  12. data/lib/nanoc/base/services/compiler.rb +34 -14
  13. data/lib/nanoc/base/services/compiler/stages.rb +1 -0
  14. data/lib/nanoc/base/services/compiler/stages/calculate_checksums.rb +31 -0
  15. data/lib/nanoc/base/services/compiler/stages/store_pre_compilation_state.rb +6 -13
  16. data/lib/nanoc/base/services/outdatedness_checker.rb +4 -2
  17. data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +1 -1
  18. data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +1 -1
  19. data/lib/nanoc/base/services/outdatedness_rules/configuration_modified.rb +1 -1
  20. data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +1 -1
  21. data/lib/nanoc/cli/cleaning_stream.rb +1 -1
  22. data/lib/nanoc/cli/commands/show-data.rb +1 -0
  23. data/lib/nanoc/rule_dsl/action_sequence_calculator.rb +7 -14
  24. data/lib/nanoc/rule_dsl/recording_executor.rb +40 -7
  25. data/lib/nanoc/version.rb +1 -1
  26. data/spec/nanoc/base/compiler_spec.rb +5 -5
  27. data/spec/nanoc/base/directed_graph_spec.rb +12 -0
  28. data/spec/nanoc/base/entities/action_sequence_spec.rb +132 -79
  29. data/spec/nanoc/base/errors/dependency_cycle_spec.rb +4 -4
  30. data/spec/nanoc/base/services/compiler/stages/calculate_checksums_spec.rb +69 -0
  31. data/spec/nanoc/base/services/executor_spec.rb +2 -2
  32. data/spec/nanoc/base/services/item_rep_router_spec.rb +4 -4
  33. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +40 -24
  34. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +27 -15
  35. data/spec/nanoc/cli/commands/show_data_spec.rb +2 -0
  36. data/spec/nanoc/rule_dsl/action_sequence_calculator_spec.rb +15 -13
  37. data/spec/nanoc/rule_dsl/recording_executor_spec.rb +4 -3
  38. data/test/cli/test_cleaning_stream.rb +8 -0
  39. metadata +6 -2
@@ -21,10 +21,10 @@ describe Nanoc::Int::Errors::DependencyCycle do
21
21
  expected = <<EOS
22
22
  The site cannot be compiled because there is a dependency cycle:
23
23
 
24
- (1) item /b.md, rep :default, depends on
25
- (2) item /c.md, rep :default, depends on
26
- (3) item /d.md, rep :default, depends on
27
- (4) item /e.md, rep :default, depends on (1)
24
+ (1) item /e.md, rep :default, uses compiled content of
25
+ (2) item /d.md, rep :default, uses compiled content of
26
+ (3) item /c.md, rep :default, uses compiled content of
27
+ (4) item /b.md, rep :default, uses compiled content of (1)
28
28
  EOS
29
29
 
30
30
  expect(error.message).to eql(expected)
@@ -0,0 +1,69 @@
1
+ describe Nanoc::Int::Compiler::Stages::CalculateChecksums do
2
+ let(:stage) do
3
+ described_class.new(items: items, layouts: layouts, code_snippets: code_snippets, config: config)
4
+ end
5
+
6
+ let(:config) do
7
+ Nanoc::Int::Configuration.new.with_defaults
8
+ end
9
+
10
+ let(:code_snippets) do
11
+ [code_snippet]
12
+ end
13
+
14
+ let(:items) do
15
+ Nanoc::Int::IdentifiableCollection.new(config, [item])
16
+ end
17
+
18
+ let(:layouts) do
19
+ Nanoc::Int::IdentifiableCollection.new(config, [layout])
20
+ end
21
+
22
+ let(:code_snippet) do
23
+ Nanoc::Int::CodeSnippet.new('woof!', 'dog.rb')
24
+ end
25
+
26
+ let(:item) do
27
+ Nanoc::Int::Item.new('hello there', {}, '/hi.md')
28
+ end
29
+
30
+ let(:layout) do
31
+ Nanoc::Int::Layout.new('t3mpl4t3', {}, '/page.erb')
32
+ end
33
+
34
+ describe '#run' do
35
+ subject { stage.run }
36
+
37
+ it 'checksums items' do
38
+ expect(subject.checksum_for(item))
39
+ .to eq(Nanoc::Int::Checksummer.calc(item))
40
+
41
+ expect(subject.content_checksum_for(item))
42
+ .to eq(Nanoc::Int::Checksummer.calc_for_content_of(item))
43
+
44
+ expect(subject.attributes_checksum_for(item))
45
+ .to eq(Nanoc::Int::Checksummer.calc_for_each_attribute_of(item))
46
+ end
47
+
48
+ it 'checksums layouts' do
49
+ expect(subject.checksum_for(layout))
50
+ .to eq(Nanoc::Int::Checksummer.calc(layout))
51
+
52
+ expect(subject.content_checksum_for(layout))
53
+ .to eq(Nanoc::Int::Checksummer.calc_for_content_of(layout))
54
+
55
+ expect(subject.attributes_checksum_for(layout))
56
+ .to eq(Nanoc::Int::Checksummer.calc_for_each_attribute_of(layout))
57
+ end
58
+
59
+ it 'checksums config' do
60
+ expect(subject.checksum_for(config))
61
+ .to eq(Nanoc::Int::Checksummer.calc(config))
62
+ end
63
+
64
+ it 'checksums code snippets' do
65
+ expect(subject.checksum_for(code_snippet))
66
+ .to eq(Nanoc::Int::Checksummer.calc(code_snippet))
67
+ end
68
+ end
69
+ end
@@ -408,8 +408,8 @@ describe Nanoc::Int::Executor do
408
408
  end
409
409
 
410
410
  let(:action_sequence) do
411
- Nanoc::Int::ActionSequence.new(rep).tap do |seq|
412
- seq.add_filter(:erb, {})
411
+ Nanoc::Int::ActionSequence.build(rep) do |b|
412
+ b.add_filter(:erb, {})
413
413
  end
414
414
  end
415
415
 
@@ -62,10 +62,10 @@ describe(Nanoc::Int::ItemRepRouter) do
62
62
  end
63
63
 
64
64
  it 'picks the paths last returned' do
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)
65
+ allow(action_provider).to receive(:action_sequence_for)
66
+ .with(reps[0]).and_return(memory_without_paths, action_sequence_for_default)
67
+ allow(action_provider).to receive(:action_sequence_for)
68
+ .with(reps[1]).and_return(memory_without_paths, action_sequence_for_csv)
69
69
 
70
70
  subject
71
71
 
@@ -3,6 +3,7 @@ describe Nanoc::Int::OutdatednessChecker do
3
3
  described_class.new(
4
4
  site: site,
5
5
  checksum_store: checksum_store,
6
+ checksums: checksums,
6
7
  dependency_store: dependency_store,
7
8
  action_sequence_store: action_sequence_store,
8
9
  action_sequences: action_sequences,
@@ -12,6 +13,15 @@ describe Nanoc::Int::OutdatednessChecker do
12
13
 
13
14
  let(:checksum_store) { double(:checksum_store) }
14
15
 
16
+ let(:checksums) do
17
+ Nanoc::Int::Compiler::Stages::CalculateChecksums.new(
18
+ items: items,
19
+ layouts: layouts,
20
+ code_snippets: code_snippets,
21
+ config: config,
22
+ ).run
23
+ end
24
+
15
25
  let(:dependency_store) do
16
26
  Nanoc::Int::DependencyStore.new(items, layouts)
17
27
  end
@@ -19,10 +29,12 @@ describe Nanoc::Int::OutdatednessChecker do
19
29
  let(:items) { Nanoc::Int::IdentifiableCollection.new(config, [item]) }
20
30
  let(:layouts) { Nanoc::Int::IdentifiableCollection.new(config) }
21
31
 
32
+ let(:code_snippets) { [] }
33
+
22
34
  let(:site) do
23
35
  Nanoc::Int::Site.new(
24
36
  config: config,
25
- code_snippets: [],
37
+ code_snippets: code_snippets,
26
38
  data_source: Nanoc::Int::InMemDataSource.new([], []),
27
39
  )
28
40
  end
@@ -32,8 +44,8 @@ describe Nanoc::Int::OutdatednessChecker do
32
44
  end
33
45
 
34
46
  let(:old_action_sequence_for_item_rep) do
35
- Nanoc::Int::ActionSequence.new(item_rep).tap do |seq|
36
- seq.add_filter(:erb, {})
47
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
48
+ b.add_filter(:erb, {})
37
49
  end
38
50
  end
39
51
 
@@ -74,8 +86,8 @@ describe Nanoc::Int::OutdatednessChecker do
74
86
 
75
87
  context 'action sequence differs' do
76
88
  let(:new_action_sequence_for_item_rep) do
77
- Nanoc::Int::ActionSequence.new(item_rep).tap do |seq|
78
- seq.add_filter(:super_erb, {})
89
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
90
+ b.add_filter(:super_erb, {})
79
91
  end
80
92
  end
81
93
 
@@ -92,8 +104,8 @@ describe Nanoc::Int::OutdatednessChecker do
92
104
 
93
105
  context 'action sequence differs' do
94
106
  let(:new_action_sequence_for_item_rep) do
95
- Nanoc::Int::ActionSequence.new(item_rep).tap do |seq|
96
- seq.add_filter(:super_erb, {})
107
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
108
+ b.add_filter(:super_erb, {})
97
109
  end
98
110
  end
99
111
 
@@ -123,8 +135,8 @@ describe Nanoc::Int::OutdatednessChecker do
123
135
  let(:items) { Nanoc::Int::IdentifiableCollection.new(config, [item, other_item]) }
124
136
 
125
137
  let(:old_action_sequence_for_other_item_rep) do
126
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
127
- seq.add_filter(:erb, {})
138
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
139
+ b.add_filter(:erb, {})
128
140
  end
129
141
  end
130
142
 
@@ -152,6 +164,10 @@ describe Nanoc::Int::OutdatednessChecker do
152
164
  let(:distant_item) { Nanoc::Int::Item.new('distant stuff', {}, '/distant.md') }
153
165
  let(:distant_item_rep) { Nanoc::Int::ItemRep.new(distant_item, :default) }
154
166
 
167
+ let(:items) do
168
+ Nanoc::Int::IdentifiableCollection.new(config, [item, other_item, distant_item])
169
+ end
170
+
155
171
  let(:action_sequences) do
156
172
  {
157
173
  item_rep => new_action_sequence_for_item_rep,
@@ -252,9 +268,9 @@ describe Nanoc::Int::OutdatednessChecker do
252
268
 
253
269
  context 'path changed' do
254
270
  let(:new_action_sequence_for_other_item_rep) do
255
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
256
- seq.add_filter(:erb, {})
257
- seq.add_snapshot(:donkey, '/giraffe.txt')
271
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
272
+ b.add_filter(:erb, {})
273
+ b.add_snapshot(:donkey, '/giraffe.txt')
258
274
  end
259
275
  end
260
276
 
@@ -296,9 +312,9 @@ describe Nanoc::Int::OutdatednessChecker do
296
312
 
297
313
  context 'path changed' do
298
314
  let(:new_action_sequence_for_other_item_rep) do
299
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
300
- seq.add_filter(:erb, {})
301
- seq.add_snapshot(:donkey, '/giraffe.txt')
315
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
316
+ b.add_filter(:erb, {})
317
+ b.add_snapshot(:donkey, '/giraffe.txt')
302
318
  end
303
319
  end
304
320
 
@@ -329,9 +345,9 @@ describe Nanoc::Int::OutdatednessChecker do
329
345
 
330
346
  context 'path changed' do
331
347
  let(:new_action_sequence_for_other_item_rep) do
332
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
333
- seq.add_filter(:erb, {})
334
- seq.add_snapshot(:donkey, '/giraffe.txt')
348
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
349
+ b.add_filter(:erb, {})
350
+ b.add_snapshot(:donkey, '/giraffe.txt')
335
351
  end
336
352
  end
337
353
 
@@ -356,9 +372,9 @@ describe Nanoc::Int::OutdatednessChecker do
356
372
 
357
373
  context 'path changed' do
358
374
  let(:new_action_sequence_for_other_item_rep) do
359
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
360
- seq.add_filter(:erb, {})
361
- seq.add_snapshot(:donkey, '/giraffe.txt')
375
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
376
+ b.add_filter(:erb, {})
377
+ b.add_snapshot(:donkey, '/giraffe.txt')
362
378
  end
363
379
  end
364
380
 
@@ -389,9 +405,9 @@ describe Nanoc::Int::OutdatednessChecker do
389
405
 
390
406
  context 'rules changed' do
391
407
  let(:new_action_sequence_for_other_item_rep) do
392
- Nanoc::Int::ActionSequence.new(other_item_rep).tap do |seq|
393
- seq.add_filter(:erb, {})
394
- seq.add_filter(:donkey, {})
408
+ Nanoc::Int::ActionSequence.build(other_item_rep) do |b|
409
+ b.add_filter(:erb, {})
410
+ b.add_filter(:donkey, {})
395
411
  end
396
412
  end
397
413
 
@@ -8,6 +8,7 @@ describe Nanoc::Int::OutdatednessRules do
8
8
  Nanoc::Int::OutdatednessChecker.new(
9
9
  site: site,
10
10
  checksum_store: checksum_store,
11
+ checksums: checksums,
11
12
  dependency_store: dependency_store,
12
13
  action_sequence_store: action_sequence_store,
13
14
  action_sequences: action_sequences,
@@ -36,6 +37,15 @@ describe Nanoc::Int::OutdatednessRules do
36
37
  let(:action_sequence_store) { Nanoc::Int::ActionSequenceStore.new }
37
38
  let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: objects) }
38
39
 
40
+ let(:checksums) do
41
+ Nanoc::Int::Compiler::Stages::CalculateChecksums.new(
42
+ items: items,
43
+ layouts: layouts,
44
+ code_snippets: code_snippets,
45
+ config: config,
46
+ ).run
47
+ end
48
+
39
49
  let(:items) { Nanoc::Int::IdentifiableCollection.new(config, [item]) }
40
50
  let(:layouts) { Nanoc::Int::IdentifiableCollection.new(config) }
41
51
 
@@ -61,7 +71,7 @@ describe Nanoc::Int::OutdatednessRules do
61
71
  it { is_expected.not_to be }
62
72
  end
63
73
 
64
- context 'only non-outdated snippets' do
74
+ context 'only outdated snippets' do
65
75
  let(:code_snippet) { Nanoc::Int::CodeSnippet.new('asdf', 'lib/foo.md') }
66
76
  let(:code_snippet_old) { Nanoc::Int::CodeSnippet.new('aaaaaaaa', 'lib/foo.md') }
67
77
  let(:code_snippets) { [code_snippet] }
@@ -305,8 +315,8 @@ describe Nanoc::Int::OutdatednessRules do
305
315
  let(:rule_class) { Nanoc::Int::OutdatednessRules::RulesModified }
306
316
 
307
317
  let(:old_mem) do
308
- Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
309
- mem.add_filter(:erb, {})
318
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
319
+ b.add_filter(:erb, {})
310
320
  end
311
321
  end
312
322
 
@@ -323,9 +333,9 @@ describe Nanoc::Int::OutdatednessRules do
323
333
 
324
334
  context 'memory is different' do
325
335
  let(:new_mem) do
326
- Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
327
- mem.add_filter(:erb, {})
328
- mem.add_filter(:donkey, {})
336
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
337
+ b.add_filter(:erb, {})
338
+ b.add_filter(:donkey, {})
329
339
  end
330
340
  end
331
341
 
@@ -344,6 +354,8 @@ describe Nanoc::Int::OutdatednessRules do
344
354
  let(:stored_obj) { raise 'override me' }
345
355
  let(:new_obj) { raise 'override me' }
346
356
 
357
+ let(:items) { [new_obj] }
358
+
347
359
  shared_examples 'a document' do
348
360
  let(:stored_obj) { klass.new('a', {}, '/foo.md') }
349
361
  let(:new_obj) { stored_obj }
@@ -463,9 +475,9 @@ describe Nanoc::Int::OutdatednessRules do
463
475
 
464
476
  context 'unknown filter' do
465
477
  let(:mem) do
466
- Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
467
- mem.add_snapshot(:donkey, '/foo.md')
468
- mem.add_filter(:asdf, {})
478
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
479
+ b.add_snapshot(:donkey, '/foo.md')
480
+ b.add_filter(:asdf, {})
469
481
  end
470
482
  end
471
483
 
@@ -474,9 +486,9 @@ describe Nanoc::Int::OutdatednessRules do
474
486
 
475
487
  context 'known filter, not always outdated' do
476
488
  let(:mem) do
477
- Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
478
- mem.add_snapshot(:donkey, '/foo.md')
479
- mem.add_filter(:erb, {})
489
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
490
+ b.add_snapshot(:donkey, '/foo.md')
491
+ b.add_filter(:erb, {})
480
492
  end
481
493
  end
482
494
 
@@ -485,9 +497,9 @@ describe Nanoc::Int::OutdatednessRules do
485
497
 
486
498
  context 'known filter, always outdated' do
487
499
  let(:mem) do
488
- Nanoc::Int::ActionSequence.new(item_rep).tap do |mem|
489
- mem.add_snapshot(:donkey, '/foo.md')
490
- mem.add_filter(:xsl, {})
500
+ Nanoc::Int::ActionSequence.build(item_rep) do |b|
501
+ b.add_snapshot(:donkey, '/foo.md')
502
+ b.add_filter(:xsl, {})
491
503
  end
492
504
  end
493
505
 
@@ -167,6 +167,7 @@ describe Nanoc::CLI::Commands::ShowData, stdio: true do
167
167
  allow(site).to receive(:compiler).and_return(compiler)
168
168
  allow(compiler).to receive(:create_outdatedness_checker).and_return(outdatedness_checker)
169
169
  allow(compiler).to receive(:reps).and_return(reps)
170
+ allow(compiler).to receive(:calculate_checksums)
170
171
  end
171
172
 
172
173
  context 'not outdated' do
@@ -239,6 +240,7 @@ describe Nanoc::CLI::Commands::ShowData, stdio: true do
239
240
  allow(runner).to receive(:site).and_return(site)
240
241
  allow(site).to receive(:compiler).and_return(compiler)
241
242
  allow(compiler).to receive(:create_outdatedness_checker).and_return(outdatedness_checker)
243
+ allow(compiler).to receive(:calculate_checksums)
242
244
  end
243
245
 
244
246
  context 'not outdated' do
@@ -175,21 +175,23 @@ describe(Nanoc::RuleDSL::ActionSequenceCalculator) do
175
175
  describe '#compact_snapshots' do
176
176
  subject { action_sequence_calculator.compact_snapshots(action_sequence) }
177
177
 
178
- let(:action_sequence) { Nanoc::Int::ActionSequence.new(rep) }
179
- let(:rep) { double(:rep) }
180
-
181
- before do
182
- action_sequence.add_snapshot(:a1, nil)
183
- action_sequence.add_snapshot(:a2, '/a2.md')
184
- action_sequence.add_snapshot(:a3, nil)
185
- action_sequence.add_filter(:erb, awesomeness: 'high')
186
- action_sequence.add_snapshot(:b1, '/b1.md')
187
- action_sequence.add_snapshot(:b2, nil)
188
- action_sequence.add_snapshot(:b3, '/b3.md')
189
- action_sequence.add_filter(:erb, awesomeness: 'high')
190
- action_sequence.add_snapshot(:c, nil)
178
+ let(:action_sequence) do
179
+ Nanoc::Int::ActionSequence.build(rep) do |b|
180
+ b.add_snapshot(:a1, nil)
181
+ b.add_snapshot(:a2, '/a2.md')
182
+ b.add_snapshot(:a3, nil)
183
+ b.add_filter(:erb, awesomeness: 'high')
184
+ b.add_snapshot(:b1, '/b1.md')
185
+ b.add_snapshot(:b2, nil)
186
+ b.add_snapshot(:b3, '/b3.md')
187
+ b.add_filter(:erb, awesomeness: 'high')
188
+ b.add_snapshot(:c, nil)
189
+ end
191
190
  end
192
191
 
192
+ let(:item) { Nanoc::Int::Item.new('asdf', {}, '/foo.md') }
193
+ let(:rep) { Nanoc::Int::ItemRep.new(item, :default) }
194
+
193
195
  example do
194
196
  expect(subject[0]).to be_a(Nanoc::Int::ProcessingActions::Snapshot)
195
197
  expect(subject[0].snapshot_names).to eql(%i[a1 a2 a3])
@@ -1,8 +1,9 @@
1
1
  describe Nanoc::RuleDSL::RecordingExecutor do
2
- let(:executor) { described_class.new(action_sequence) }
2
+ let(:executor) { described_class.new(rep) }
3
3
 
4
- let(:action_sequence) { Nanoc::Int::ActionSequence.new(rep) }
5
- let(:rep) { double(:rep) }
4
+ let(:action_sequence) { executor.action_sequence }
5
+ let(:item) { Nanoc::Int::Item.new('stuff', {}, '/foo.md') }
6
+ let(:rep) { Nanoc::Int::ItemRep.new(item, :default) }
6
7
 
7
8
  describe '#filter' do
8
9
  it 'records filter call without arguments' do
@@ -84,4 +84,12 @@ class Nanoc::CLI::CleaningStreamTest < Nanoc::TestCase
84
84
  cleaning_stream << obj
85
85
  assert_equal 'Hello… world!', stream.string
86
86
  end
87
+
88
+ def test_invalid_string
89
+ s = "\x80"
90
+ stream = StringIO.new
91
+ cleaning_stream = Nanoc::CLI::CleaningStream.new(stream)
92
+ cleaning_stream << s
93
+ assert_equal "\xef\xbf\xbd", stream.string
94
+ end
87
95
  end