nanoc 4.4.6 → 4.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,6 +16,9 @@ module Nanoc::Int
16
16
 
17
17
  action_provider ||= Nanoc::Int::ActionProvider.named(:rule_dsl).for(site)
18
18
 
19
+ outdatedness_store =
20
+ Nanoc::Int::OutdatednessStore.new(site: site, reps: item_rep_repo)
21
+
19
22
  outdatedness_checker =
20
23
  Nanoc::Int::OutdatednessChecker.new(
21
24
  site: site,
@@ -40,6 +43,7 @@ module Nanoc::Int
40
43
  outdatedness_checker: outdatedness_checker,
41
44
  reps: item_rep_repo,
42
45
  action_provider: action_provider,
46
+ outdatedness_store: outdatedness_store,
43
47
  }
44
48
 
45
49
  Nanoc::Int::Compiler.new(site, params)
@@ -82,12 +82,8 @@ module Nanoc::Int
82
82
 
83
83
  Reasons = Nanoc::Int::OutdatednessReasons
84
84
 
85
- # @param [Nanoc::Int::Site] site
86
- # @param [Nanoc::Int::ChecksumStore] checksum_store
87
- # @param [Nanoc::Int::DependencyStore] dependency_store
88
- # @param [Nanoc::Int::RuleMemoryStore] rule_memory_store
89
- # @param [Nanoc::Int::ActionProvider] action_provider
90
- # @param [Nanoc::Int::ItemRepRepo] reps
85
+ # FIXME: Replace C::Any with proper types
86
+ contract C::KeywordArgs[site: Nanoc::Int::Site, checksum_store: Nanoc::Int::ChecksumStore, dependency_store: Nanoc::Int::DependencyStore, rule_memory_store: Nanoc::Int::RuleMemoryStore, action_provider: C::Any, reps: Nanoc::Int::ItemRepRepo] => C::Any
91
87
  def initialize(site:, checksum_store:, dependency_store:, rule_memory_store:, action_provider:, reps:)
92
88
  @site = site
93
89
  @checksum_store = checksum_store
@@ -12,8 +12,6 @@ module ::Nanoc::Checking::Checks
12
12
  identifiers :external_links, :elinks
13
13
 
14
14
  def run
15
- require 'parallel'
16
-
17
15
  # Find all broken external hrefs
18
16
  # TODO: de-duplicate this (duplicated in internal links check)
19
17
  filenames = output_filenames.select { |f| File.extname(f) == '.html' && !excluded_file?(f) }
@@ -163,7 +163,7 @@ module Nanoc::DataSources
163
163
  attributes,
164
164
  identifier,
165
165
  content_checksum_data: proto_doc.content_checksum_data,
166
- attributes_checksum_data: proto_doc.attributes_checksum_data,
166
+ attributes_checksum_data: attributes_checksum_data_for(proto_doc, content_filename, meta_filename),
167
167
  )
168
168
  end
169
169
  end
@@ -171,16 +171,25 @@ module Nanoc::DataSources
171
171
  res
172
172
  end
173
173
 
174
- def attributes_for(proto_doc, content_filename, meta_filename)
175
- extra_attributes = {
174
+ def attributes_checksum_data_for(proto_doc, content_filename, meta_filename)
175
+ YAML.dump(
176
+ attributes: proto_doc.attributes_checksum_data,
177
+ extra_attributes: extra_attributes_for(content_filename, meta_filename),
178
+ )
179
+ end
180
+
181
+ def extra_attributes_for(content_filename, meta_filename)
182
+ {
176
183
  filename: content_filename,
177
184
  content_filename: content_filename,
178
185
  meta_filename: meta_filename,
179
186
  extension: content_filename ? ext_of(content_filename)[1..-1] : nil,
180
187
  mtime: mtime_of(content_filename, meta_filename),
181
188
  }
189
+ end
182
190
 
183
- extra_attributes.merge(proto_doc.attributes)
191
+ def attributes_for(proto_doc, content_filename, meta_filename)
192
+ extra_attributes_for(content_filename, meta_filename).merge(proto_doc.attributes)
184
193
  end
185
194
 
186
195
  def identifier_for(content_filename, meta_filename, dir_name)
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.4.6'.freeze
3
+ VERSION = '4.4.7'.freeze
4
4
  end
@@ -9,16 +9,18 @@ describe Nanoc::Int::Compiler do
9
9
  dependency_store: dependency_store,
10
10
  outdatedness_checker: outdatedness_checker,
11
11
  reps: reps,
12
+ outdatedness_store: outdatedness_store,
12
13
  )
13
14
  end
14
15
 
15
- let(:checksum_store) { :__irrelevant_checksum_store }
16
- let(:rule_memory_store) { :__irrelevant_rule_memory_store }
16
+ let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: items) }
17
+ let(:rule_memory_store) { Nanoc::Int::RuleMemoryStore.new }
17
18
 
18
19
  let(:dependency_store) { Nanoc::Int::DependencyStore.new(items.to_a) }
19
20
  let(:reps) { Nanoc::Int::ItemRepRepo.new }
20
21
 
21
22
  let(:outdatedness_checker) { double(:outdatedness_checker) }
23
+ let(:outdatedness_store) { Nanoc::Int::OutdatednessStore.new(site: site, reps: reps) }
22
24
  let(:action_provider) { double(:action_provider) }
23
25
 
24
26
  let(:compiled_content_cache) { Nanoc::Int::CompiledContentCache.new(items: items) }
@@ -50,10 +52,13 @@ describe Nanoc::Int::Compiler do
50
52
  end
51
53
 
52
54
  let(:memory) do
53
- [
54
- Nanoc::Int::ProcessingActions::Filter.new(:erb, {}),
55
- Nanoc::Int::ProcessingActions::Snapshot.new(:last, nil),
56
- ]
55
+ actions =
56
+ [
57
+ Nanoc::Int::ProcessingActions::Filter.new(:erb, {}),
58
+ Nanoc::Int::ProcessingActions::Snapshot.new(:last, nil),
59
+ ]
60
+
61
+ Nanoc::Int::RuleMemory.new(nil, actions: actions)
57
62
  end
58
63
 
59
64
  before do
@@ -72,7 +77,10 @@ describe Nanoc::Int::Compiler do
72
77
  end
73
78
 
74
79
  describe '#compile_reps' do
75
- subject { compiler.send(:compile_reps) }
80
+ subject do
81
+ compiler.send(:determine_outdatedness)
82
+ compiler.send(:compile_reps)
83
+ end
76
84
 
77
85
  before do
78
86
  allow(action_provider).to receive(:snapshots_defs_for).with(rep).and_return(snapshot_defs_for_rep)
@@ -93,6 +101,21 @@ describe Nanoc::Int::Compiler do
93
101
  .to('3')
94
102
  end
95
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
+
96
119
  context 'exception' do
97
120
  let(:item) { Nanoc::Int::Item.new('<%= raise "lol" %>', {}, '/hi.md') }
98
121
 
@@ -112,11 +135,28 @@ describe Nanoc::Int::Compiler do
112
135
  expect(err.unwrap.message).to eq('lol')
113
136
  end
114
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
115
153
  end
116
154
  end
117
155
 
118
156
  describe '#compile_rep' do
119
- subject { compiler.send(:compile_rep, rep, is_outdated: is_outdated) }
157
+ let(:stage) { compiler.send(:compile_reps_stage) }
158
+
159
+ subject { stage.send(:compile_rep, rep, is_outdated: is_outdated) }
120
160
 
121
161
  let(:is_outdated) { true }
122
162
 
@@ -145,10 +185,10 @@ describe Nanoc::Int::Compiler do
145
185
  it 'generates expected output' do
146
186
  expect(rep.snapshot_contents[:last].string).to eql(item.content.string)
147
187
 
148
- expect { compiler.send(:compile_rep, rep, is_outdated: true) }
188
+ expect { stage.send(:compile_rep, rep, is_outdated: true) }
149
189
  .to raise_error(Nanoc::Int::Errors::UnmetDependency)
150
- compiler.send(:compile_rep, other_rep, is_outdated: true)
151
- compiler.send(:compile_rep, rep, is_outdated: true)
190
+ stage.send(:compile_rep, other_rep, is_outdated: true)
191
+ stage.send(:compile_rep, rep, is_outdated: true)
152
192
 
153
193
  expect(rep.snapshot_contents[:last].string).to eql('other=other content')
154
194
  end
@@ -171,10 +211,10 @@ describe Nanoc::Int::Compiler do
171
211
  expect(Nanoc::Int::NotificationCenter).to receive(:post).with(:filtering_ended, rep, :erb).ordered
172
212
  expect(Nanoc::Int::NotificationCenter).to receive(:post).with(:compilation_ended, rep).ordered
173
213
 
174
- expect { compiler.send(:compile_rep, rep, is_outdated: true) }
214
+ expect { stage.send(:compile_rep, rep, is_outdated: true) }
175
215
  .to raise_error(Nanoc::Int::Errors::UnmetDependency)
176
- compiler.send(:compile_rep, other_rep, is_outdated: true)
177
- compiler.send(:compile_rep, rep, is_outdated: true)
216
+ stage.send(:compile_rep, other_rep, is_outdated: true)
217
+ stage.send(:compile_rep, rep, is_outdated: true)
178
218
  end
179
219
  end
180
220
  end
@@ -0,0 +1,100 @@
1
+ describe Nanoc::Int::OutdatednessStore do
2
+ subject(:store) { described_class.new(site: site, reps: reps) }
3
+
4
+ let(:site) { double(:site) }
5
+ let(:reps) { Nanoc::Int::ItemRepRepo.new }
6
+
7
+ let(:item) { Nanoc::Int::Item.new('foo', {}, '/foo.md') }
8
+ let(:rep) { Nanoc::Int::ItemRep.new(item, :foo) }
9
+
10
+ let(:site) do
11
+ Nanoc::Int::Site.new(
12
+ config: config,
13
+ code_snippets: code_snippets,
14
+ items: items,
15
+ layouts: layouts,
16
+ )
17
+ end
18
+
19
+ let(:config) { Nanoc::Int::Configuration.new.with_defaults }
20
+ let(:items) { [] }
21
+ let(:layouts) { [] }
22
+ let(:code_snippets) { [] }
23
+
24
+ describe '#include?, #add and #remove' do
25
+ subject { store.include?(rep) }
26
+
27
+ context 'nothing added' do
28
+ it { is_expected.not_to be }
29
+ end
30
+
31
+ context 'rep added' do
32
+ before { store.add(rep) }
33
+ it { is_expected.to be }
34
+ end
35
+
36
+ context 'rep added and removed' do
37
+ before do
38
+ store.add(rep)
39
+ store.remove(rep)
40
+ end
41
+
42
+ it { is_expected.not_to be }
43
+ end
44
+
45
+ context 'rep added, removed, and added again' do
46
+ before do
47
+ store.add(rep)
48
+ store.remove(rep)
49
+ store.add(rep)
50
+ end
51
+
52
+ it { is_expected.to be }
53
+ end
54
+ end
55
+
56
+ describe '#to_a' do
57
+ subject { store.to_a }
58
+
59
+ context 'nothing added' do
60
+ it { is_expected.to be_empty }
61
+ end
62
+
63
+ context 'one rep added' do
64
+ before { store.add(rep) }
65
+ it { is_expected.to eql([rep]) }
66
+ end
67
+ end
68
+
69
+ describe 'reloading' do
70
+ subject do
71
+ store.store
72
+ store.load
73
+ store.include?(rep)
74
+ end
75
+
76
+ context 'not added' do
77
+ context 'rep part of new reps' do
78
+ before { reps << rep }
79
+ it { is_expected.not_to be }
80
+ end
81
+
82
+ context 'rep not part of new reps' do
83
+ it { is_expected.not_to be }
84
+ end
85
+ end
86
+
87
+ context 'added' do
88
+ before { store.add(rep) }
89
+
90
+ context 'rep part of new reps' do
91
+ before { reps << rep }
92
+ it { is_expected.to be }
93
+ end
94
+
95
+ context 'rep not part of new reps' do
96
+ it { is_expected.not_to be }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -10,9 +10,22 @@ describe Nanoc::Int::OutdatednessChecker do
10
10
  )
11
11
  end
12
12
 
13
- let(:site) { double(:site) }
14
13
  let(:checksum_store) { double(:checksum_store) }
15
- let(:dependency_store) { double(:dependency_store) }
14
+
15
+ let(:dependency_store) do
16
+ Nanoc::Int::DependencyStore.new(objects)
17
+ end
18
+
19
+ let(:objects) { [item] }
20
+
21
+ let(:site) do
22
+ Nanoc::Int::Site.new(
23
+ config: config,
24
+ items: [],
25
+ layouts: [],
26
+ code_snippets: [],
27
+ )
28
+ end
16
29
 
17
30
  let(:rule_memory_store) do
18
31
  Nanoc::Int::RuleMemoryStore.new
@@ -102,10 +115,6 @@ describe Nanoc::Int::OutdatednessChecker do
102
115
  describe '#outdated_due_to_dependencies?' do
103
116
  subject { outdatedness_checker.send(:outdated_due_to_dependencies?, item) }
104
117
 
105
- let(:dependency_store) do
106
- Nanoc::Int::DependencyStore.new(objects)
107
- end
108
-
109
118
  let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: objects) }
110
119
 
111
120
  let(:other_item) { Nanoc::Int::Item.new('other stuff', {}, '/other.md') }
@@ -18,11 +18,19 @@ describe Nanoc::Int::OutdatednessRules do
18
18
  let(:item_rep) { Nanoc::Int::ItemRep.new(item, :default) }
19
19
  let(:item) { Nanoc::Int::Item.new('stuff', {}, '/foo.md') }
20
20
 
21
- let(:site) { double(:site) }
22
21
  let(:config) { Nanoc::Int::Configuration.new }
23
22
  let(:code_snippets) { [] }
24
23
  let(:objects) { [config] + code_snippets + [item] }
25
24
 
25
+ let(:site) do
26
+ Nanoc::Int::Site.new(
27
+ config: config,
28
+ items: [],
29
+ layouts: [],
30
+ code_snippets: code_snippets,
31
+ )
32
+ end
33
+
26
34
  let(:action_provider) { double(:action_provider) }
27
35
  let(:reps) { Nanoc::Int::ItemRepRepo.new }
28
36
  let(:dependency_store) { Nanoc::Int::DependencyStore.new(dependency_store_objects) }
@@ -67,15 +75,15 @@ describe Nanoc::Int::OutdatednessRules do
67
75
  context 'ConfigurationModified' do
68
76
  let(:rule_class) { Nanoc::Int::OutdatednessRules::ConfigurationModified }
69
77
 
70
- context 'only non-outdated snippets' do
71
- let(:config) { Nanoc::Int::CodeSnippet.new('asdf', 'lib/foo.md') }
78
+ context 'non-outdated' do
79
+ let(:config) { Nanoc::Int::Configuration.new }
72
80
 
73
81
  before { checksum_store.add(config) }
74
82
 
75
83
  it { is_expected.not_to be }
76
84
  end
77
85
 
78
- context 'only non-outdated snippets' do
86
+ context 'outdated' do
79
87
  let(:config) { Nanoc::Int::Configuration.new }
80
88
  let(:config_old) { Nanoc::Int::Configuration.new(hash: { foo: 125 }) }
81
89
 
@@ -1,3 +1,5 @@
1
+ require 'net/http'
2
+
1
3
  describe Nanoc::CLI::Commands::View, site: true, stdio: true do
2
4
  describe '#run' do
3
5
  def run_nanoc_cmd(cmd)
@@ -48,7 +48,19 @@ describe Nanoc::DataSources::Filesystem do
48
48
  expect(subject[0].identifier).to eq(Nanoc::Identifier.new('/bar/'))
49
49
  expect(subject[0].checksum_data).to be_nil
50
50
  expect(subject[0].content_checksum_data).to eq('test 1')
51
- expect(subject[0].attributes_checksum_data).to eq("num: 1\n")
51
+ end
52
+
53
+ it 'has the right attributes checksum data' do
54
+ cs = YAML.load(subject[0].attributes_checksum_data)
55
+
56
+ expect(cs[:attributes]).to eq("num: 1\n")
57
+ expect(cs[:extra_attributes]).to eq(
58
+ filename: 'foo/bar.html',
59
+ content_filename: 'foo/bar.html',
60
+ meta_filename: nil,
61
+ extension: 'html',
62
+ mtime: now,
63
+ )
52
64
  end
53
65
  end
54
66
  end
@@ -13,7 +13,7 @@ describe Nanoc::Extra::ParallelCollection do
13
13
  let!(:out) { [] }
14
14
 
15
15
  it 'is fast' do
16
- expect { subject }.to finish_in_under(0.2).seconds
16
+ expect { subject }.to finish_in_under(0.25).seconds
17
17
  end
18
18
 
19
19
  it 'is correct' do
@@ -66,7 +66,7 @@ describe Nanoc::Extra::ParallelCollection do
66
66
  end
67
67
 
68
68
  it 'is fast' do
69
- expect { subject }.to finish_in_under(0.2).seconds
69
+ expect { subject }.to finish_in_under(0.25).seconds
70
70
  end
71
71
 
72
72
  it 'does not leave threads lingering' do
@@ -1,9 +1,14 @@
1
1
  describe 'Outdatedness integration', site: true, stdio: true do
2
2
  context 'only attribute dependency' do
3
+ let(:time) { Time.now }
4
+
3
5
  before do
4
6
  File.write('content/foo.md', "---\ntitle: hello\n---\n\nfoo")
5
7
  File.write('content/bar.md', '<%= @items["/foo.*"][:title] %>')
6
8
 
9
+ FileUtils.touch('content/foo.md', mtime: time)
10
+ FileUtils.touch('content/bar.md', mtime: time)
11
+
7
12
  File.write('Rules', <<EOS)
8
13
  compile '/foo.*' do
9
14
  write '/foo.html'
@@ -29,6 +34,7 @@ EOS
29
34
 
30
35
  it 'shows file as outdated after modification' do
31
36
  File.write('content/bar.md', 'JUST BAR!')
37
+ FileUtils.touch('content/bar.md', mtime: time)
32
38
 
33
39
  expect { Nanoc::CLI.run(%w(show-data --no-color)) }.to(
34
40
  output(/^item \/foo\.md, rep default:\n is not outdated/).to_stdout,
@@ -40,6 +46,7 @@ EOS
40
46
 
41
47
  it 'shows file and dependencies as not outdated after content modification' do
42
48
  File.write('content/foo.md', "---\ntitle: hello\n---\n\nfoooOoooOOoooOooo")
49
+ FileUtils.touch('content/foo.md', mtime: time)
43
50
 
44
51
  expect { Nanoc::CLI.run(%w(show-data --no-color)) }.to(
45
52
  output(/^item \/foo\.md, rep default:\n is outdated: /).to_stdout,
@@ -51,6 +58,7 @@ EOS
51
58
 
52
59
  it 'shows file and dependencies as outdated after title modification' do
53
60
  File.write('content/foo.md', "---\ntitle: bye\n---\n\nfoo")
61
+ FileUtils.touch('content/foo.md', mtime: time)
54
62
 
55
63
  expect { Nanoc::CLI.run(%w(show-data --no-color)) }.to(
56
64
  output(/^item \/foo\.md, rep default:\n is outdated: /).to_stdout,