nanoc 4.7.4 → 4.7.5

Sign up to get free protection for your applications and to get access to all the features.
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