nanoc 4.6.0 → 4.6.1

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +7 -7
  3. data/NEWS.md +13 -3
  4. data/README.md +1 -1
  5. data/lib/nanoc/base/entities/context.rb +14 -2
  6. data/lib/nanoc/base/services/compiler/phases/cache.rb +32 -0
  7. data/lib/nanoc/base/services/compiler/phases/mark_done.rb +16 -0
  8. data/lib/nanoc/base/services/compiler/phases/recalculate.rb +38 -0
  9. data/lib/nanoc/base/services/compiler/phases/resume.rb +46 -0
  10. data/lib/nanoc/base/services/compiler/phases/write.rb +19 -0
  11. data/lib/nanoc/base/services/compiler/phases.rb +8 -0
  12. data/lib/nanoc/base/services/compiler/stages/cleanup.rb +37 -0
  13. data/lib/nanoc/base/services/compiler/stages/compile_reps.rb +65 -0
  14. data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +22 -0
  15. data/lib/nanoc/base/services/compiler/stages/preprocess.rb +19 -0
  16. data/lib/nanoc/base/services/compiler/stages/prune.rb +24 -0
  17. data/lib/nanoc/base/services/compiler/stages.rb +8 -0
  18. data/lib/nanoc/base/services/compiler.rb +1 -308
  19. data/lib/nanoc/base/services/item_rep_selector.rb +38 -6
  20. data/lib/nanoc/base/services.rb +3 -0
  21. data/lib/nanoc/cli/commands/compile.rb +32 -29
  22. data/lib/nanoc/data_sources/filesystem.rb +12 -4
  23. data/lib/nanoc/version.rb +1 -1
  24. data/spec/nanoc/base/compiler_spec.rb +0 -77
  25. data/spec/nanoc/base/services/compiler/stages/cleanup_spec.rb +65 -1
  26. data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +141 -0
  27. data/spec/nanoc/base/services/item_rep_selector_spec.rb +16 -1
  28. data/spec/nanoc/cli/commands/compile/timing_recorder_spec.rb +3 -3
  29. data/spec/nanoc/data_sources/filesystem_spec.rb +23 -11
  30. metadata +16 -3
@@ -72,309 +72,6 @@ module Nanoc::Int
72
72
  end
73
73
  end
74
74
 
75
- # All phases for the compilation of a single item rep. Phases will be repeated for every rep.
76
- module Phases
77
- # Provides functionality for (re)calculating the content of an item rep, without caching or
78
- # outdatedness checking.
79
- class Recalculate
80
- include Nanoc::Int::ContractsSupport
81
-
82
- def initialize(action_provider:, dependency_store:, compilation_context:)
83
- @action_provider = action_provider
84
- @dependency_store = dependency_store
85
- @compilation_context = compilation_context
86
- end
87
-
88
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Any
89
- def run(rep, is_outdated:) # rubocop:disable Lint/UnusedMethodArgument
90
- dependency_tracker = Nanoc::Int::DependencyTracker.new(@dependency_store)
91
- dependency_tracker.enter(rep.item)
92
-
93
- executor = Nanoc::Int::Executor.new(rep, @compilation_context, dependency_tracker)
94
-
95
- @compilation_context.snapshot_repo.set(rep, :last, rep.item.content)
96
-
97
- @action_provider.memory_for(rep).each do |action|
98
- case action
99
- when Nanoc::Int::ProcessingActions::Filter
100
- executor.filter(action.filter_name, action.params)
101
- when Nanoc::Int::ProcessingActions::Layout
102
- executor.layout(action.layout_identifier, action.params)
103
- when Nanoc::Int::ProcessingActions::Snapshot
104
- executor.snapshot(action.snapshot_name)
105
- else
106
- raise Nanoc::Int::Errors::InternalInconsistency, "unknown action #{action.inspect}"
107
- end
108
- end
109
- ensure
110
- dependency_tracker.exit
111
- end
112
- end
113
-
114
- # Provides functionality for (re)calculating the content of an item rep, with caching or
115
- # outdatedness checking. Delegates to s::Recalculate if outdated or no cache available.
116
- class Cache
117
- include Nanoc::Int::ContractsSupport
118
-
119
- def initialize(compiled_content_cache:, snapshot_repo:, wrapped:)
120
- @compiled_content_cache = compiled_content_cache
121
- @snapshot_repo = snapshot_repo
122
- @wrapped = wrapped
123
- end
124
-
125
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Any
126
- def run(rep, is_outdated:)
127
- if can_reuse_content_for_rep?(rep, is_outdated: is_outdated)
128
- Nanoc::Int::NotificationCenter.post(:cached_content_used, rep)
129
-
130
- @snapshot_repo.set_all(rep, @compiled_content_cache[rep])
131
- else
132
- @wrapped.run(rep, is_outdated: is_outdated)
133
- end
134
-
135
- rep.compiled = true
136
- @compiled_content_cache[rep] = @snapshot_repo.get_all(rep)
137
- end
138
-
139
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Bool
140
- def can_reuse_content_for_rep?(rep, is_outdated:)
141
- !is_outdated && !@compiled_content_cache[rep].nil?
142
- end
143
- end
144
-
145
- # Provides functionality for suspending and resuming item rep compilation (using fibers).
146
- class Resume
147
- include Nanoc::Int::ContractsSupport
148
-
149
- def initialize(wrapped:)
150
- @wrapped = wrapped
151
- end
152
-
153
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Any
154
- def run(rep, is_outdated:)
155
- fiber = fiber_for(rep, is_outdated: is_outdated)
156
- while fiber.alive?
157
- Nanoc::Int::NotificationCenter.post(:compilation_started, rep)
158
- res = fiber.resume
159
-
160
- case res
161
- when Nanoc::Int::Errors::UnmetDependency
162
- Nanoc::Int::NotificationCenter.post(:compilation_suspended, rep, res)
163
- raise(res)
164
- when Proc
165
- fiber.resume(res.call)
166
- else
167
- # TODO: raise
168
- end
169
- end
170
-
171
- Nanoc::Int::NotificationCenter.post(:compilation_ended, rep)
172
- end
173
-
174
- private
175
-
176
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => Fiber
177
- def fiber_for(rep, is_outdated:)
178
- @fibers ||= {}
179
-
180
- @fibers[rep] ||=
181
- Fiber.new do
182
- @wrapped.run(rep, is_outdated: is_outdated)
183
- @fibers.delete(rep)
184
- end
185
-
186
- @fibers[rep]
187
- end
188
- end
189
-
190
- class Write
191
- include Nanoc::Int::ContractsSupport
192
-
193
- def initialize(snapshot_repo:, wrapped:)
194
- @snapshot_repo = snapshot_repo
195
- @wrapped = wrapped
196
- end
197
-
198
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Any
199
- def run(rep, is_outdated:)
200
- @wrapped.run(rep, is_outdated: is_outdated)
201
-
202
- rep.snapshot_defs.each do |sdef|
203
- ItemRepWriter.new.write(rep, @snapshot_repo, sdef.name)
204
- end
205
- end
206
- end
207
-
208
- class MarkDone
209
- include Nanoc::Int::ContractsSupport
210
-
211
- def initialize(wrapped:, outdatedness_store:)
212
- @wrapped = wrapped
213
- @outdatedness_store = outdatedness_store
214
- end
215
-
216
- contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool] => C::Any
217
- def run(rep, is_outdated:)
218
- @wrapped.run(rep, is_outdated: is_outdated)
219
- @outdatedness_store.remove(rep)
220
- end
221
- end
222
- end
223
-
224
- module Stages
225
- class Preprocess
226
- def initialize(action_provider:, site:, dependency_store:, checksum_store:)
227
- @action_provider = action_provider
228
- @site = site
229
- @dependency_store = dependency_store
230
- @checksum_store = checksum_store
231
- end
232
-
233
- def run
234
- @action_provider.preprocess(@site)
235
-
236
- @dependency_store.objects = @site.items.to_a + @site.layouts.to_a
237
- @checksum_store.objects = @site.items.to_a + @site.layouts.to_a + @site.code_snippets + [@site.config]
238
-
239
- @site.freeze
240
- end
241
- end
242
-
243
- class Prune
244
- def initialize(config:, reps:)
245
- @config = config
246
- @reps = reps
247
- end
248
-
249
- def run
250
- if @config[:prune][:auto_prune]
251
- Nanoc::Pruner.new(@config, @reps, exclude: prune_config_exclude).run
252
- end
253
- end
254
-
255
- private
256
-
257
- def prune_config
258
- @config[:prune] || {}
259
- end
260
-
261
- def prune_config_exclude
262
- prune_config[:exclude] || {}
263
- end
264
- end
265
-
266
- class DetermineOutdatedness
267
- def initialize(reps:, outdatedness_checker:, outdatedness_store:)
268
- @reps = reps
269
- @outdatedness_checker = outdatedness_checker
270
- @outdatedness_store = outdatedness_store
271
- end
272
-
273
- def run
274
- outdated_reps_tmp = @reps.select do |r|
275
- @outdatedness_store.include?(r) || @outdatedness_checker.outdated?(r)
276
- end
277
-
278
- outdated_items = outdated_reps_tmp.map(&:item).uniq
279
- outdated_reps = Set.new(outdated_items.flat_map { |i| @reps[i] })
280
-
281
- outdated_reps.each { |r| @outdatedness_store.add(r) }
282
-
283
- yield(outdated_items)
284
- end
285
- end
286
-
287
- class CompileReps
288
- def initialize(outdatedness_store:, dependency_store:, action_provider:, compilation_context:, compiled_content_cache:)
289
- @outdatedness_store = outdatedness_store
290
- @dependency_store = dependency_store
291
- @action_provider = action_provider
292
- @compilation_context = compilation_context
293
- @compiled_content_cache = compiled_content_cache
294
- end
295
-
296
- def run
297
- selector = Nanoc::Int::ItemRepSelector.new(@outdatedness_store.to_a)
298
- selector.each do |rep|
299
- handle_errors_while(rep) { compile_rep(rep, is_outdated: @outdatedness_store.include?(rep)) }
300
- end
301
- ensure
302
- @outdatedness_store.store
303
- @compiled_content_cache.store
304
- end
305
-
306
- private
307
-
308
- def handle_errors_while(item_rep)
309
- yield
310
- rescue => e
311
- raise Nanoc::Int::Errors::CompilationError.new(e, item_rep)
312
- end
313
-
314
- def compile_rep(rep, is_outdated:)
315
- item_rep_compiler.run(rep, is_outdated: is_outdated)
316
- end
317
-
318
- def item_rep_compiler
319
- @_item_rep_compiler ||= begin
320
- recalculate_phase = Phases::Recalculate.new(
321
- action_provider: @action_provider,
322
- dependency_store: @dependency_store,
323
- compilation_context: @compilation_context,
324
- )
325
-
326
- cache_phase = Phases::Cache.new(
327
- compiled_content_cache: @compiled_content_cache,
328
- snapshot_repo: @compilation_context.snapshot_repo,
329
- wrapped: recalculate_phase,
330
- )
331
-
332
- resume_phase = Phases::Resume.new(
333
- wrapped: cache_phase,
334
- )
335
-
336
- write_phase = Phases::Write.new(
337
- snapshot_repo: @compilation_context.snapshot_repo,
338
- wrapped: resume_phase,
339
- )
340
-
341
- mark_done_phase = Phases::MarkDone.new(
342
- wrapped: write_phase,
343
- outdatedness_store: @outdatedness_store,
344
- )
345
-
346
- mark_done_phase
347
- end
348
- end
349
- end
350
-
351
- class Cleanup
352
- def initialize(config)
353
- @config = config
354
- end
355
-
356
- def run
357
- cleanup_temps(Nanoc::Filter::TMP_BINARY_ITEMS_DIR)
358
- cleanup_temps(Nanoc::Int::ItemRepWriter::TMP_TEXT_ITEMS_DIR)
359
- cleanup_unused_stores
360
- end
361
-
362
- private
363
-
364
- def cleanup_temps(dir)
365
- Nanoc::Int::TempFilenameFactory.instance.cleanup(dir)
366
- end
367
-
368
- def cleanup_unused_stores
369
- used_paths = @config.output_dirs.map { |d| Nanoc::Int::Store.tmp_path_prefix(d) }
370
- all_paths = Dir.glob('tmp/nanoc/*')
371
- (all_paths - used_paths).each do |obsolete_path|
372
- FileUtils.rm_rf(obsolete_path)
373
- end
374
- end
375
- end
376
- end
377
-
378
75
  include Nanoc::Int::ContractsSupport
379
76
 
380
77
  # @api private
@@ -431,7 +128,7 @@ module Nanoc::Int
431
128
  determine_outdatedness
432
129
  forget_dependencies_if_needed
433
130
  store
434
- compile_reps
131
+ compile_reps_stage.run
435
132
  store_output_state
436
133
  @action_provider.postprocess(@site, @reps)
437
134
  ensure
@@ -530,10 +227,6 @@ module Nanoc::Int
530
227
  @outdated_items.each { |i| @dependency_store.forget_dependencies_for(i) }
531
228
  end
532
229
 
533
- def compile_reps
534
- compile_reps_stage.run
535
- end
536
-
537
230
  # Returns all stores that can load/store data that can be used for
538
231
  # compilation.
539
232
  def stores
@@ -7,18 +7,24 @@ module Nanoc::Int
7
7
  @reps = reps
8
8
  end
9
9
 
10
+ NONE = Object.new
11
+
10
12
  def each
11
13
  graph = Nanoc::Int::DirectedGraph.new(@reps)
12
14
 
15
+ prio_dependent = Set.new
16
+ prio_in_progress = Set.new
13
17
  loop do
14
- break if graph.roots.empty?
15
- rep = graph.roots.each { |e| break e }
18
+ rep = find(graph, prio_dependent, prio_in_progress)
19
+ break if NONE.equal?(rep)
16
20
 
17
21
  begin
22
+ prio_in_progress << rep
18
23
  yield(rep)
24
+ prio_in_progress.delete(rep)
19
25
  graph.delete_vertex(rep)
20
26
  rescue => e
21
- handle_error(e, rep, graph)
27
+ handle_error(e, rep, graph, prio_dependent)
22
28
  end
23
29
  end
24
30
 
@@ -28,7 +34,32 @@ module Nanoc::Int
28
34
  end
29
35
  end
30
36
 
31
- def handle_error(e, rep, graph)
37
+ def find(graph, prio_dependent, prio_in_progress)
38
+ if graph.roots.empty?
39
+ NONE
40
+ elsif prio_dependent.any?
41
+ find_prio(graph, prio_dependent, prio_dependent, prio_in_progress)
42
+ elsif prio_in_progress.any?
43
+ find_prio(graph, prio_in_progress, prio_dependent, prio_in_progress)
44
+ else
45
+ graph.roots.each { |e| break e }
46
+ end
47
+ end
48
+
49
+ def find_prio(graph, prio, prio_dependent, prio_in_progress)
50
+ until prio.empty?
51
+ rep = prio.each { |e| break e }
52
+ if graph.roots.include?(rep)
53
+ return rep
54
+ else
55
+ prio.delete(rep)
56
+ end
57
+ end
58
+
59
+ find(graph, prio_dependent, prio_in_progress)
60
+ end
61
+
62
+ def handle_error(e, rep, graph, prio_dependent)
32
63
  actual_error =
33
64
  if e.is_a?(Nanoc::Int::Errors::CompilationError)
34
65
  e.unwrap
@@ -37,14 +68,15 @@ module Nanoc::Int
37
68
  end
38
69
 
39
70
  if actual_error.is_a?(Nanoc::Int::Errors::UnmetDependency)
40
- handle_dependency_error(actual_error, rep, graph)
71
+ handle_dependency_error(actual_error, rep, graph, prio_dependent)
41
72
  else
42
73
  raise(e)
43
74
  end
44
75
  end
45
76
 
46
- def handle_dependency_error(e, rep, graph)
77
+ def handle_dependency_error(e, rep, graph, prio_dependent)
47
78
  other_rep = e.rep
79
+ prio_dependent << other_rep
48
80
  graph.add_edge(other_rep, rep)
49
81
  unless graph.vertices.include?(other_rep)
50
82
  graph.add_vertex(other_rep)
@@ -15,4 +15,7 @@ require_relative 'services/temp_filename_factory'
15
15
  require_relative 'services/outdatedness_rule'
16
16
  require_relative 'services/outdatedness_rules'
17
17
 
18
+ require_relative 'services/compiler/phases'
19
+ require_relative 'services/compiler/stages'
20
+
18
21
  require_relative 'services/outdatedness_checker'
@@ -211,10 +211,26 @@ module Nanoc::CLI::Commands
211
211
 
212
212
  protected
213
213
 
214
+ def profiling_table
215
+ headers = ['', 'count', 'min', 'avg', 'max', 'tot']
216
+
217
+ rows = durations_per_filter.to_a.sort_by { |r| r[1] }.map do |row|
218
+ filter_name, samples = *row
219
+ count = samples.size
220
+ min = samples.min
221
+ tot = samples.reduce(0, &:+)
222
+ avg = tot / count
223
+ max = samples.max
224
+
225
+ [filter_name.to_s, count.to_s] + [min, avg, max, tot].map { |r| "#{format('%4.2f', r)}s" }
226
+ end
227
+
228
+ [headers] + rows
229
+ end
230
+
214
231
  def print_profiling_feedback
215
232
  # Get max filter length
216
- max_filter_name_length = durations_per_filter.keys.map { |k| k.to_s.size }.max
217
- return if max_filter_name_length.nil?
233
+ return if durations_per_filter.empty?
218
234
 
219
235
  # Print warning if necessary
220
236
  if @reps.any? { |r| !r.compiled? }
@@ -223,37 +239,24 @@ module Nanoc::CLI::Commands
223
239
  'some items were not compiled.'
224
240
  end
225
241
 
226
- # Print header
227
242
  puts
228
- puts ' ' * max_filter_name_length + ' | count min avg max tot'
229
- puts '-' * max_filter_name_length + '-+-----------------------------------'
243
+ print_table profiling_table
244
+ end
230
245
 
231
- durations_per_filter.to_a.sort_by { |r| r[1] }.each do |row|
232
- print_row(row, max_filter_name_length)
233
- end
246
+ def print_table(table)
247
+ lengths = table.transpose.map { |r| r.map(&:size).max }
248
+
249
+ print_row(table[0], lengths)
250
+
251
+ puts "#{'-' * lengths[0]}-+-#{lengths[1..-1].map { |length| '-' * length }.join('---')}"
252
+
253
+ table[1..-1].each { |row| print_row(row, lengths) }
234
254
  end
235
255
 
236
- def print_row(row, length)
237
- # Extract data
238
- filter_name, samples = *row
239
-
240
- # Calculate stats
241
- count = samples.size
242
- min = samples.min
243
- tot = samples.reduce(0) { |acc, elem| acc + elem }
244
- avg = tot / count
245
- max = samples.max
246
-
247
- # Format stats
248
- count = format('%4d', count)
249
- min = format('%4.2f', min)
250
- avg = format('%4.2f', avg)
251
- max = format('%4.2f', max)
252
- tot = format('%5.2f', tot)
253
-
254
- # Output stats
255
- key = format("%#{length}s", filter_name)
256
- puts "#{key} | #{count} #{min}s #{avg}s #{max}s #{tot}s"
256
+ def print_row(row, lengths)
257
+ values = row.zip(lengths).map { |text, length| text.rjust length }
258
+
259
+ puts values[0] + ' | ' + values[1..-1].join(' ')
257
260
  end
258
261
 
259
262
  def durations_per_filter
@@ -164,7 +164,7 @@ module Nanoc::DataSources
164
164
  content,
165
165
  attributes,
166
166
  identifier,
167
- content_checksum_data: proto_doc.content_checksum_data,
167
+ content_checksum_data: content_checksum_data_for(proto_doc),
168
168
  attributes_checksum_data: attributes_checksum_data_for(proto_doc, content_filename, meta_filename),
169
169
  )
170
170
  end
@@ -173,10 +173,18 @@ module Nanoc::DataSources
173
173
  res
174
174
  end
175
175
 
176
+ def content_checksum_data_for(proto_doc)
177
+ Digest::SHA1.digest(
178
+ proto_doc.content_checksum_data || '',
179
+ )
180
+ end
181
+
176
182
  def attributes_checksum_data_for(proto_doc, content_filename, meta_filename)
177
- YAML.dump(
178
- attributes: proto_doc.attributes_checksum_data,
179
- extra_attributes: extra_attributes_for(content_filename, meta_filename),
183
+ Digest::SHA1.digest(
184
+ YAML.dump(
185
+ attributes: proto_doc.attributes_checksum_data,
186
+ extra_attributes: extra_attributes_for(content_filename, meta_filename),
187
+ ),
180
188
  )
181
189
  end
182
190
 
data/lib/nanoc/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.6.0'.freeze
3
+ VERSION = '4.6.1'.freeze
4
4
  end
@@ -76,83 +76,6 @@ describe Nanoc::Int::Compiler do
76
76
  allow(action_provider).to receive(:memory_for).with(other_rep).and_return(memory)
77
77
  end
78
78
 
79
- describe '#compile_reps' do
80
- subject do
81
- compiler.send(:determine_outdatedness)
82
- compiler.send(:compile_reps)
83
- end
84
-
85
- before do
86
- allow(action_provider).to receive(:snapshots_defs_for).with(rep).and_return(snapshot_defs_for_rep)
87
- allow(action_provider).to receive(:snapshots_defs_for).with(other_rep).and_return(snapshot_defs_for_rep)
88
- end
89
-
90
- let(:snapshot_defs_for_rep) do
91
- [Nanoc::Int::SnapshotDef.new(:last)]
92
- end
93
-
94
- let(:snapshot_defs_for_other_rep) do
95
- [Nanoc::Int::SnapshotDef.new(:last)]
96
- end
97
-
98
- it 'compiles individual reps' do
99
- expect { subject }.to change { compiler.snapshot_repo.get(rep, :last) }
100
- .from(nil)
101
- .to(some_textual_content('3'))
102
- end
103
-
104
- it 'removes the item rep from the outdatedness store' do
105
- expect(compiler.outdatedness_store.include?(rep)).not_to be
106
- expect { subject }.not_to change { compiler.outdatedness_store.include?(rep) }
107
- end
108
-
109
- context 'rep in outdatedness store' do
110
- before do
111
- compiler.outdatedness_store.add(rep)
112
- end
113
-
114
- it 'removes the item rep from the outdatedness store' do
115
- expect { subject }.to change { compiler.outdatedness_store.include?(rep) }.from(true).to(false)
116
- end
117
- end
118
-
119
- context 'exception' do
120
- let(:item) { Nanoc::Int::Item.new('<%= raise "lol" %>', {}, '/hi.md') }
121
-
122
- it 'wraps exception' do
123
- expect { subject }.to raise_error(Nanoc::Int::Errors::CompilationError)
124
- end
125
-
126
- it 'contains the right item rep in the wrapped exception' do
127
- expect { subject }.to raise_error do |err|
128
- expect(err.item_rep).to eql(rep)
129
- end
130
- end
131
-
132
- it 'contains the right wrapped exception' do
133
- expect { subject }.to raise_error do |err|
134
- expect(err.unwrap).to be_a(RuntimeError)
135
- expect(err.unwrap.message).to eq('lol')
136
- end
137
- end
138
-
139
- it 'adds the item rep to the outdatedness store' do
140
- expect { subject rescue nil }.to change { compiler.outdatedness_store.include?(rep) }.from(false).to(true)
141
- end
142
-
143
- context 'rep in outdatedness store' do
144
- before do
145
- compiler.outdatedness_store.add(rep)
146
- end
147
-
148
- it 'keeps the item rep in the outdatedness store' do
149
- expect(compiler.outdatedness_store.include?(rep)).to be
150
- expect { subject rescue nil }.not_to change { compiler.outdatedness_store.include?(rep) }
151
- end
152
- end
153
- end
154
- end
155
-
156
79
  describe '#compile_rep' do
157
80
  let(:stage) { compiler.send(:compile_reps_stage) }
158
81
 
@@ -8,7 +8,71 @@ describe Nanoc::Int::Compiler::Stages::Cleanup do
8
8
  describe '#run' do
9
9
  subject { stage.run }
10
10
 
11
- example do
11
+ it 'removes temporary binary items' do
12
+ a = Nanoc::Int::TempFilenameFactory.instance.create(Nanoc::Filter::TMP_BINARY_ITEMS_DIR)
13
+ File.write(a, 'hello there')
14
+
15
+ expect { subject }
16
+ .to change { File.file?(a) }
17
+ .from(true).to(false)
18
+ end
19
+
20
+ it 'removes temporary textual items' do
21
+ a = Nanoc::Int::TempFilenameFactory.instance.create(Nanoc::Int::ItemRepWriter::TMP_TEXT_ITEMS_DIR)
22
+ File.write(a, 'hello there')
23
+
24
+ expect { subject }
25
+ .to change { File.file?(a) }
26
+ .from(true).to(false)
27
+ end
28
+
29
+ shared_examples 'an old store' do
30
+ it 'removes the old store' do
31
+ FileUtils.mkdir_p('tmp')
32
+ File.write('tmp/' + store_name, 'stuff')
33
+
34
+ expect { subject }
35
+ .to change { File.file?('tmp/' + store_name) }
36
+ .from(true).to(false)
37
+ end
38
+ end
39
+
40
+ context 'tmp/checksums' do
41
+ let(:store_name) { 'checksums' }
42
+ it_behaves_like 'an old store'
43
+ end
44
+
45
+ context 'tmp/compiled_content' do
46
+ let(:store_name) { 'compiled_content' }
47
+ it_behaves_like 'an old store'
48
+ end
49
+
50
+ context 'tmp/dependencies' do
51
+ let(:store_name) { 'dependencies' }
52
+ it_behaves_like 'an old store'
53
+ end
54
+
55
+ context 'tmp/outdatedness' do
56
+ let(:store_name) { 'outdatedness' }
57
+ it_behaves_like 'an old store'
58
+ end
59
+
60
+ context 'tmp/rule_memory' do
61
+ let(:store_name) { 'rule_memory' }
62
+ it_behaves_like 'an old store'
63
+ end
64
+
65
+ context 'tmp/somethingelse' do
66
+ it 'does not removes the store' do
67
+ FileUtils.mkdir_p('tmp')
68
+ File.write('tmp/somethingelse', 'stuff')
69
+
70
+ expect { subject }
71
+ .not_to change { File.file?('tmp/somethingelse') }
72
+ end
73
+ end
74
+
75
+ it 'removes stores for unused output paths' do
12
76
  FileUtils.mkdir_p('tmp/nanoc/2f0692fb1a1d')
13
77
  FileUtils.mkdir_p('tmp/nanoc/1a2195bfef6c')
14
78
  FileUtils.mkdir_p('tmp/nanoc/1029d67644815')