nanoc 4.8.10 → 4.8.11
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/NEWS.md +7 -0
- data/lib/nanoc.rb +11 -6
- data/lib/nanoc/base.rb +1 -0
- data/lib/nanoc/base/changes_stream.rb +53 -0
- data/lib/nanoc/base/contracts_support.rb +0 -2
- data/lib/nanoc/base/feature.rb +3 -0
- data/lib/nanoc/base/memoization.rb +0 -2
- data/lib/nanoc/base/repos/aggregate_data_source.rb +8 -0
- data/lib/nanoc/base/repos/data_source.rb +12 -0
- data/lib/nanoc/base/repos/in_mem_data_source.rb +10 -1
- data/lib/nanoc/base/repos/prefixed_data_source.rb +8 -0
- data/lib/nanoc/base/repos/site_loader.rb +11 -7
- data/lib/nanoc/base/services/compiler.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/postprocess.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/preprocess.rb +1 -1
- data/lib/nanoc/base/services/pruner.rb +0 -2
- data/lib/nanoc/base/services/temp_filename_factory.rb +0 -2
- data/lib/nanoc/checking/checks/external_links.rb +0 -5
- data/lib/nanoc/checking/checks/internal_links.rb +0 -2
- data/lib/nanoc/checking/checks/stale.rb +0 -2
- data/lib/nanoc/cli.rb +7 -1
- data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +0 -3
- data/lib/nanoc/cli/commands/live.rb +30 -0
- data/lib/nanoc/cli/commands/view.rb +4 -5
- data/lib/nanoc/cli/error_handler.rb +52 -36
- data/lib/nanoc/cli/logger.rb +0 -2
- data/lib/nanoc/cli/stack_trace_writer.rb +50 -0
- data/lib/nanoc/data_sources/filesystem.rb +25 -0
- data/lib/nanoc/extra.rb +1 -0
- data/lib/nanoc/extra/jruby_nokogiri_warner.rb +0 -2
- data/lib/nanoc/extra/link_collector.rb +0 -2
- data/lib/nanoc/extra/live_recompiler.rb +131 -0
- data/lib/nanoc/extra/parallel_collection.rb +0 -2
- data/lib/nanoc/extra/piper.rb +0 -2
- data/lib/nanoc/filters/relativize_paths.rb +8 -7
- data/lib/nanoc/helpers/link_to.rb +0 -2
- data/lib/nanoc/rule_dsl/action_provider.rb +2 -2
- data/lib/nanoc/version.rb +1 -1
- data/nanoc.gemspec +15 -4
- data/nanoc.manifest +545 -0
- data/spec/manifest_spec.rb +22 -0
- data/spec/nanoc/base/changes_stream_spec.rb +45 -0
- data/spec/nanoc/base/checksummer_spec.rb +0 -2
- data/spec/nanoc/base/directed_graph_spec.rb +66 -0
- data/spec/nanoc/base/entities/code_snippet_spec.rb +9 -0
- data/spec/nanoc/base/entities/context_spec.rb +26 -0
- data/spec/nanoc/base/entities/identifiable_collection_spec.rb +53 -0
- data/spec/nanoc/base/repos/aggregate_data_source_spec.rb +87 -0
- data/spec/nanoc/base/repos/data_source_spec.rb +95 -0
- data/spec/nanoc/base/repos/in_mem_data_source_spec.rb +39 -0
- data/spec/nanoc/base/repos/prefixed_data_source_spec.rb +39 -0
- data/spec/nanoc/cli/error_handler_spec.rb +43 -0
- data/spec/nanoc/cli/stack_trace_writer_spec.rb +156 -0
- data/spec/nanoc/data_sources/filesystem_spec.rb +46 -0
- data/spec/nanoc/extra/live_recompiler_spec.rb +129 -0
- data/spec/nanoc/helpers/blogging_spec.rb +1 -1
- data/spec/spec_helper.rb +60 -0
- data/test/base/test_compiler.rb +11 -11
- data/test/cli/test_cli.rb +0 -1
- data/test/cli/test_error_handler.rb +4 -5
- data/test/filters/test_relativize_paths.rb +30 -0
- data/test/filters/test_sass.rb +3 -3
- data/test/rule_dsl/test_compiler_dsl.rb +2 -2
- metadata +39 -43
- data/.github/CONTRIBUTING.md +0 -17
- data/.github/ISSUE_TEMPLATE.md +0 -23
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -18
- data/.gitignore +0 -10
- data/.travis.yml +0 -27
- data/Gemfile +0 -73
- data/Guardfile +0 -5
- data/scripts/release +0 -95
- data/test/base/test_code_snippet.rb +0 -17
- data/test/base/test_context.rb +0 -35
- data/test/base/test_data_source.rb +0 -60
- data/test/base/test_directed_graph.rb +0 -56
- data/test/base/test_item_array.rb +0 -37
@@ -20,7 +20,7 @@ module Nanoc::CLI::Commands
|
|
20
20
|
load_adsf
|
21
21
|
require 'rack'
|
22
22
|
|
23
|
-
|
23
|
+
config = Nanoc::Int::ConfigLoader.new.new_from_cwd
|
24
24
|
|
25
25
|
# Set options
|
26
26
|
options_for_rack = {
|
@@ -40,16 +40,15 @@ module Nanoc::CLI::Commands
|
|
40
40
|
end
|
41
41
|
|
42
42
|
# Build app
|
43
|
-
site = @site
|
44
43
|
app = Rack::Builder.new do
|
45
44
|
use Rack::CommonLogger
|
46
45
|
use Rack::ShowExceptions
|
47
46
|
use Rack::Lint
|
48
47
|
use Rack::Head
|
49
48
|
use Adsf::Rack::IndexFileFinder,
|
50
|
-
root:
|
51
|
-
index_filenames:
|
52
|
-
run Rack::File.new(
|
49
|
+
root: config[:output_dir],
|
50
|
+
index_filenames: config[:index_filenames]
|
51
|
+
run Rack::File.new(config[:output_dir])
|
53
52
|
end.to_app
|
54
53
|
|
55
54
|
# Print a link
|
@@ -64,13 +64,16 @@ module Nanoc::CLI
|
|
64
64
|
|
65
65
|
# Run
|
66
66
|
yield
|
67
|
-
rescue Nanoc::Int::Errors::GenericTrivial => e
|
68
|
-
$stderr.puts "Error: #{e.message}"
|
69
|
-
exit(1)
|
70
67
|
rescue Interrupt
|
71
68
|
exit(1)
|
72
69
|
rescue StandardError, ScriptError => e
|
73
|
-
|
70
|
+
if trivial?(e)
|
71
|
+
$stderr.puts "Error: #{e.message}"
|
72
|
+
resolution = resolution_for(e)
|
73
|
+
$stderr.puts resolution if resolution
|
74
|
+
else
|
75
|
+
print_error(e)
|
76
|
+
end
|
74
77
|
exit(1)
|
75
78
|
end
|
76
79
|
|
@@ -109,17 +112,21 @@ module Nanoc::CLI
|
|
109
112
|
#
|
110
113
|
# @return [void]
|
111
114
|
def write_compact_error(error, stream)
|
112
|
-
# Header
|
113
115
|
stream.puts
|
114
116
|
stream.puts 'Captain! We’ve been hit!'
|
115
117
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
if forwards_stack_trace?
|
119
|
+
write_stack_trace(stream, error)
|
120
|
+
write_error_message(stream, error)
|
121
|
+
write_item_rep(stream, error)
|
122
|
+
else
|
123
|
+
write_error_message(stream, error)
|
124
|
+
write_item_rep(stream, error)
|
125
|
+
write_stack_trace(stream, error)
|
126
|
+
end
|
120
127
|
|
121
|
-
|
122
|
-
|
128
|
+
stream.puts
|
129
|
+
stream.puts 'A detailed crash log has been written to ./crash.log.'
|
123
130
|
end
|
124
131
|
|
125
132
|
# Writes a verbose representation of the error on the given stream.
|
@@ -130,10 +137,8 @@ module Nanoc::CLI
|
|
130
137
|
#
|
131
138
|
# @return [void]
|
132
139
|
def write_verbose_error(error, stream)
|
133
|
-
# Header
|
134
140
|
stream.puts "Crashlog created at #{Time.now}"
|
135
141
|
|
136
|
-
# Sections
|
137
142
|
write_error_message(stream, error, verbose: true)
|
138
143
|
write_item_rep(stream, error, verbose: true)
|
139
144
|
write_stack_trace(stream, error, verbose: true)
|
@@ -144,6 +149,14 @@ module Nanoc::CLI
|
|
144
149
|
write_load_paths(stream, verbose: true)
|
145
150
|
end
|
146
151
|
|
152
|
+
# @api private
|
153
|
+
def forwards_stack_trace?
|
154
|
+
feature_enabled = Nanoc::Feature.enabled?(Nanoc::Feature::SENSIBLE_STACK_TRACES)
|
155
|
+
ruby_2_5_used = ruby_version.start_with?('2.5')
|
156
|
+
|
157
|
+
feature_enabled || ruby_2_5_used
|
158
|
+
end
|
159
|
+
|
147
160
|
protected
|
148
161
|
|
149
162
|
# @return [Hash<String, Array>] A hash containing the gem names as keys and gem versions as value
|
@@ -191,6 +204,15 @@ module Nanoc::CLI
|
|
191
204
|
'w3c_validators' => 'w3c_validators',
|
192
205
|
}.freeze
|
193
206
|
|
207
|
+
def trivial?(error)
|
208
|
+
case error
|
209
|
+
when Nanoc::Int::Errors::GenericTrivial, Errno::EADDRINUSE
|
210
|
+
true
|
211
|
+
else
|
212
|
+
false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
194
216
|
# Attempts to find a resolution for the given error, or nil if no
|
195
217
|
# resolution can be automatically obtained.
|
196
218
|
#
|
@@ -221,6 +243,9 @@ module Nanoc::CLI
|
|
221
243
|
'be modified once compilation has started. Such data includes ' \
|
222
244
|
'content and attributes of items and layouts, and filter arguments.'
|
223
245
|
end
|
246
|
+
when Errno::EADDRINUSE
|
247
|
+
'There already is a server running. Either shut down that one, or ' \
|
248
|
+
'specify a different port to run this server on.'
|
224
249
|
end
|
225
250
|
end
|
226
251
|
|
@@ -228,14 +253,17 @@ module Nanoc::CLI
|
|
228
253
|
defined?(Bundler) && Bundler::SharedHelpers.in_bundle?
|
229
254
|
end
|
230
255
|
|
256
|
+
def ruby_version
|
257
|
+
RUBY_VERSION
|
258
|
+
end
|
259
|
+
|
231
260
|
def write_section_header(stream, title, verbose: false)
|
232
261
|
stream.puts
|
262
|
+
|
233
263
|
if verbose
|
234
264
|
stream.puts '===== ' + title.upcase + ':'
|
235
|
-
|
236
|
-
stream.puts "\e[1m\e[31m" + title + ':' + "\e[0m"
|
265
|
+
stream.puts
|
237
266
|
end
|
238
|
-
stream.puts
|
239
267
|
end
|
240
268
|
|
241
269
|
def write_error_message(stream, error, verbose: false)
|
@@ -243,7 +271,11 @@ module Nanoc::CLI
|
|
243
271
|
|
244
272
|
error = unwrap_error(error)
|
245
273
|
|
246
|
-
|
274
|
+
message = "#{error.class}: #{error.message}"
|
275
|
+
unless verbose
|
276
|
+
message = "\e[1m\e[31m" + message + "\e[0m"
|
277
|
+
end
|
278
|
+
stream.puts message
|
247
279
|
resolution = resolution_for(error)
|
248
280
|
stream.puts resolution.to_s if resolution
|
249
281
|
end
|
@@ -254,30 +286,14 @@ module Nanoc::CLI
|
|
254
286
|
write_section_header(stream, 'Item being compiled', verbose: verbose)
|
255
287
|
|
256
288
|
item_rep = error.item_rep
|
257
|
-
stream.puts "
|
258
|
-
stream.puts "Item rep name: #{item_rep.name.inspect}"
|
289
|
+
stream.puts "Current item: #{item_rep.item.identifier} (#{item_rep.name.inspect} representation)"
|
259
290
|
end
|
260
291
|
|
261
292
|
def write_stack_trace(stream, error, verbose: false)
|
262
293
|
write_section_header(stream, 'Stack trace', verbose: verbose)
|
263
294
|
|
264
|
-
|
265
|
-
|
266
|
-
count = verbose ? -1 : 10
|
267
|
-
error.backtrace[0...count].each_with_index do |item, index|
|
268
|
-
stream.puts " #{index}. #{item}"
|
269
|
-
end
|
270
|
-
if !verbose && error.backtrace.size > count
|
271
|
-
stream.puts " ... #{error.backtrace.size - count} more lines omitted. See full crash log for details."
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def write_issue_link(stream, _params = {})
|
276
|
-
stream.puts
|
277
|
-
stream.puts 'If you believe this is a bug in Nanoc, please do report it at'
|
278
|
-
stream.puts '-> https://github.com/nanoc/nanoc/issues/new <-'
|
279
|
-
stream.puts
|
280
|
-
stream.puts 'A detailed crash log has been written to ./crash.log.'
|
295
|
+
writer = StackTraceWriter.new(stream, forwards: forwards_stack_trace?)
|
296
|
+
writer.write(unwrap_error(error), verbose: verbose)
|
281
297
|
end
|
282
298
|
|
283
299
|
def write_version_information(stream, verbose: false)
|
data/lib/nanoc/cli/logger.rb
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc::CLI
|
4
|
+
# @api private
|
5
|
+
class StackTraceWriter
|
6
|
+
def initialize(stream, forwards:)
|
7
|
+
@stream = stream
|
8
|
+
@forwards = forwards
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(error, verbose:)
|
12
|
+
if @forwards
|
13
|
+
write_forwards(error, verbose: verbose)
|
14
|
+
else
|
15
|
+
write_backwards(error, verbose: verbose)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def write_backwards(error, verbose:)
|
22
|
+
count = verbose ? -1 : 10
|
23
|
+
|
24
|
+
error.backtrace[0...count].each_with_index do |item, index|
|
25
|
+
@stream.puts " #{index}. #{item}"
|
26
|
+
end
|
27
|
+
|
28
|
+
if !verbose && error.backtrace.size > count
|
29
|
+
@stream.puts " ... #{error.backtrace.size - count} lines omitted (see crash.log for details)"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def write_forwards(error, verbose:)
|
34
|
+
count = 10
|
35
|
+
backtrace = verbose ? error.backtrace : error.backtrace.take(count)
|
36
|
+
|
37
|
+
if !verbose && error.backtrace.size > count
|
38
|
+
@stream.puts " ... #{error.backtrace.size - count} lines omitted (see crash.log for details)"
|
39
|
+
end
|
40
|
+
|
41
|
+
backtrace.each_with_index.to_a.reverse.each do |(item, index)|
|
42
|
+
if index.zero?
|
43
|
+
@stream.puts " #{item}"
|
44
|
+
else
|
45
|
+
@stream.puts " #{index}. from #{item}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -74,6 +74,31 @@ module Nanoc::DataSources
|
|
74
74
|
load_objects(layouts_dir_name, Nanoc::Int::Layout)
|
75
75
|
end
|
76
76
|
|
77
|
+
def item_changes
|
78
|
+
changes_for_dir(content_dir_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def layout_changes
|
82
|
+
changes_for_dir(layouts_dir_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def changes_for_dir(dir)
|
86
|
+
require 'listen'
|
87
|
+
|
88
|
+
Nanoc::ChangesStream.new do |cl|
|
89
|
+
listener =
|
90
|
+
Listen.to(dir, latency: 0.0, wait_for_delay: 0.0) do |_modifieds, _addeds, _deleteds|
|
91
|
+
cl.unknown
|
92
|
+
end
|
93
|
+
|
94
|
+
listener.start
|
95
|
+
|
96
|
+
cl.to_stop { listener.stop }
|
97
|
+
|
98
|
+
sleep
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
77
102
|
protected
|
78
103
|
|
79
104
|
class ProtoDocument
|
data/lib/nanoc/extra.rb
CHANGED
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc::Extra
|
4
|
+
class LiveRecompiler
|
5
|
+
def initialize(command_runner:)
|
6
|
+
@command_runner = command_runner
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
run_parent do |site|
|
11
|
+
handle_changes(site, @command_runner)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def gen_changes_for_child(site)
|
18
|
+
changes = [
|
19
|
+
site.data_source.item_changes,
|
20
|
+
site.data_source.layout_changes,
|
21
|
+
gen_config_and_rules_changes,
|
22
|
+
]
|
23
|
+
|
24
|
+
SlowEnumeratorTools.batch(SlowEnumeratorTools.merge(changes))
|
25
|
+
end
|
26
|
+
|
27
|
+
def run_child(pipe_write, pipe_read)
|
28
|
+
pipe_write.close
|
29
|
+
|
30
|
+
site = Nanoc::Int::SiteLoader.new.new_from_cwd
|
31
|
+
changes_enum = gen_changes_for_child(site)
|
32
|
+
yield(site)
|
33
|
+
|
34
|
+
quit = Object.new
|
35
|
+
parent_enum = Enumerator.new do |y|
|
36
|
+
pipe_read.read
|
37
|
+
y << quit
|
38
|
+
end
|
39
|
+
|
40
|
+
SlowEnumeratorTools.merge([parent_enum, changes_enum]).each do |e|
|
41
|
+
break if quit.equal?(e)
|
42
|
+
|
43
|
+
$stderr.print 'Reloading site… '
|
44
|
+
$stderr.flush
|
45
|
+
site_loader = Nanoc::Int::SiteLoader.new
|
46
|
+
site = Nanoc::Int::Site.new(
|
47
|
+
config: Nanoc::Int::ConfigLoader.new.new_from_cwd,
|
48
|
+
data_source: site_loader.gen_data_source_for_config(site.config),
|
49
|
+
code_snippets: site.code_snippets,
|
50
|
+
)
|
51
|
+
$stderr.puts 'done'
|
52
|
+
|
53
|
+
yield(site)
|
54
|
+
end
|
55
|
+
|
56
|
+
exit 0
|
57
|
+
rescue Interrupt
|
58
|
+
exit 0
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_parent
|
62
|
+
# create initial child
|
63
|
+
pipe_read, pipe_write = IO.pipe
|
64
|
+
fork { run_child(pipe_write, pipe_read) { |s| yield(s) } }
|
65
|
+
pipe_read.close
|
66
|
+
|
67
|
+
gen_lib_changes.each do |_e|
|
68
|
+
# stop child
|
69
|
+
pipe_write.write('q')
|
70
|
+
pipe_write.close
|
71
|
+
Process.wait
|
72
|
+
|
73
|
+
# create new child
|
74
|
+
pipe_read, pipe_write = IO.pipe
|
75
|
+
fork { run_child(pipe_write, pipe_read) { |s| yield(s) } }
|
76
|
+
pipe_read.close
|
77
|
+
end
|
78
|
+
rescue Interrupt
|
79
|
+
end
|
80
|
+
|
81
|
+
def handle_changes(site, command_runner)
|
82
|
+
time_before = Time.now
|
83
|
+
|
84
|
+
puts 'Compiling site…'
|
85
|
+
compiler = Nanoc::Int::Compiler.new_for(site)
|
86
|
+
listener = Nanoc::CLI::Commands::CompileListeners::Aggregate.new(
|
87
|
+
command_runner: command_runner,
|
88
|
+
site: site,
|
89
|
+
compiler: compiler,
|
90
|
+
)
|
91
|
+
listener.run_while do
|
92
|
+
compiler.run_until_end
|
93
|
+
end
|
94
|
+
|
95
|
+
time_after = Time.now
|
96
|
+
puts "Site compiled in #{format('%.2f', time_after - time_before)}s."
|
97
|
+
puts
|
98
|
+
end
|
99
|
+
|
100
|
+
def gen_lib_changes
|
101
|
+
require 'listen'
|
102
|
+
|
103
|
+
Nanoc::ChangesStream.new do |cl|
|
104
|
+
opts = {
|
105
|
+
latency: 0.0,
|
106
|
+
wait_for_delay: 0.0,
|
107
|
+
}
|
108
|
+
|
109
|
+
listener = Listen.to('lib', opts) { |*| cl.lib }
|
110
|
+
listener.start
|
111
|
+
sleep
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def gen_config_and_rules_changes
|
116
|
+
require 'listen'
|
117
|
+
|
118
|
+
Nanoc::ChangesStream.new do |cl|
|
119
|
+
opts = {
|
120
|
+
only: /(\/|\A)(nanoc\.yaml|config\.yaml|rules|Rules|rules\.rb|Rules\.rb)\z/,
|
121
|
+
latency: 0.0,
|
122
|
+
wait_for_delay: 0.0,
|
123
|
+
}
|
124
|
+
|
125
|
+
listener = Listen.to('.', opts) { |*| cl.unknown }
|
126
|
+
listener.start
|
127
|
+
sleep
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|