nanoc 4.7.4 → 4.7.5

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +19 -29
  4. data/NEWS.md +11 -0
  5. data/lib/nanoc/base/entities/identifiable_collection.rb +21 -0
  6. data/lib/nanoc/base/services/compilation_context.rb +54 -0
  7. data/lib/nanoc/base/services/compiler/stages/build_reps.rb +27 -0
  8. data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +4 -6
  9. data/lib/nanoc/base/services/compiler/stages/forget_outdated_dependencies.rb +14 -0
  10. data/lib/nanoc/base/services/compiler/stages/load_stores.rb +22 -0
  11. data/lib/nanoc/base/services/compiler/stages/postprocess.rb +16 -0
  12. data/lib/nanoc/base/services/compiler/stages/store_post_compilation_state.rb +14 -0
  13. data/lib/nanoc/base/services/compiler/stages/store_pre_compilation_state.rb +33 -0
  14. data/lib/nanoc/base/services/compiler/stages.rb +6 -0
  15. data/lib/nanoc/base/services/compiler.rb +85 -142
  16. data/lib/nanoc/base/services/compiler_loader.rb +0 -11
  17. data/lib/nanoc/base/services/outdatedness_checker.rb +19 -40
  18. data/lib/nanoc/base/services.rb +1 -0
  19. data/lib/nanoc/base/views/identifiable_collection_view.rb +1 -2
  20. data/lib/nanoc/cli/commands/compile_listeners/timing_recorder.rb +2 -2
  21. data/lib/nanoc/cli/commands/show-data.rb +14 -12
  22. data/lib/nanoc/version.rb +1 -1
  23. data/spec/nanoc/base/compiler_spec.rb +0 -5
  24. data/spec/nanoc/base/entities/identifiable_collection_spec.rb +34 -0
  25. data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +1 -1
  26. data/spec/nanoc/base/services/executor_spec.rb +1 -1
  27. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +21 -8
  28. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +6 -9
  29. data/spec/nanoc/cli/commands/show_data_spec.rb +147 -0
  30. data/spec/nanoc/integration/outdatedness_integration_spec.rb +14 -14
  31. data/spec/nanoc/integration/partial_recompilation_spec.rb +4 -4
  32. data/spec/nanoc/regressions/gh_1145_spec.rb +16 -0
  33. data/spec/nanoc/regressions/gh_970b_spec.rb +3 -3
  34. data/spec/spec_helper.rb +1 -1
  35. metadata +10 -3
  36. data/test/base/test_outdatedness_checker.rb +0 -491
@@ -1,491 +0,0 @@
1
- require 'helper'
2
-
3
- class Nanoc::Int::OutdatednessCheckerTest < Nanoc::TestCase
4
- def test_not_outdated
5
- # Compile once
6
- with_site(name: 'foo') do |site|
7
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
8
- File.open('lib/stuff.rb', 'w') { |io| io.write('$foo = 123') }
9
-
10
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
11
- site.compile
12
- end
13
-
14
- # Check
15
- with_site(name: 'foo') do |site|
16
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
17
- site.compiler.build_reps
18
- site.compiler.load_stores
19
- outdatedness_checker = site.compiler.send :outdatedness_checker
20
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
21
- assert_nil outdatedness_checker.outdatedness_reason_for(rep)
22
- end
23
- end
24
-
25
- def test_outdated_if_item_checksum_nil
26
- # Compile once
27
- with_site(name: 'foo') do |site|
28
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
29
- File.open('lib/stuff.rb', 'w') { |io| io.write('$foo = 123') }
30
-
31
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
32
- site.compile
33
- end
34
-
35
- # Delete checksums
36
- with_site(name: 'foo') do |_site|
37
- Dir['tmp/nanoc/*/checksums'].each { |fn| FileUtils.rm(fn) }
38
- end
39
-
40
- # Check
41
- with_site(name: 'foo') do |site|
42
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
43
- site.compiler.build_reps
44
- site.compiler.load_stores
45
- outdatedness_checker = site.compiler.send :outdatedness_checker
46
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
47
- assert_equal ::Nanoc::Int::OutdatednessReasons::ContentModified, outdatedness_checker.outdatedness_reason_for(rep)
48
- end
49
- end
50
-
51
- def test_outdated_if_compiled_file_doesnt_exist
52
- # Compile once
53
- with_site(name: 'foo') do |site|
54
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
55
- File.open('lib/stuff.rb', 'w') { |io| io.write('$foo = 123') }
56
-
57
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
58
- site.compile
59
- end
60
-
61
- # Delete old item
62
- FileUtils.cd('foo') do
63
- FileUtils.rm_rf('output/index.html')
64
- end
65
-
66
- # Check
67
- with_site(name: 'foo') do |site|
68
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
69
- site.compiler.build_reps
70
- site.compiler.load_stores
71
- outdatedness_checker = site.compiler.send :outdatedness_checker
72
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
73
- assert_equal ::Nanoc::Int::OutdatednessReasons::NotWritten, outdatedness_checker.outdatedness_reason_for(rep)
74
- end
75
- end
76
-
77
- def test_outdated_if_item_content_checksum_is_different
78
- # Compile once
79
- with_site(name: 'foo') do |site|
80
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
81
- File.open('content/new.html', 'w') { |io| io.write('o hello too') }
82
- File.open('lib/stuff.rb', 'w') { |io| io.write('$foo = 123') }
83
-
84
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
85
- site.compile
86
- end
87
-
88
- # Update item
89
- FileUtils.cd('foo') do
90
- File.open('content/new.html', 'w') { |io| io.write('o hello DIFFERENT!!!') }
91
- end
92
-
93
- # Check
94
- with_site(name: 'foo') do |site|
95
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
96
- site.compiler.build_reps
97
- site.compiler.load_stores
98
- outdatedness_checker = site.compiler.send :outdatedness_checker
99
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/new/' }][0]
100
- assert_equal ::Nanoc::Int::OutdatednessReasons::ContentModified, outdatedness_checker.outdatedness_reason_for(rep)
101
- end
102
- end
103
-
104
- def test_outdated_if_item_attributes_checksum_is_different
105
- # Compile once
106
- with_site(name: 'foo') do |site|
107
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
108
- File.open('content/new.html', 'w') { |io| io.write('o hello too') }
109
- File.open('lib/stuff.rb', 'w') { |io| io.write('$foo = 123') }
110
-
111
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
112
- site.compile
113
- end
114
-
115
- # Update item
116
- FileUtils.cd('foo') do
117
- File.open('content/new.html', 'w') { |io| io.write("---\ntitle: donkey\n---\no hello too") }
118
- end
119
-
120
- # Check
121
- with_site(name: 'foo') do |site|
122
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
123
- site.compiler.build_reps
124
- site.compiler.load_stores
125
- outdatedness_checker = site.compiler.send :outdatedness_checker
126
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/new/' }][0]
127
- assert_equal ::Nanoc::Int::OutdatednessReasons::AttributesModified, outdatedness_checker.outdatedness_reason_for(rep).class
128
- end
129
- end
130
-
131
- def test_outdated_if_dependent_layout_outdated
132
- # Compile once
133
- with_site(name: 'foo', compilation_rule_content: 'layout "/default/"', has_layout: true) do |site|
134
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
135
- File.open('layouts/default.html', 'w') { |io| io.write('!!! <%= yield %> !!!') }
136
-
137
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
138
- site.compile
139
- end
140
-
141
- # Change layout
142
- FileUtils.cd('foo') do
143
- File.open('layouts/default.html', 'w') { |io| io.write('!!! <%= yield %> !!! different') }
144
- end
145
-
146
- # Check
147
- with_site(name: 'foo') do |site|
148
- # FIXME: ugly fugly hack
149
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
150
- site.compiler.build_reps
151
- site.compiler.load_stores
152
-
153
- outdatedness_checker = site.compiler.send :outdatedness_checker
154
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
155
- assert_equal ::Nanoc::Int::OutdatednessReasons::DependenciesOutdated, outdatedness_checker.outdatedness_reason_for(rep)
156
- end
157
- end
158
-
159
- def test_outdated_if_dependent_item_outdated
160
- # Compile once
161
- with_site(name: 'foo', compilation_rule_content: 'filter :erb') do |site|
162
- File.open('content/a.html', 'w') do |io|
163
- io.write('<%= @items.find { |i| i.identifier == "/b/" }.compiled_content %>')
164
- end
165
- File.open('content/b.html', 'w') do |io|
166
- io.write('stuff')
167
- end
168
-
169
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
170
- site.compile
171
- end
172
-
173
- # Change item
174
- FileUtils.cd('foo') do
175
- File.open('content/b.html', 'w') do |io|
176
- io.write('stuff different!!!')
177
- end
178
- end
179
-
180
- # Check
181
- with_site(name: 'foo') do |site|
182
- # FIXME: ugly fugly hack
183
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
184
- site.compiler.build_reps
185
- site.compiler.load_stores
186
-
187
- outdatedness_checker = site.compiler.send :outdatedness_checker
188
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/a/' }][0]
189
- assert_equal ::Nanoc::Int::OutdatednessReasons::DependenciesOutdated, outdatedness_checker.outdatedness_reason_for(rep)
190
- end
191
- end
192
-
193
- def test_outdated_if_dependent_item_outdated_chained
194
- # Compile once
195
- with_site(name: 'foo', compilation_rule_content: 'filter :erb') do |site|
196
- File.open('content/a.html', 'w') do |io|
197
- io.write('<%= @items.find { |i| i.identifier == "/b/" }.compiled_content %> aaa')
198
- end
199
- File.open('content/b.html', 'w') do |io|
200
- io.write('<%= @items.find { |i| i.identifier == "/c/" }.compiled_content %> bbb')
201
- end
202
- File.open('content/c.html', 'w') do |io|
203
- io.write('stuff')
204
- end
205
-
206
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
207
- site.compile
208
- end
209
-
210
- # Change item
211
- FileUtils.cd('foo') do
212
- File.open('content/c.html', 'w') do |io|
213
- io.write('stuff different!!!')
214
- end
215
- end
216
-
217
- # Check
218
- with_site(name: 'foo') do |site|
219
- # FIXME: ugly fugly hack
220
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
221
- site.compiler.build_reps
222
- site.compiler.load_stores
223
-
224
- outdatedness_checker = site.compiler.send :outdatedness_checker
225
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/a/' }][0]
226
- assert_equal ::Nanoc::Int::OutdatednessReasons::DependenciesOutdated, outdatedness_checker.outdatedness_reason_for(rep)
227
- end
228
- end
229
-
230
- def test_outdated_if_dependent_item_removed
231
- # Compile once
232
- with_site(name: 'foo', compilation_rule_content: 'filter :erb') do |site|
233
- File.open('content/a.html', 'w') do |io|
234
- io.write('<% @items.select { |i| i.identifier != @item.identifier }.each do |i| %>')
235
- io.write(' <%= i.compiled_content %>')
236
- io.write('<% end %>')
237
- end
238
- File.open('content/b.html', 'w') do |io|
239
- io.write('stuff')
240
- end
241
-
242
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
243
- site.compile
244
- end
245
-
246
- # Delete item
247
- FileUtils.cd('foo') do
248
- FileUtils.rm_rf('content/b.html')
249
- end
250
-
251
- # Check
252
- with_site(name: 'foo') do |site|
253
- # FIXME: ugly fugly hack
254
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
255
- site.compiler.build_reps
256
- site.compiler.load_stores
257
-
258
- outdatedness_checker = site.compiler.send :outdatedness_checker
259
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/a/' }][0]
260
- assert_equal ::Nanoc::Int::OutdatednessReasons::DependenciesOutdated, outdatedness_checker.outdatedness_reason_for(rep)
261
- end
262
- end
263
-
264
- def test_outdated_if_dependent_item_added
265
- # Compile once
266
- with_site(name: 'foo', compilation_rule_content: 'filter :erb') do |site|
267
- File.open('content/a.html', 'w') do |io|
268
- io.write('<% @items.select { |i| i.identifier != @item.identifier }.each do |i| %>')
269
- io.write(' <%= i.compiled_content %>')
270
- io.write('<% end %>')
271
- end
272
- File.open('content/b.html', 'w') do |io|
273
- io.write('stuff')
274
- end
275
-
276
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
277
- site.compile
278
- end
279
-
280
- # Add item
281
- FileUtils.cd('foo') do
282
- File.open('content/z.html', 'w') do |io|
283
- io.write('moar stuff')
284
- end
285
- end
286
-
287
- # Check
288
- with_site(name: 'foo') do |site|
289
- # FIXME: ugly fugly hack
290
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
291
- site.compiler.build_reps
292
- site.compiler.load_stores
293
-
294
- outdatedness_checker = site.compiler.send :outdatedness_checker
295
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/a/' }][0]
296
- assert_equal ::Nanoc::Int::OutdatednessReasons::DependenciesOutdated, outdatedness_checker.outdatedness_reason_for(rep)
297
- end
298
- end
299
-
300
- # TODO: make sure outdatedness of non-outdated items is correct
301
-
302
- def test_outdated_if_code_snippets_outdated
303
- # Compile once
304
- with_site(name: 'foo') do |site|
305
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
306
-
307
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
308
- site.compile
309
- end
310
-
311
- # Change code
312
- FileUtils.cd('foo') do
313
- File.open('lib/moo.rb', 'w') { |io| io.write('def moo ; puts "moo" ; end') }
314
- end
315
-
316
- # Check
317
- with_site(name: 'foo') do |site|
318
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
319
- site.compiler.build_reps
320
- site.compiler.load_stores
321
- outdatedness_checker = site.compiler.send :outdatedness_checker
322
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
323
- assert_equal ::Nanoc::Int::OutdatednessReasons::CodeSnippetsModified, outdatedness_checker.outdatedness_reason_for(rep)
324
- end
325
- end
326
-
327
- def test_outdated_if_config_outdated
328
- # Compile once
329
- with_site(name: 'foo') do |site|
330
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
331
-
332
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
333
- site.compile
334
- end
335
-
336
- # Change code
337
- FileUtils.cd('foo') do
338
- File.open('nanoc.yaml', 'w') do |io|
339
- io << 'awesome: true' << "\n"
340
- io << 'string_pattern_type: legacy' << "\n"
341
- io << 'data_sources:' << "\n"
342
- io << ' -' << "\n"
343
- io << ' type: filesystem' << "\n"
344
- io << ' identifier_type: legacy' << "\n"
345
- end
346
- end
347
-
348
- # Check
349
- with_site(name: 'foo') do |site|
350
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
351
- site.compiler.build_reps
352
- site.compiler.load_stores
353
- outdatedness_checker = site.compiler.send :outdatedness_checker
354
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
355
- assert_equal ::Nanoc::Int::OutdatednessReasons::ConfigurationModified, outdatedness_checker.outdatedness_reason_for(rep)
356
- end
357
- end
358
-
359
- def test_not_outdated_if_irrelevant_rule_modified
360
- # Compile once
361
- with_site(name: 'foo') do |site|
362
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
363
-
364
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
365
- site.compile
366
- end
367
-
368
- # Change code
369
- FileUtils.cd('foo') do
370
- File.open('Rules', 'a') { |io| io.write('layout "/moo/", :haml') }
371
- end
372
-
373
- # Check
374
- with_site(name: 'foo') do |site|
375
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
376
- site.compiler.build_reps
377
- site.compiler.load_stores
378
- outdatedness_checker = site.compiler.send :outdatedness_checker
379
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
380
- assert_nil outdatedness_checker.outdatedness_reason_for(rep)
381
- end
382
- end
383
-
384
- def test_outdated_if_relevant_rule_modified
385
- # Create site
386
- with_site(name: 'foo') do |_site|
387
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
388
- File.open('Rules', 'w') do |io|
389
- io.write("compile '/' do\n")
390
- io.write(" filter :erb\n")
391
- io.write("end\n")
392
- io.write("\n")
393
- io.write("route '/' do\n")
394
- io.write(" '/index.html'\n")
395
- io.write("end\n")
396
- end
397
- end
398
-
399
- # Compile once
400
- FileUtils.cd('foo') do
401
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
402
- site.compile
403
- end
404
-
405
- # Modify rules
406
- FileUtils.cd('foo') do
407
- File.open('Rules', 'w') do |io|
408
- io.write("compile '/' do\n")
409
- io.write("end\n")
410
- io.write("\n")
411
- io.write("route '/' do\n")
412
- io.write(" '/index.html'\n")
413
- io.write("end\n")
414
- end
415
- end
416
-
417
- # Check
418
- FileUtils.cd('foo') do
419
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
420
- site.compiler.build_reps
421
- site.compiler.load_stores
422
- outdatedness_checker = site.compiler.send :outdatedness_checker
423
- rep = site.compiler.reps[site.items.find { |i| i.identifier == '/' }][0]
424
- assert_equal ::Nanoc::Int::OutdatednessReasons::RulesModified, outdatedness_checker.outdatedness_reason_for(rep)
425
- end
426
- end
427
-
428
- def test_items_in_rules_should_not_cause_outdatedness
429
- # Create site
430
- with_site(name: 'foo') do |_site|
431
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
432
- File.open('Rules', 'w') do |io|
433
- io.write("compile '/' do\n")
434
- io.write(" filter :erb, :stuff => @items\n")
435
- io.write("end\n")
436
- io.write("\n")
437
- io.write("route '/' do\n")
438
- io.write(" '/index.html'\n")
439
- io.write("end\n")
440
- end
441
- end
442
-
443
- # Compile
444
- FileUtils.cd('foo') do
445
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
446
- site.compile
447
- end
448
-
449
- # Assert not outdated
450
- FileUtils.cd('foo') do
451
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
452
- outdatedness_checker = site.compiler.outdatedness_checker
453
- site.items.each do |item|
454
- refute outdatedness_checker.outdated?(item), 'item should not be outdated'
455
- end
456
- end
457
- end
458
-
459
- def test_non_serializable_parameters_in_rules_should_be_allowed
460
- # Create site
461
- with_site(name: 'foo') do |_site|
462
- File.open('content/index.html', 'w') { |io| io.write('o hello') }
463
- File.open('Rules', 'w') do |io|
464
- io.write("compile '/' do\n")
465
- io.write(" c = Class.new {}\n")
466
- io.write(" def c.inspect ; 'I am so classy' ; end\n")
467
- io.write(" filter :erb, :stuff => c, :more => 123\n")
468
- io.write("end\n")
469
- io.write("\n")
470
- io.write("route '/' do\n")
471
- io.write(" '/index.html'\n")
472
- io.write("end\n")
473
- end
474
- end
475
-
476
- # Compile
477
- FileUtils.cd('foo') do
478
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
479
- site.compile
480
- end
481
-
482
- # Assert not outdated
483
- FileUtils.cd('foo') do
484
- site = Nanoc::Int::SiteLoader.new.new_from_cwd
485
- outdatedness_checker = site.compiler.outdatedness_checker
486
- site.items.each do |item|
487
- refute outdatedness_checker.outdated?(item), 'item should not be outdated'
488
- end
489
- end
490
- end
491
- end