nanoc 4.4.5 → 4.4.6

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 (233) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -2
  3. data/Gemfile.lock +37 -18
  4. data/NEWS.md +6 -0
  5. data/Rakefile +8 -20
  6. data/lib/nanoc/base/entities/code_snippet.rb +0 -2
  7. data/lib/nanoc/base/entities/item_rep.rb +4 -22
  8. data/lib/nanoc/base/entities/processing_actions/snapshot.rb +9 -7
  9. data/lib/nanoc/base/entities/rule_memory.rb +15 -7
  10. data/lib/nanoc/base/entities/snapshot_def.rb +2 -8
  11. data/lib/nanoc/base/repos/store.rb +2 -28
  12. data/lib/nanoc/base/services/checksummer.rb +9 -10
  13. data/lib/nanoc/base/services/compiler.rb +14 -16
  14. data/lib/nanoc/base/services/executor.rb +2 -13
  15. data/lib/nanoc/base/views/mixins/with_reps_view_mixin.rb +1 -1
  16. data/lib/nanoc/checking/checks/external_links.rb +2 -1
  17. data/lib/nanoc/cli/commands/compile.rb +8 -14
  18. data/lib/nanoc/extra/parallel_collection.rb +57 -0
  19. data/lib/nanoc/extra.rb +1 -0
  20. data/lib/nanoc/filters/mustache.rb +1 -1
  21. data/lib/nanoc/rule_dsl/recording_executor.rb +6 -34
  22. data/lib/nanoc/rule_dsl/rule_memory_calculator.rb +42 -12
  23. data/lib/nanoc/spec.rb +1 -1
  24. data/lib/nanoc/version.rb +1 -1
  25. data/nanoc.gemspec +1 -2
  26. data/spec/contributors_spec.rb +18 -0
  27. data/spec/nanoc/base/checksummer_spec.rb +381 -0
  28. data/spec/nanoc/base/compiler_spec.rb +181 -0
  29. data/spec/nanoc/base/entities/configuration_spec.rb +49 -0
  30. data/spec/nanoc/base/entities/content_spec.rb +193 -0
  31. data/spec/nanoc/base/entities/document_spec.rb +206 -0
  32. data/spec/nanoc/base/entities/identifier_spec.rb +460 -0
  33. data/spec/nanoc/base/entities/item_rep_spec.rb +226 -0
  34. data/spec/nanoc/base/entities/item_spec.rb +3 -0
  35. data/spec/nanoc/base/entities/layout_spec.rb +3 -0
  36. data/spec/nanoc/base/entities/lazy_value_spec.rb +106 -0
  37. data/spec/nanoc/base/entities/outdatedness_status_spec.rb +113 -0
  38. data/spec/nanoc/base/entities/pattern_spec.rb +125 -0
  39. data/spec/nanoc/base/entities/processing_action_spec.rb +9 -0
  40. data/spec/nanoc/base/entities/processing_actions/filter_spec.rb +18 -0
  41. data/spec/nanoc/base/entities/processing_actions/layout_spec.rb +18 -0
  42. data/spec/nanoc/base/entities/processing_actions/snapshot_spec.rb +32 -0
  43. data/spec/nanoc/base/entities/props_spec.rb +195 -0
  44. data/spec/nanoc/base/entities/rule_memory_spec.rb +131 -0
  45. data/spec/nanoc/base/entities/site_spec.rb +73 -0
  46. data/spec/nanoc/base/feature_spec.rb +107 -0
  47. data/spec/nanoc/base/filter_spec.rb +99 -0
  48. data/spec/nanoc/base/item_rep_writer_spec.rb +131 -0
  49. data/spec/nanoc/base/plugin_registry_spec.rb +29 -0
  50. data/spec/nanoc/base/repos/checksum_store_spec.rb +133 -0
  51. data/spec/nanoc/base/repos/compiled_content_cache_spec.rb +55 -0
  52. data/spec/nanoc/base/repos/config_loader_spec.rb +243 -0
  53. data/spec/nanoc/base/repos/dependency_store_spec.rb +195 -0
  54. data/spec/nanoc/base/repos/site_loader_spec.rb +214 -0
  55. data/spec/nanoc/base/services/dependency_tracker_spec.rb +238 -0
  56. data/spec/nanoc/base/services/executor_spec.rb +495 -0
  57. data/spec/nanoc/base/services/item_rep_router_spec.rb +134 -0
  58. data/spec/nanoc/base/services/item_rep_selector_spec.rb +169 -0
  59. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +370 -0
  60. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +432 -0
  61. data/spec/nanoc/base/services/pruner_spec.rb +105 -0
  62. data/spec/nanoc/base/services/temp_filename_factory_spec.rb +87 -0
  63. data/spec/nanoc/base/views/config_view_spec.rb +96 -0
  64. data/spec/nanoc/base/views/document_view_spec.rb +332 -0
  65. data/spec/nanoc/base/views/identifiable_collection_view_spec.rb +190 -0
  66. data/spec/nanoc/base/views/item_collection_with_reps_view_spec.rb +18 -0
  67. data/spec/nanoc/base/views/item_collection_without_reps_view_spec.rb +18 -0
  68. data/spec/nanoc/base/views/item_rep_collection_view_spec.rb +143 -0
  69. data/spec/nanoc/base/views/item_rep_view_spec.rb +265 -0
  70. data/spec/nanoc/base/views/item_view_spec.rb +341 -0
  71. data/spec/nanoc/base/views/layout_collection_view_spec.rb +18 -0
  72. data/spec/nanoc/base/views/layout_view_spec.rb +14 -0
  73. data/spec/nanoc/base/views/mutable_config_view_spec.rb +16 -0
  74. data/spec/nanoc/base/views/mutable_document_view_spec.rb +92 -0
  75. data/spec/nanoc/base/views/mutable_identifiable_collection_view_spec.rb +36 -0
  76. data/spec/nanoc/base/views/mutable_item_collection_view_spec.rb +49 -0
  77. data/spec/nanoc/base/views/mutable_item_view_spec.rb +22 -0
  78. data/spec/nanoc/base/views/mutable_layout_collection_view_spec.rb +49 -0
  79. data/spec/nanoc/base/views/mutable_layout_view_spec.rb +13 -0
  80. data/spec/nanoc/base/views/post_compile_item_rep_collection_view_spec.rb +4 -0
  81. data/spec/nanoc/base/views/post_compile_item_rep_view_spec.rb +137 -0
  82. data/spec/nanoc/base/views/post_compile_item_view_spec.rb +56 -0
  83. data/spec/nanoc/cli/commands/compile/file_action_printer_spec.rb +76 -0
  84. data/spec/nanoc/cli/commands/compile/timing_recorder_spec.rb +66 -0
  85. data/spec/nanoc/cli/commands/compile_spec.rb +64 -0
  86. data/spec/nanoc/cli/commands/deploy_spec.rb +327 -0
  87. data/spec/nanoc/cli/commands/shell_spec.rb +54 -0
  88. data/spec/nanoc/cli/commands/show_data_spec.rb +126 -0
  89. data/spec/nanoc/cli/commands/show_rules_spec.rb +112 -0
  90. data/spec/nanoc/cli/commands/view_spec.rb +58 -0
  91. data/spec/nanoc/data_sources/filesystem_spec.rb +56 -0
  92. data/spec/nanoc/deploying/fog_spec.rb +193 -0
  93. data/spec/nanoc/extra/parallel_collection_spec.rb +108 -0
  94. data/spec/nanoc/filters/colorize_syntax/rouge_spec.rb +195 -0
  95. data/spec/nanoc/filters/less_spec.rb +120 -0
  96. data/spec/nanoc/helpers/blogging_spec.rb +216 -0
  97. data/spec/nanoc/helpers/breadcrumbs_spec.rb +133 -0
  98. data/spec/nanoc/helpers/capturing_spec.rb +181 -0
  99. data/spec/nanoc/helpers/child_parent_spec.rb +105 -0
  100. data/spec/nanoc/helpers/filtering_spec.rb +72 -0
  101. data/spec/nanoc/helpers/html_escape_spec.rb +35 -0
  102. data/spec/nanoc/helpers/link_to_spec.rb +275 -0
  103. data/spec/nanoc/helpers/rendering_spec.rb +141 -0
  104. data/spec/nanoc/helpers/tagging_spec.rb +104 -0
  105. data/spec/nanoc/helpers/text_spec.rb +58 -0
  106. data/spec/nanoc/integration/outdatedness_integration_spec.rb +208 -0
  107. data/spec/nanoc/regressions/gh_1015_spec.rb +17 -0
  108. data/spec/nanoc/regressions/gh_1031_spec.rb +54 -0
  109. data/spec/nanoc/regressions/gh_1035_spec.rb +33 -0
  110. data/spec/nanoc/regressions/gh_1040_spec.rb +22 -0
  111. data/spec/nanoc/regressions/gh_761_spec.rb +23 -0
  112. data/spec/nanoc/regressions/gh_767_spec.rb +19 -0
  113. data/spec/nanoc/regressions/gh_769_spec.rb +30 -0
  114. data/spec/nanoc/regressions/gh_776_spec.rb +43 -0
  115. data/spec/nanoc/regressions/gh_787_spec.rb +19 -0
  116. data/spec/nanoc/regressions/gh_795_spec.rb +19 -0
  117. data/spec/nanoc/regressions/gh_804_spec.rb +26 -0
  118. data/spec/nanoc/regressions/gh_807_spec.rb +17 -0
  119. data/spec/nanoc/regressions/gh_809_spec.rb +17 -0
  120. data/spec/nanoc/regressions/gh_813_spec.rb +22 -0
  121. data/spec/nanoc/regressions/gh_815_spec.rb +18 -0
  122. data/spec/nanoc/regressions/gh_828_spec.rb +23 -0
  123. data/spec/nanoc/regressions/gh_833_spec.rb +14 -0
  124. data/spec/nanoc/regressions/gh_841_spec.rb +15 -0
  125. data/spec/nanoc/regressions/gh_867_spec.rb +15 -0
  126. data/spec/nanoc/regressions/gh_882_spec.rb +29 -0
  127. data/spec/nanoc/regressions/gh_885_spec.rb +30 -0
  128. data/spec/nanoc/regressions/gh_891_spec.rb +26 -0
  129. data/spec/nanoc/regressions/gh_913_spec.rb +24 -0
  130. data/spec/nanoc/regressions/gh_928_spec.rb +5 -0
  131. data/spec/nanoc/regressions/gh_937_spec.rb +25 -0
  132. data/spec/nanoc/regressions/gh_942_spec.rb +21 -0
  133. data/spec/nanoc/regressions/gh_947_spec.rb +21 -0
  134. data/spec/nanoc/regressions/gh_948_spec.rb +16 -0
  135. data/spec/nanoc/regressions/gh_951_spec.rb +19 -0
  136. data/spec/nanoc/regressions/gh_954_spec.rb +33 -0
  137. data/spec/nanoc/regressions/gh_970a_spec.rb +17 -0
  138. data/spec/nanoc/regressions/gh_970b_spec.rb +50 -0
  139. data/spec/nanoc/regressions/gh_974_spec.rb +17 -0
  140. data/spec/nanoc/regressions/gh_981_spec.rb +21 -0
  141. data/spec/nanoc/rule_dsl/recording_executor_spec.rb +142 -0
  142. data/spec/nanoc/rule_dsl/rule_context_spec.rb +177 -0
  143. data/spec/nanoc/rule_dsl/rule_memory_calculator_spec.rb +233 -0
  144. data/spec/nanoc/rule_dsl/rules_collection_spec.rb +299 -0
  145. data/spec/regression_filenames_spec.rb +16 -0
  146. data/spec/spec_helper.rb +173 -0
  147. data/test/base/core_ext/array_spec.rb +2 -0
  148. data/test/base/core_ext/hash_spec.rb +2 -0
  149. data/test/base/core_ext/string_spec.rb +2 -0
  150. data/test/base/test_code_snippet.rb +2 -0
  151. data/test/base/test_compiler.rb +2 -0
  152. data/test/base/test_context.rb +4 -2
  153. data/test/base/test_data_source.rb +2 -0
  154. data/test/base/test_dependency_tracker.rb +2 -0
  155. data/test/base/test_directed_graph.rb +2 -0
  156. data/test/base/test_filter.rb +7 -5
  157. data/test/base/test_item.rb +2 -0
  158. data/test/base/test_item_array.rb +3 -1
  159. data/test/base/test_layout.rb +2 -0
  160. data/test/base/test_memoization.rb +2 -0
  161. data/test/base/test_notification_center.rb +2 -0
  162. data/test/base/test_outdatedness_checker.rb +2 -0
  163. data/test/base/test_plugin.rb +2 -0
  164. data/test/base/test_site.rb +2 -0
  165. data/test/base/test_store.rb +2 -0
  166. data/test/checking/checks/test_css.rb +2 -0
  167. data/test/checking/checks/test_external_links.rb +4 -2
  168. data/test/checking/checks/test_html.rb +2 -0
  169. data/test/checking/checks/test_internal_links.rb +5 -3
  170. data/test/checking/checks/test_mixed_content.rb +2 -0
  171. data/test/checking/checks/test_stale.rb +2 -0
  172. data/test/checking/test_check.rb +2 -0
  173. data/test/checking/test_dsl.rb +2 -0
  174. data/test/checking/test_runner.rb +2 -0
  175. data/test/cli/commands/test_check.rb +2 -0
  176. data/test/cli/commands/test_compile.rb +2 -0
  177. data/test/cli/commands/test_create_site.rb +2 -0
  178. data/test/cli/commands/test_help.rb +2 -0
  179. data/test/cli/commands/test_info.rb +2 -0
  180. data/test/cli/commands/test_prune.rb +2 -0
  181. data/test/cli/test_cleaning_stream.rb +2 -0
  182. data/test/cli/test_cli.rb +11 -9
  183. data/test/cli/test_error_handler.rb +2 -0
  184. data/test/cli/test_logger.rb +2 -0
  185. data/test/data_sources/test_filesystem.rb +8 -6
  186. data/test/data_sources/test_filesystem_tools.rb +2 -0
  187. data/test/deploying/test_fog.rb +2 -0
  188. data/test/deploying/test_rsync.rb +4 -2
  189. data/test/extra/core_ext/test_pathname.rb +2 -0
  190. data/test/extra/core_ext/test_time.rb +2 -0
  191. data/test/extra/test_link_collector.rb +2 -0
  192. data/test/extra/test_piper.rb +2 -0
  193. data/test/filters/colorize_syntax/test_coderay.rb +2 -0
  194. data/test/filters/colorize_syntax/test_common.rb +2 -0
  195. data/test/filters/colorize_syntax/test_pygmentize.rb +2 -0
  196. data/test/filters/colorize_syntax/test_pygments.rb +2 -0
  197. data/test/filters/colorize_syntax/test_simon.rb +2 -0
  198. data/test/filters/test_asciidoc.rb +2 -0
  199. data/test/filters/test_bluecloth.rb +2 -0
  200. data/test/filters/test_coffeescript.rb +2 -0
  201. data/test/filters/test_erb.rb +7 -5
  202. data/test/filters/test_erubis.rb +6 -4
  203. data/test/filters/test_haml.rb +7 -5
  204. data/test/filters/test_handlebars.rb +2 -0
  205. data/test/filters/test_kramdown.rb +2 -0
  206. data/test/filters/test_markaby.rb +2 -0
  207. data/test/filters/test_maruku.rb +2 -0
  208. data/test/filters/test_mustache.rb +4 -2
  209. data/test/filters/test_pandoc.rb +2 -0
  210. data/test/filters/test_rainpress.rb +2 -0
  211. data/test/filters/test_rdiscount.rb +2 -0
  212. data/test/filters/test_rdoc.rb +2 -0
  213. data/test/filters/test_redcarpet.rb +2 -0
  214. data/test/filters/test_redcloth.rb +2 -0
  215. data/test/filters/test_relativize_paths.rb +2 -0
  216. data/test/filters/test_rubypants.rb +2 -0
  217. data/test/filters/test_sass.rb +4 -2
  218. data/test/filters/test_slim.rb +4 -2
  219. data/test/filters/test_typogruby.rb +2 -0
  220. data/test/filters/test_uglify_js.rb +2 -0
  221. data/test/filters/test_xsl.rb +2 -0
  222. data/test/filters/test_yui_compressor.rb +5 -3
  223. data/test/helpers/test_blogging.rb +2 -0
  224. data/test/helpers/test_capturing.rb +2 -0
  225. data/test/helpers/test_link_to.rb +2 -0
  226. data/test/helpers/test_xml_sitemap.rb +2 -0
  227. data/test/rule_dsl/test_action_provider.rb +2 -0
  228. data/test/rule_dsl/test_compiler_dsl.rb +6 -4
  229. data/test/rule_dsl/test_rule.rb +2 -0
  230. data/test/rule_dsl/test_rules_collection.rb +2 -0
  231. data/test/test_gem.rb +2 -0
  232. metadata +124 -17
  233. data/test/base/test_item_rep.rb +0 -156
@@ -0,0 +1,432 @@
1
+ describe Nanoc::Int::OutdatednessRules do
2
+ describe '#apply' do
3
+ subject { rule_class.instance.apply(obj, outdatedness_checker) }
4
+
5
+ let(:obj) { item_rep }
6
+
7
+ let(:outdatedness_checker) do
8
+ Nanoc::Int::OutdatednessChecker.new(
9
+ site: site,
10
+ checksum_store: checksum_store,
11
+ dependency_store: dependency_store,
12
+ rule_memory_store: rule_memory_store,
13
+ action_provider: action_provider,
14
+ reps: reps,
15
+ )
16
+ end
17
+
18
+ let(:item_rep) { Nanoc::Int::ItemRep.new(item, :default) }
19
+ let(:item) { Nanoc::Int::Item.new('stuff', {}, '/foo.md') }
20
+
21
+ let(:site) { double(:site) }
22
+ let(:config) { Nanoc::Int::Configuration.new }
23
+ let(:code_snippets) { [] }
24
+ let(:objects) { [config] + code_snippets + [item] }
25
+
26
+ let(:action_provider) { double(:action_provider) }
27
+ let(:reps) { Nanoc::Int::ItemRepRepo.new }
28
+ let(:dependency_store) { Nanoc::Int::DependencyStore.new(dependency_store_objects) }
29
+ let(:rule_memory_store) { Nanoc::Int::RuleMemoryStore.new }
30
+ let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: objects) }
31
+
32
+ let(:dependency_store_objects) { [item] }
33
+
34
+ before do
35
+ allow(site).to receive(:code_snippets).and_return(code_snippets)
36
+ allow(site).to receive(:config).and_return(config)
37
+ end
38
+
39
+ context 'CodeSnippetsModified' do
40
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::CodeSnippetsModified }
41
+
42
+ context 'no snippets' do
43
+ let(:code_snippets) { [] }
44
+ it { is_expected.not_to be }
45
+ end
46
+
47
+ context 'only non-outdated snippets' do
48
+ let(:code_snippet) { Nanoc::Int::CodeSnippet.new('asdf', 'lib/foo.md') }
49
+ let(:code_snippets) { [code_snippet] }
50
+
51
+ before { checksum_store.add(code_snippet) }
52
+
53
+ it { is_expected.not_to be }
54
+ end
55
+
56
+ context 'only non-outdated snippets' do
57
+ let(:code_snippet) { Nanoc::Int::CodeSnippet.new('asdf', 'lib/foo.md') }
58
+ let(:code_snippet_old) { Nanoc::Int::CodeSnippet.new('aaaaaaaa', 'lib/foo.md') }
59
+ let(:code_snippets) { [code_snippet] }
60
+
61
+ before { checksum_store.add(code_snippet_old) }
62
+
63
+ it { is_expected.to be }
64
+ end
65
+ end
66
+
67
+ context 'ConfigurationModified' do
68
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::ConfigurationModified }
69
+
70
+ context 'only non-outdated snippets' do
71
+ let(:config) { Nanoc::Int::CodeSnippet.new('asdf', 'lib/foo.md') }
72
+
73
+ before { checksum_store.add(config) }
74
+
75
+ it { is_expected.not_to be }
76
+ end
77
+
78
+ context 'only non-outdated snippets' do
79
+ let(:config) { Nanoc::Int::Configuration.new }
80
+ let(:config_old) { Nanoc::Int::Configuration.new(hash: { foo: 125 }) }
81
+
82
+ before { checksum_store.add(config_old) }
83
+
84
+ it { is_expected.to be }
85
+ end
86
+ end
87
+
88
+ context 'NotWritten' do
89
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::NotWritten }
90
+
91
+ context 'no path' do
92
+ before { item_rep.paths = {} }
93
+
94
+ it { is_expected.not_to be }
95
+ end
96
+
97
+ context 'path' do
98
+ let(:path) { 'foo.txt' }
99
+
100
+ before { item_rep.raw_paths = { last: path } }
101
+
102
+ context 'not written' do
103
+ it { is_expected.to be }
104
+ end
105
+
106
+ context 'written' do
107
+ before { File.write(path, 'hello') }
108
+ it { is_expected.not_to be }
109
+ end
110
+ end
111
+ end
112
+
113
+ context 'ContentModified' do
114
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::ContentModified }
115
+
116
+ context 'item' do
117
+ let(:obj) { item }
118
+
119
+ before { reps << item_rep }
120
+
121
+ context 'no checksum available' do
122
+ it { is_expected.to be }
123
+ end
124
+
125
+ context 'checksum available and same' do
126
+ before { checksum_store.add(item) }
127
+ it { is_expected.not_to be }
128
+ end
129
+
130
+ context 'checksum available, but content different' do
131
+ let(:old_item) { Nanoc::Int::Item.new('other stuff!!!!', {}, '/foo.md') }
132
+ before { checksum_store.add(old_item) }
133
+ it { is_expected.to be }
134
+ end
135
+
136
+ context 'checksum available, but attributes different' do
137
+ let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
138
+ before { checksum_store.add(old_item) }
139
+ it { is_expected.not_to be }
140
+ end
141
+ end
142
+
143
+ context 'item rep' do
144
+ let(:obj) { item_rep }
145
+
146
+ context 'no checksum available' do
147
+ it { is_expected.to be }
148
+ end
149
+
150
+ context 'checksum available and same' do
151
+ before { checksum_store.add(item) }
152
+ it { is_expected.not_to be }
153
+ end
154
+
155
+ context 'checksum available, but content different' do
156
+ let(:old_item) { Nanoc::Int::Item.new('other stuff!!!!', {}, '/foo.md') }
157
+ before { checksum_store.add(old_item) }
158
+ it { is_expected.to be }
159
+ end
160
+
161
+ context 'checksum available, but attributes different' do
162
+ let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
163
+ before { checksum_store.add(old_item) }
164
+ it { is_expected.not_to be }
165
+ end
166
+ end
167
+ end
168
+
169
+ context 'AttributesModified' do
170
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::AttributesModified }
171
+
172
+ context 'item' do
173
+ let(:obj) { item }
174
+
175
+ before { reps << item_rep }
176
+
177
+ context 'no checksum available' do
178
+ it { is_expected.to be }
179
+ end
180
+
181
+ context 'checksum available and same' do
182
+ before { checksum_store.add(item) }
183
+ it { is_expected.not_to be }
184
+ end
185
+
186
+ context 'checksum available, but content different' do
187
+ let(:old_item) { Nanoc::Int::Item.new('other stuff!!!!', {}, '/foo.md') }
188
+ before { checksum_store.add(old_item) }
189
+ it { is_expected.not_to be }
190
+ end
191
+
192
+ context 'checksum available, but attributes different' do
193
+ let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
194
+ before { checksum_store.add(old_item) }
195
+ it { is_expected.to be }
196
+ end
197
+ end
198
+
199
+ context 'item rep' do
200
+ let(:obj) { item_rep }
201
+
202
+ context 'no checksum available' do
203
+ it { is_expected.to be }
204
+ end
205
+
206
+ context 'checksum available and same' do
207
+ before { checksum_store.add(item) }
208
+ it { is_expected.not_to be }
209
+ end
210
+
211
+ context 'checksum available, but content different' do
212
+ let(:old_item) { Nanoc::Int::Item.new('other stuff!!!!', {}, '/foo.md') }
213
+ before { checksum_store.add(old_item) }
214
+ it { is_expected.not_to be }
215
+ end
216
+
217
+ context 'checksum available, but attributes different' do
218
+ let(:old_item) { Nanoc::Int::Item.new('stuff', { greeting: 'hi' }, '/foo.md') }
219
+ before { checksum_store.add(old_item) }
220
+ it { is_expected.to be }
221
+ end
222
+ end
223
+ end
224
+
225
+ context 'RulesModified' do
226
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::RulesModified }
227
+
228
+ let(:old_mem) do
229
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
230
+ mem.add_filter(:erb, {})
231
+ end
232
+ end
233
+
234
+ before do
235
+ rule_memory_store[item_rep] = old_mem.serialize
236
+ allow(action_provider).to receive(:memory_for).with(item_rep).and_return(new_mem)
237
+ end
238
+
239
+ context 'memory is the same' do
240
+ let(:new_mem) { old_mem }
241
+ it { is_expected.not_to be }
242
+ end
243
+
244
+ context 'memory is different' do
245
+ let(:new_mem) do
246
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
247
+ mem.add_filter(:erb, {})
248
+ mem.add_filter(:donkey, {})
249
+ end
250
+ end
251
+
252
+ it { is_expected.to be }
253
+ end
254
+ end
255
+
256
+ context 'PathsModified' do
257
+ let(:rule_class) { Nanoc::Int::OutdatednessRules::PathsModified }
258
+
259
+ before do
260
+ allow(action_provider).to receive(:memory_for).with(item_rep).and_return(new_mem)
261
+ end
262
+
263
+ context 'old mem does not exist' do
264
+ let(:new_mem) do
265
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
266
+ mem.add_snapshot(:donkey, '/foo.md')
267
+ mem.add_filter(:asdf, {})
268
+ end
269
+ end
270
+
271
+ it { is_expected.to be }
272
+ end
273
+
274
+ context 'old mem exists' do
275
+ let(:old_mem) do
276
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
277
+ mem.add_filter(:erb, {})
278
+ mem.add_snapshot(:donkey, '/foo.md')
279
+ end
280
+ end
281
+
282
+ before do
283
+ rule_memory_store[item_rep] = old_mem.serialize
284
+ end
285
+
286
+ context 'paths in memory are the same' do
287
+ let(:new_mem) do
288
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
289
+ mem.add_snapshot(:donkey, '/foo.md')
290
+ mem.add_filter(:asdf, {})
291
+ end
292
+ end
293
+
294
+ it { is_expected.not_to be }
295
+ end
296
+
297
+ context 'paths in memory are different' do
298
+ let(:new_mem) do
299
+ Nanoc::Int::RuleMemory.new(item_rep).tap do |mem|
300
+ mem.add_filter(:erb, {})
301
+ mem.add_snapshot(:donkey, '/foo.md')
302
+ mem.add_filter(:donkey, {})
303
+ mem.add_snapshot(:giraffe, '/bar.md')
304
+ end
305
+ end
306
+
307
+ it { is_expected.to be }
308
+ end
309
+ end
310
+ end
311
+
312
+ describe '#{Content,Attributes}Modified' do
313
+ subject do
314
+ # TODO: remove negation
315
+ [
316
+ Nanoc::Int::OutdatednessRules::ContentModified,
317
+ Nanoc::Int::OutdatednessRules::AttributesModified,
318
+ ].map { |c| !c.instance.apply(new_obj, outdatedness_checker) }
319
+ end
320
+
321
+ let(:stored_obj) { raise 'override me' }
322
+ let(:new_obj) { raise 'override me' }
323
+
324
+ shared_examples 'a document' do
325
+ let(:stored_obj) { klass.new('a', {}, '/foo.md') }
326
+ let(:new_obj) { stored_obj }
327
+
328
+ context 'no checksum data' do
329
+ context 'not stored' do
330
+ it { is_expected.to eql([false, false]) }
331
+ end
332
+
333
+ context 'stored' do
334
+ before { checksum_store.add(stored_obj) }
335
+
336
+ context 'but content changed afterwards' do
337
+ let(:new_obj) { klass.new('aaaaaaaa', {}, '/foo.md') }
338
+ it { is_expected.to eql([false, true]) }
339
+ end
340
+
341
+ context 'but attributes changed afterwards' do
342
+ let(:new_obj) { klass.new('a', { animal: 'donkey' }, '/foo.md') }
343
+ it { is_expected.to eql([true, false]) }
344
+ end
345
+
346
+ context 'and unchanged' do
347
+ it { is_expected.to eql([true, true]) }
348
+ end
349
+ end
350
+ end
351
+
352
+ context 'checksum_data' do
353
+ let(:stored_obj) { klass.new('a', {}, '/foo.md', checksum_data: 'cs-data') }
354
+ let(:new_obj) { stored_obj }
355
+
356
+ context 'not stored' do
357
+ it { is_expected.to eql([false, false]) }
358
+ end
359
+
360
+ context 'stored' do
361
+ before { checksum_store.add(stored_obj) }
362
+
363
+ context 'but checksum data afterwards' do
364
+ let(:new_obj) { klass.new('a', {}, '/foo.md', checksum_data: 'cs-data-new') }
365
+ it { is_expected.to eql([false, false]) }
366
+ end
367
+
368
+ context 'and unchanged' do
369
+ it { is_expected.to eql([true, true]) }
370
+ end
371
+ end
372
+ end
373
+
374
+ context 'content_checksum_data' do
375
+ let(:stored_obj) { klass.new('a', {}, '/foo.md', content_checksum_data: 'cs-data') }
376
+ let(:new_obj) { stored_obj }
377
+
378
+ context 'not stored' do
379
+ it { is_expected.to eql([false, false]) }
380
+ end
381
+
382
+ context 'stored' do
383
+ before { checksum_store.add(stored_obj) }
384
+
385
+ context 'but checksum data afterwards' do
386
+ let(:new_obj) { klass.new('a', {}, '/foo.md', content_checksum_data: 'cs-data-new') }
387
+ it { is_expected.to eql([false, true]) }
388
+ end
389
+
390
+ context 'and unchanged' do
391
+ it { is_expected.to eql([true, true]) }
392
+ end
393
+ end
394
+ end
395
+
396
+ context 'attributes_checksum_data' do
397
+ let(:stored_obj) { klass.new('a', {}, '/foo.md', attributes_checksum_data: 'cs-data') }
398
+ let(:new_obj) { stored_obj }
399
+
400
+ context 'not stored' do
401
+ it { is_expected.to eql([false, false]) }
402
+ end
403
+
404
+ context 'stored' do
405
+ before { checksum_store.add(stored_obj) }
406
+
407
+ context 'but checksum data afterwards' do
408
+ let(:new_obj) { klass.new('a', {}, '/foo.md', attributes_checksum_data: 'cs-data-new') }
409
+ it { is_expected.to eql([true, false]) }
410
+ end
411
+
412
+ context 'and unchanged' do
413
+ it { is_expected.to eql([true, true]) }
414
+ end
415
+ end
416
+ end
417
+ end
418
+
419
+ context 'item' do
420
+ let(:klass) { Nanoc::Int::Item }
421
+ it_behaves_like 'a document'
422
+ end
423
+
424
+ context 'layout' do
425
+ let(:klass) { Nanoc::Int::Layout }
426
+ it_behaves_like 'a document'
427
+ end
428
+
429
+ # …
430
+ end
431
+ end
432
+ end
@@ -0,0 +1,105 @@
1
+ describe Nanoc::Pruner do
2
+ subject(:pruner) { described_class.new(config, reps, dry_run: dry_run, exclude: exclude) }
3
+
4
+ let(:config) { Nanoc::Int::Configuration.new({}) }
5
+ let(:dry_run) { false }
6
+ let(:exclude) { [] }
7
+
8
+ let(:reps) do
9
+ Nanoc::Int::ItemRepRepo.new.tap do |reps|
10
+ reps << Nanoc::Int::ItemRep.new(item, :default).tap do |rep|
11
+ rep.raw_paths = { last: 'output/asdf.html' }
12
+ end
13
+
14
+ reps << Nanoc::Int::ItemRep.new(item, :text).tap do |rep|
15
+ rep.raw_paths = { last: 'output/asdf.txt' }
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:item) { Nanoc::Int::Item.new('asdf', {}, '/a.md') }
21
+
22
+ it 'is accessible through Nanoc::Extra::Pruner' do
23
+ expect(Nanoc::Extra::Pruner).to equal(Nanoc::Pruner)
24
+ end
25
+
26
+ describe '#files_and_dirs_in' do
27
+ subject { pruner.files_and_dirs_in('output/') }
28
+
29
+ before do
30
+ FileUtils.mkdir_p('output/projects')
31
+ FileUtils.mkdir_p('output/.git')
32
+
33
+ File.write('output/asdf.html', '<p>text</p>')
34
+ File.write('output/.htaccess', 'secret stuff here')
35
+ File.write('output/projects/nanoc.html', '<p>Nanoc is v cool!!</p>')
36
+ File.write('output/.git/HEAD', 'some content here')
37
+ end
38
+
39
+ context 'nothing excluded' do
40
+ let(:exclude) { [] }
41
+
42
+ it 'returns all files' do
43
+ files = [
44
+ 'output/asdf.html',
45
+ 'output/.htaccess',
46
+ 'output/projects/nanoc.html',
47
+ 'output/.git/HEAD',
48
+ ]
49
+ expect(subject[0]).to match_array(files)
50
+ end
51
+
52
+ it 'returns all directories' do
53
+ dirs = [
54
+ 'output/',
55
+ 'output/projects',
56
+ 'output/.git',
57
+ ]
58
+ expect(subject[1]).to match_array(dirs)
59
+ end
60
+ end
61
+
62
+ context 'directory (.git) excluded' do
63
+ let(:exclude) { ['.git'] }
64
+
65
+ it 'returns all files' do
66
+ files = [
67
+ 'output/asdf.html',
68
+ 'output/.htaccess',
69
+ 'output/projects/nanoc.html',
70
+ ]
71
+ expect(subject[0]).to match_array(files)
72
+ end
73
+
74
+ it 'returns all directories' do
75
+ dirs = [
76
+ 'output/',
77
+ 'output/projects',
78
+ ]
79
+ expect(subject[1]).to match_array(dirs)
80
+ end
81
+ end
82
+
83
+ context 'file (.htaccess) excluded' do
84
+ let(:exclude) { ['.htaccess'] }
85
+
86
+ it 'returns all files' do
87
+ files = [
88
+ 'output/asdf.html',
89
+ 'output/projects/nanoc.html',
90
+ 'output/.git/HEAD',
91
+ ]
92
+ expect(subject[0]).to match_array(files)
93
+ end
94
+
95
+ it 'returns all directories' do
96
+ dirs = [
97
+ 'output/',
98
+ 'output/projects',
99
+ 'output/.git',
100
+ ]
101
+ expect(subject[1]).to match_array(dirs)
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,87 @@
1
+ describe Nanoc::Int::TempFilenameFactory do
2
+ subject(:factory) { described_class.new }
3
+
4
+ let(:prefix) { 'foo' }
5
+
6
+ describe '#create' do
7
+ it 'creates unique paths' do
8
+ path_a = subject.create(prefix)
9
+ path_b = subject.create(prefix)
10
+
11
+ expect(path_a).not_to eq(path_b)
12
+ end
13
+
14
+ it 'returns absolute paths' do
15
+ path = subject.create(prefix)
16
+
17
+ expect(path).to match(/\A\//)
18
+ end
19
+
20
+ it 'creates the containing directory' do
21
+ expect(Dir[subject.root_dir + '/**/*']).to be_empty
22
+
23
+ path = subject.create(prefix)
24
+
25
+ expect(File.directory?(File.dirname(path))).to be(true)
26
+ end
27
+
28
+ it 'reuses the same path after cleanup' do
29
+ path_a = subject.create(prefix)
30
+
31
+ subject.cleanup(prefix)
32
+
33
+ path_b = subject.create(prefix)
34
+ expect(path_a).to eq(path_b)
35
+ end
36
+
37
+ it 'does not create the file' do
38
+ path = subject.create(prefix)
39
+ expect(File.file?(path)).not_to be(true)
40
+ end
41
+ end
42
+
43
+ describe '#cleanup' do
44
+ subject { factory.cleanup(prefix) }
45
+
46
+ let!(:path) { factory.create(prefix) }
47
+
48
+ before { File.write(path, 'hello') }
49
+
50
+ def files
51
+ Dir[factory.root_dir + '/**/*'].select { |fn| File.file?(fn) }
52
+ end
53
+
54
+ it 'removes generated files' do
55
+ expect { subject }.to change { files }.from([path]).to([])
56
+ end
57
+
58
+ context 'files with other prefixes exist' do
59
+ before do
60
+ factory.create('donkey')
61
+ end
62
+
63
+ it 'does not delete root dir' do
64
+ expect(File.directory?(factory.root_dir)).to be(true)
65
+ expect { subject }.not_to change { File.directory?(factory.root_dir) }
66
+ end
67
+ end
68
+
69
+ context 'no files with other prefixes exist' do
70
+ it 'deletes root dir' do
71
+ expect { subject }.to change { File.directory?(factory.root_dir) }.from(true).to(false)
72
+ end
73
+ end
74
+ end
75
+
76
+ describe 'other instance' do
77
+ let(:other_instance) do
78
+ Nanoc::Int::TempFilenameFactory.new
79
+ end
80
+
81
+ it 'creates unique paths across instances' do
82
+ path_a = subject.create(prefix)
83
+ path_b = other_instance.create(prefix)
84
+ expect(path_a).not_to eq(path_b)
85
+ end
86
+ end
87
+ end