nanoc 4.8.10 → 4.8.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|