nanoc 4.5.2 → 4.5.3

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +7 -7
  3. data/NEWS.md +7 -0
  4. data/lib/nanoc/base/entities/item_rep.rb +0 -46
  5. data/lib/nanoc/base/repos.rb +1 -0
  6. data/lib/nanoc/base/repos/snapshot_repo.rb +60 -0
  7. data/lib/nanoc/base/services/compiler.rb +30 -17
  8. data/lib/nanoc/base/services/executor.rb +17 -8
  9. data/lib/nanoc/base/services/item_rep_writer.rb +3 -3
  10. data/lib/nanoc/base/views/item_rep_collection_view.rb +1 -1
  11. data/lib/nanoc/base/views/item_rep_view.rb +2 -2
  12. data/lib/nanoc/base/views/post_compile_item_rep_view.rb +9 -7
  13. data/lib/nanoc/base/views/view_context.rb +3 -1
  14. data/lib/nanoc/cli/commands/compile.rb +3 -3
  15. data/lib/nanoc/cli/commands/shell.rb +1 -0
  16. data/lib/nanoc/extra/parallel_collection.rb +1 -1
  17. data/lib/nanoc/helpers/capturing.rb +9 -5
  18. data/lib/nanoc/rule_dsl/action_provider.rb +2 -0
  19. data/lib/nanoc/rule_dsl/rule_memory_calculator.rb +4 -1
  20. data/lib/nanoc/spec.rb +17 -18
  21. data/lib/nanoc/version.rb +1 -1
  22. data/spec/nanoc/base/compiler_spec.rb +9 -8
  23. data/spec/nanoc/base/entities/item_rep_spec.rb +0 -222
  24. data/spec/nanoc/base/filter_spec.rb +1 -0
  25. data/spec/nanoc/base/item_rep_writer_spec.rb +9 -4
  26. data/spec/nanoc/base/repos/snapshot_repo_spec.rb +314 -0
  27. data/spec/nanoc/base/services/compiler/phases/cache_spec.rb +107 -0
  28. data/spec/nanoc/base/services/executor_spec.rb +230 -44
  29. data/spec/nanoc/base/views/document_view_spec.rb +1 -0
  30. data/spec/nanoc/base/views/item_rep_view_spec.rb +18 -5
  31. data/spec/nanoc/base/views/item_view_spec.rb +18 -7
  32. data/spec/nanoc/base/views/mutable_document_view_spec.rb +6 -5
  33. data/spec/nanoc/base/views/post_compile_item_rep_view_spec.rb +8 -3
  34. data/spec/nanoc/cli/commands/compile/file_action_printer_spec.rb +3 -3
  35. data/spec/nanoc/helpers/capturing_spec.rb +8 -5
  36. data/spec/nanoc/regressions/gh_1064_spec.rb +18 -0
  37. data/spec/nanoc/rule_dsl/rule_context_spec.rb +2 -1
  38. data/spec/nanoc/rule_dsl/rule_memory_calculator_spec.rb +15 -3
  39. data/spec/spec_helper.rb +43 -0
  40. data/test/cli/commands/test_compile.rb +1 -1
  41. data/test/filters/test_xsl.rb +1 -0
  42. data/test/helpers/test_capturing.rb +9 -2
  43. data/test/helpers/test_xml_sitemap.rb +1 -1
  44. metadata +6 -2
@@ -57,7 +57,7 @@ module Nanoc
57
57
  when Symbol
58
58
  res = @item_reps.find { |ir| ir.name == rep_name }
59
59
  res && view_class.new(res, @context)
60
- when Fixnum
60
+ when Integer
61
61
  raise ArgumentError, "expected ItemRepCollectionView#[] to be called with a symbol (you likely want `.reps[:default]` rather than `.reps[#{rep_name}]`)"
62
62
  else
63
63
  raise ArgumentError, 'expected ItemRepCollectionView#[] to be called with a symbol'
@@ -43,7 +43,7 @@ module Nanoc
43
43
  # @return [String] The content at the given snapshot.
44
44
  def compiled_content(snapshot: nil)
45
45
  @context.dependency_tracker.bounce(unwrap.item, compiled_content: true)
46
- @item_rep.compiled_content(snapshot: snapshot)
46
+ @context.snapshot_repo.compiled_content(rep: unwrap, snapshot: snapshot)
47
47
  end
48
48
 
49
49
  # Returns the item rep’s path, as used when being linked to. It starts
@@ -75,7 +75,7 @@ module Nanoc
75
75
 
76
76
  # @api private
77
77
  def binary?
78
- @item_rep.binary?
78
+ @context.snapshot_repo.get(unwrap, :last).binary?
79
79
  end
80
80
 
81
81
  def inspect
@@ -1,18 +1,20 @@
1
1
  module Nanoc
2
2
  class PostCompileItemRepView < ::Nanoc::ItemRepView
3
3
  def compiled_content(snapshot: nil)
4
- if unwrap.binary?
5
- raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(unwrap)
6
- end
7
-
8
4
  snapshot_contents = @context.compilation_context.compiled_content_cache[unwrap]
5
+
9
6
  snapshot_name = snapshot || (snapshot_contents[:pre] ? :pre : :last)
10
7
 
11
- if snapshot_contents[snapshot_name]
12
- snapshot_contents[snapshot_name].string
13
- else
8
+ unless snapshot_contents[snapshot_name]
14
9
  raise Nanoc::Int::Errors::NoSuchSnapshot.new(unwrap, snapshot_name)
15
10
  end
11
+
12
+ content = snapshot_contents[snapshot_name]
13
+ if content.binary?
14
+ raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(unwrap)
15
+ end
16
+
17
+ content.string
16
18
  end
17
19
  end
18
20
  end
@@ -5,12 +5,14 @@ module Nanoc
5
5
  attr_reader :items
6
6
  attr_reader :dependency_tracker
7
7
  attr_reader :compilation_context
8
+ attr_reader :snapshot_repo
8
9
 
9
- def initialize(reps:, items:, dependency_tracker:, compilation_context:)
10
+ def initialize(reps:, items:, dependency_tracker:, compilation_context:, snapshot_repo:)
10
11
  @reps = reps
11
12
  @items = items
12
13
  @dependency_tracker = dependency_tracker
13
14
  @compilation_context = compilation_context
15
+ @snapshot_repo = snapshot_repo
14
16
  end
15
17
  end
16
18
  end
@@ -66,8 +66,8 @@ module Nanoc::CLI::Commands
66
66
  Nanoc::Int::NotificationCenter.on(:will_write_rep, self) do |rep, path|
67
67
  old_contents[rep] = File.file?(path) ? File.read(path) : nil
68
68
  end
69
- Nanoc::Int::NotificationCenter.on(:rep_written, self) do |rep, path, _is_created, _is_modified|
70
- unless rep.binary?
69
+ Nanoc::Int::NotificationCenter.on(:rep_written, self) do |rep, binary, path, _is_created, _is_modified|
70
+ unless binary
71
71
  new_contents = File.file?(path) ? File.read(path) : nil
72
72
  if old_contents[rep] && new_contents
73
73
  generate_diff_for(path, old_contents[rep], new_contents)
@@ -326,7 +326,7 @@ module Nanoc::CLI::Commands
326
326
  @acc_durations[rep] += Time.now - @start_times[rep]
327
327
  end
328
328
 
329
- Nanoc::Int::NotificationCenter.on(:rep_written, self) do |rep, path, is_created, is_modified|
329
+ Nanoc::Int::NotificationCenter.on(:rep_written, self) do |rep, _binary, path, is_created, is_modified|
330
330
  @acc_durations[rep] += Time.now - @start_times[rep]
331
331
  duration = @acc_durations[rep]
332
332
 
@@ -35,6 +35,7 @@ module Nanoc::CLI::Commands
35
35
  items: site.items,
36
36
  dependency_tracker: Nanoc::Int::DependencyTracker::Null.new,
37
37
  compilation_context: nil,
38
+ snapshot_repo: nil,
38
39
  )
39
40
  end
40
41
 
@@ -7,7 +7,7 @@ module Nanoc::Extra
7
7
 
8
8
  include Nanoc::Int::ContractsSupport
9
9
 
10
- contract C::RespondTo[:each], C::KeywordArgs[parallelism: Fixnum] => C::Any
10
+ contract C::RespondTo[:each], C::KeywordArgs[parallelism: Integer] => C::Any
11
11
  def initialize(enum, parallelism: 2)
12
12
  @enum = enum
13
13
  @parallelism = parallelism
@@ -30,17 +30,19 @@ module Nanoc::Helpers
30
30
  content_string = capture(&block)
31
31
 
32
32
  # Get existing contents and prep for store
33
- snapshot_contents = @item.reps[:default].unwrap.snapshot_contents
33
+ snapshot_repo = @item._context.snapshot_repo
34
+ rep = @item.reps[:default].unwrap
34
35
  capture_name = "__capture_#{name}".to_sym
35
36
  old_content_string =
36
37
  case existing_behavior
37
38
  when :overwrite
38
39
  ''
39
40
  when :append
40
- c = snapshot_contents[capture_name]
41
+ c = snapshot_repo.get(rep, capture_name)
41
42
  c ? c.string : ''
42
43
  when :error
43
- if snapshot_contents[capture_name] && snapshot_contents[capture_name].string != content_string
44
+ contents = snapshot_repo.get(rep, capture_name)
45
+ if contents && contents.string != content_string
44
46
  # FIXME: get proper exception
45
47
  raise "a capture named #{name.inspect} for #{@item.identifier} already exists"
46
48
  else
@@ -52,7 +54,8 @@ module Nanoc::Helpers
52
54
  end
53
55
 
54
56
  # Store
55
- snapshot_contents[capture_name] = Nanoc::Int::TextualContent.new(old_content_string + content_string)
57
+ new_content = Nanoc::Int::TextualContent.new(old_content_string + content_string)
58
+ snapshot_repo.set(rep, capture_name, new_content)
56
59
  else # Get content
57
60
  if args.size != 2
58
61
  raise ArgumentError, 'expected 2 arguments (the item ' \
@@ -74,7 +77,8 @@ module Nanoc::Helpers
74
77
  end
75
78
  end
76
79
 
77
- content = rep.snapshot_contents["__capture_#{name}".to_sym]
80
+ snapshot_repo = @config._context.snapshot_repo
81
+ content = snapshot_repo.get(rep, "__capture_#{name}".to_sym)
78
82
  content ? content.string : nil
79
83
  end
80
84
  end
@@ -56,6 +56,7 @@ module Nanoc::RuleDSL
56
56
  items: site.items,
57
57
  dependency_tracker: dependency_tracker,
58
58
  compilation_context: site.compiler.compilation_context,
59
+ snapshot_repo: nil,
59
60
  )
60
61
  ctx = new_postprocessor_context(site, view_context)
61
62
 
@@ -73,6 +74,7 @@ module Nanoc::RuleDSL
73
74
  items: nil,
74
75
  dependency_tracker: dependency_tracker,
75
76
  compilation_context: nil,
77
+ snapshot_repo: nil,
76
78
  )
77
79
 
78
80
  Nanoc::Int::Context.new(
@@ -84,6 +84,9 @@ module Nanoc::RuleDSL
84
84
  unless rule_memory.snapshot_actions.any? { |sa| sa.snapshot_name == :last }
85
85
  executor.snapshot(:last)
86
86
  end
87
+ unless rule_memory.snapshot_actions.any? { |sa| sa.snapshot_name == :pre }
88
+ executor.snapshot(:pre)
89
+ end
87
90
 
88
91
  assign_paths_to_mem(rule_memory, rep: rep)
89
92
  end
@@ -125,7 +128,7 @@ module Nanoc::RuleDSL
125
128
  return nil if routing_rule.nil?
126
129
 
127
130
  dependency_tracker = Nanoc::Int::DependencyTracker::Null.new
128
- view_context = Nanoc::ViewContext.new(reps: nil, items: nil, dependency_tracker: dependency_tracker, compilation_context: nil)
131
+ view_context = Nanoc::ViewContext.new(reps: nil, items: nil, dependency_tracker: dependency_tracker, compilation_context: nil, snapshot_repo: nil)
129
132
  basic_path = routing_rule.apply_to(rep, executor: nil, site: @site, view_context: view_context)
130
133
  if basic_path && !basic_path.start_with?('/')
131
134
  raise PathWithoutInitialSlashError.new(rep, basic_path)
data/lib/nanoc/spec.rb CHANGED
@@ -111,6 +111,10 @@ module Nanoc
111
111
  @rule_memory[obj] = memory
112
112
  end
113
113
 
114
+ def snapshot_repo
115
+ view_context.snapshot_repo
116
+ end
117
+
114
118
  private
115
119
 
116
120
  def view_context
@@ -118,7 +122,8 @@ module Nanoc
118
122
  reps: @reps,
119
123
  items: @items,
120
124
  dependency_tracker: @dependency_tracker,
121
- compilation_context: new_site.compiler.compilation_context,
125
+ compilation_context: site.compiler.compilation_context,
126
+ snapshot_repo: site.compiler.compilation_context.snapshot_repo,
122
127
  )
123
128
  end
124
129
 
@@ -150,26 +155,20 @@ module Nanoc
150
155
  Nanoc::Int::CompilerLoader.new.load(site, action_provider: new_action_provider)
151
156
  end
152
157
 
153
- def new_site
154
- site = Nanoc::Int::Site.new(
155
- config: @config,
156
- code_snippets: [],
157
- items: @items,
158
- layouts: @layouts,
159
- )
160
- site.compiler = new_compiler_for(site)
161
- site
158
+ def site
159
+ @_site ||= begin
160
+ site = Nanoc::Int::Site.new(
161
+ config: @config,
162
+ code_snippets: [],
163
+ items: @items,
164
+ layouts: @layouts,
165
+ )
166
+ site.compiler = new_compiler_for(site)
167
+ site
168
+ end
162
169
  end
163
170
 
164
171
  def assigns
165
- site = Nanoc::Int::Site.new(
166
- config: @config,
167
- code_snippets: [],
168
- items: @items,
169
- layouts: @layouts,
170
- )
171
- site.compiler = new_compiler_for(site)
172
-
173
172
  {
174
173
  config: Nanoc::MutableConfigView.new(@config, view_context),
175
174
  item_rep: @item_rep ? Nanoc::ItemRepView.new(@item_rep, view_context) : nil,
data/lib/nanoc/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.5.2'.freeze
3
+ VERSION = '4.5.3'.freeze
4
4
  end
@@ -96,9 +96,9 @@ describe Nanoc::Int::Compiler do
96
96
  end
97
97
 
98
98
  it 'compiles individual reps' do
99
- expect { subject }.to change { rep.snapshot_contents[:last].string }
100
- .from('<%= 1 + 2 %>')
101
- .to('3')
99
+ expect { subject }.to change { compiler.snapshot_repo.get(rep, :last) }
100
+ .from(nil)
101
+ .to(some_textual_content('3'))
102
102
  end
103
103
 
104
104
  it 'removes the item rep from the outdatedness store' do
@@ -161,9 +161,10 @@ describe Nanoc::Int::Compiler do
161
161
  let(:is_outdated) { true }
162
162
 
163
163
  it 'generates expected output' do
164
- expect(rep.snapshot_contents[:last].string).to eql(item.content.string)
165
- subject
166
- expect(rep.snapshot_contents[:last].string).to eql('3')
164
+ expect { subject }
165
+ .to change { compiler.snapshot_repo.get(rep, :last) }
166
+ .from(nil)
167
+ .to(some_textual_content('3'))
167
168
  end
168
169
 
169
170
  it 'generates notifications in the proper order' do
@@ -183,14 +184,14 @@ describe Nanoc::Int::Compiler do
183
184
  end
184
185
 
185
186
  it 'generates expected output' do
186
- expect(rep.snapshot_contents[:last].string).to eql(item.content.string)
187
+ expect(compiler.snapshot_repo.get(rep, :last)).to be_nil
187
188
 
188
189
  expect { stage.send(:compile_rep, rep, is_outdated: true) }
189
190
  .to raise_error(Nanoc::Int::Errors::UnmetDependency)
190
191
  stage.send(:compile_rep, other_rep, is_outdated: true)
191
192
  stage.send(:compile_rep, rep, is_outdated: true)
192
193
 
193
- expect(rep.snapshot_contents[:last].string).to eql('other=other content')
194
+ expect(compiler.snapshot_repo.get(rep, :last).string).to eql('other=other content')
194
195
  end
195
196
 
196
197
  it 'generates notifications in the proper order' do
@@ -1,226 +1,4 @@
1
1
  describe Nanoc::Int::ItemRep do
2
2
  let(:item) { Nanoc::Int::Item.new('asdf', {}, '/foo.md') }
3
3
  let(:rep) { Nanoc::Int::ItemRep.new(item, :giraffe) }
4
-
5
- describe '#compiled_content' do
6
- let(:snapshot_name) { raise 'override me' }
7
- subject { rep.compiled_content(snapshot: snapshot_name) }
8
-
9
- shared_examples 'a non-moving snapshot with content' do
10
- context 'no snapshot def' do
11
- it 'raises' do
12
- expect { subject }.to raise_error(Nanoc::Int::Errors::NoSuchSnapshot)
13
- end
14
- end
15
-
16
- context 'snapshot def exists' do
17
- before do
18
- rep.snapshot_defs = [Nanoc::Int::SnapshotDef.new(snapshot_name)]
19
- rep.snapshot_contents = { snapshot_name => content }
20
- end
21
-
22
- context 'content is textual' do
23
- let(:content) { Nanoc::Int::TextualContent.new('hellos') }
24
- it { is_expected.to eql('hellos') }
25
- end
26
-
27
- context 'content is binary' do
28
- before { File.write('donkey.dat', 'binary data') }
29
- let(:content) { Nanoc::Int::BinaryContent.new(File.expand_path('donkey.dat')) }
30
-
31
- it 'raises' do
32
- expect { subject }.to raise_error(Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem)
33
- end
34
- end
35
- end
36
- end
37
-
38
- shared_examples 'a non-moving snapshot' do
39
- include_examples 'a non-moving snapshot with content'
40
-
41
- context 'snapshot def exists, but not content' do
42
- before do
43
- rep.snapshot_defs = [Nanoc::Int::SnapshotDef.new(snapshot_name)]
44
- rep.snapshot_contents = {}
45
- end
46
-
47
- it 'errors' do
48
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
49
- end
50
- end
51
- end
52
-
53
- shared_examples 'snapshot :last' do
54
- context 'no snapshot def' do
55
- it 'errors' do
56
- expect { subject }.to raise_error(Nanoc::Int::Errors::NoSuchSnapshot)
57
- end
58
- end
59
-
60
- context 'snapshot exists' do
61
- context 'snapshot is not final' do
62
- before do
63
- rep.snapshot_defs = [Nanoc::Int::SnapshotDef.new(snapshot_name)]
64
- end
65
-
66
- context 'snapshot content does not exist' do
67
- before do
68
- rep.snapshot_contents = {}
69
- end
70
-
71
- it 'errors' do
72
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
73
- end
74
- end
75
-
76
- context 'snapshot content exists' do
77
- context 'content is textual' do
78
- before do
79
- rep.snapshot_contents[snapshot_name] = Nanoc::Int::TextualContent.new('hellos')
80
- end
81
-
82
- context 'not compiled' do
83
- before { rep.compiled = false }
84
-
85
- it 'raises' do
86
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
87
- end
88
- end
89
-
90
- context 'compiled' do
91
- before { rep.compiled = true }
92
-
93
- it { is_expected.to eql('hellos') }
94
- end
95
- end
96
-
97
- context 'content is binary' do
98
- before do
99
- File.write('donkey.dat', 'binary data')
100
- rep.snapshot_contents[snapshot_name] = Nanoc::Int::BinaryContent.new(File.expand_path('donkey.dat'))
101
- end
102
-
103
- context 'not compiled' do
104
- before { rep.compiled = false }
105
-
106
- it 'raises' do
107
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
108
- end
109
- end
110
-
111
- context 'compiled' do
112
- before { rep.compiled = true }
113
-
114
- it 'raises' do
115
- expect { subject }.to raise_error(Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem)
116
- end
117
- end
118
- end
119
- end
120
- end
121
-
122
- context 'snapshot is final' do
123
- before do
124
- rep.snapshot_defs = [Nanoc::Int::SnapshotDef.new(snapshot_name)]
125
- end
126
-
127
- context 'snapshot content does not exist' do
128
- before do
129
- rep.snapshot_contents = {}
130
- end
131
-
132
- it 'errors' do
133
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
134
- end
135
- end
136
-
137
- context 'snapshot content exists' do
138
- context 'content is textual' do
139
- before do
140
- rep.snapshot_contents[snapshot_name] = Nanoc::Int::TextualContent.new('hellos')
141
- end
142
-
143
- context 'not compiled' do
144
- before { rep.compiled = false }
145
-
146
- it 'errors' do
147
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
148
- end
149
- end
150
-
151
- context 'compiled' do
152
- before { rep.compiled = true }
153
-
154
- it { is_expected.to eql('hellos') }
155
- end
156
- end
157
-
158
- context 'content is binary' do
159
- before do
160
- File.write('donkey.dat', 'binary data')
161
- rep.snapshot_contents[snapshot_name] = Nanoc::Int::BinaryContent.new(File.expand_path('donkey.dat'))
162
- end
163
-
164
- context 'not compiled' do
165
- before { rep.compiled = false }
166
-
167
- it 'raises' do
168
- expect { subject }.to yield_from_fiber(an_instance_of(Nanoc::Int::Errors::UnmetDependency))
169
- end
170
- end
171
-
172
- context 'compiled' do
173
- before { rep.compiled = true }
174
-
175
- it 'raises' do
176
- expect { subject }.to raise_error(Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem)
177
- end
178
- end
179
- end
180
- end
181
- end
182
- end
183
- end
184
-
185
- context 'snapshot nil' do
186
- let(:snapshot_name) { :last }
187
- subject { rep.compiled_content(snapshot: nil) }
188
- include_examples 'snapshot :last'
189
- end
190
-
191
- context 'snapshot not specified' do
192
- subject { rep.compiled_content }
193
-
194
- context 'pre exists' do
195
- before { rep.snapshot_contents[:pre] = Nanoc::Int::TextualContent.new('omg') }
196
- let(:snapshot_name) { :pre }
197
- include_examples 'a non-moving snapshot with content'
198
- end
199
-
200
- context 'pre does not exist' do
201
- let(:snapshot_name) { :last }
202
- include_examples 'snapshot :last'
203
- end
204
- end
205
-
206
- context 'snapshot :pre specified' do
207
- let(:snapshot_name) { :pre }
208
- include_examples 'a non-moving snapshot'
209
- end
210
-
211
- context 'snapshot :post specified' do
212
- let(:snapshot_name) { :post }
213
- include_examples 'a non-moving snapshot'
214
- end
215
-
216
- context 'snapshot :last specified' do
217
- let(:snapshot_name) { :last }
218
- include_examples 'snapshot :last'
219
- end
220
-
221
- context 'snapshot :donkey specified' do
222
- let(:snapshot_name) { :donkey }
223
- include_examples 'a non-moving snapshot'
224
- end
225
- end
226
4
  end