nanoc 4.8.19 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/NEWS.md +21 -0
- data/lib/nanoc.rb +5 -4
- data/lib/nanoc/base/entities/directed_graph.rb +4 -4
- data/lib/nanoc/base/entities/identifier.rb +5 -0
- data/lib/nanoc/base/feature.rb +1 -2
- data/lib/nanoc/base/repos/dependency_store.rb +4 -4
- data/lib/nanoc/base/services/compiler/phases/abstract.rb +8 -0
- data/lib/nanoc/base/services/compiler/phases/write.rb +58 -1
- data/lib/nanoc/base/services/compiler/stages/compile_reps.rb +39 -29
- data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +2 -2
- data/lib/nanoc/base/services/instrumentor.rb +1 -1
- data/lib/nanoc/base/services/item_rep_writer.rb +2 -2
- data/lib/nanoc/base/views/compilation_item_rep_view.rb +7 -0
- data/lib/nanoc/checking.rb +4 -1
- data/lib/nanoc/checking/check.rb +7 -0
- data/lib/nanoc/checking/checks/external_links.rb +21 -12
- data/lib/nanoc/checking/dsl.rb +5 -7
- data/lib/nanoc/checking/loader.rb +50 -0
- data/lib/nanoc/checking/runner.rb +18 -40
- data/lib/nanoc/cli.rb +1 -1
- data/lib/nanoc/cli/ansi_string_colorizer.rb +4 -4
- data/lib/nanoc/cli/cleaning_stream.rb +12 -12
- data/lib/nanoc/cli/commands/check.rb +5 -15
- data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +7 -7
- data/lib/nanoc/cli/commands/compile_listeners/file_action_printer.rb +12 -2
- data/lib/nanoc/cli/commands/compile_listeners/timing_recorder.rb +27 -19
- data/lib/nanoc/cli/commands/deploy.rb +1 -1
- data/lib/nanoc/cli/commands/show-rules.rb +2 -2
- data/lib/nanoc/cli/error_handler.rb +1 -4
- data/lib/nanoc/cli/stream_cleaners/abstract.rb +2 -2
- data/lib/nanoc/cli/stream_cleaners/ansi_colors.rb +2 -2
- data/lib/nanoc/cli/stream_cleaners/utf8.rb +2 -2
- data/lib/nanoc/data_sources/filesystem/parser.rb +1 -1
- data/lib/nanoc/deploying/deployers/fog.rb +3 -3
- data/lib/nanoc/extra.rb +1 -2
- data/lib/nanoc/filters/colorize_syntax.rb +2 -2
- data/lib/nanoc/filters/relativize_paths.rb +2 -2
- data/lib/nanoc/helpers/blogging.rb +11 -11
- data/lib/nanoc/rule_dsl/compilation_rule_context.rb +1 -1
- data/lib/nanoc/version.rb +1 -1
- metadata +27 -13
- data/lib/nanoc/extra/parallel_collection.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed74af636c6e396ec74288c853dca19336227108e99d4db697f83a655c50d3fc
|
4
|
+
data.tar.gz: 9e38014cee26d2f3f88e4e77ea1d9f2c493c78f5613e6e7ea6867d3d0828ce94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44254d1810d3d2bfbbf12b9155035c968d641cdf1880fef342baee260cc4e0fc2fd17731df76b7108292917becb1b2c48902aa87feee47422b33b3941ada97ea
|
7
|
+
data.tar.gz: 271d3c575afbf515409eb5d635eaf53b0a387e97bea37eaf18a8a424d522a961a2138d36d85cb49b988cfdaae782ab5145b2bc596744b3ef5c3b24853a191f59
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2007-
|
1
|
+
Copyright (c) 2007-2018 Denis Defreyne and contributors
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/NEWS.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Nanoc news
|
2
2
|
|
3
|
+
## 4.9.0 (2018-01-31)
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
* Added `Identifier#match?` (#1305)
|
8
|
+
* Added `Nanoc::Check.define`
|
9
|
+
* Made Nanoc read checks configuration from `nanoc.yaml` (#1296)
|
10
|
+
|
11
|
+
Enhancements:
|
12
|
+
|
13
|
+
* Made Nanoc write out files asynchronously (#1288)
|
14
|
+
* Made the filesystem data source ignore an initial blank line after the frontmatter (#1292, #1293)
|
15
|
+
* Made the `check` command run deploy checks by default (#1304)
|
16
|
+
* Made Nanoc honor the `NO_COLOR` environment variable (#1306)
|
17
|
+
|
18
|
+
Bugs:
|
19
|
+
|
20
|
+
* Fixed a potential deadlock in the `external_links` check (#1294, #1295)
|
21
|
+
* Fixed the `external_links` check’s handling of redirects without a `Location` header (#1297, #1302)
|
22
|
+
* Fixed the `external_links` check’s handling of URLs with invalid components (#1303)
|
23
|
+
|
3
24
|
## 4.8.19 (2018-01-01)
|
4
25
|
|
5
26
|
Enhancements:
|
data/lib/nanoc.rb
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
|
3
3
|
# Load external dependencies
|
4
4
|
require 'addressable'
|
5
|
+
require 'ddmemoize'
|
6
|
+
require 'ddmetrics'
|
5
7
|
require 'ddplugin'
|
6
8
|
require 'hamster'
|
9
|
+
require 'parallel'
|
7
10
|
require 'ref'
|
8
11
|
require 'slow_enumerator_tools'
|
9
|
-
require 'ddmemoize'
|
10
|
-
require 'ddtelemetry'
|
11
12
|
|
12
|
-
DDMemoize.
|
13
|
+
DDMemoize.enable_metrics
|
13
14
|
|
14
15
|
module Nanoc
|
15
16
|
# @return [String] A string containing information about this Nanoc version
|
@@ -17,7 +18,7 @@ module Nanoc
|
|
17
18
|
#
|
18
19
|
# @api private
|
19
20
|
def self.version_information
|
20
|
-
"Nanoc #{Nanoc::VERSION} © 2007-
|
21
|
+
"Nanoc #{Nanoc::VERSION} © 2007-2018 Denis Defreyne.\n" \
|
21
22
|
"Running #{RUBY_ENGINE} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) on #{RUBY_PLATFORM} with RubyGems #{Gem::VERSION}.\n"
|
22
23
|
end
|
23
24
|
|
@@ -88,13 +88,13 @@ module Nanoc::Int
|
|
88
88
|
|
89
89
|
# Adds the given vertex to the graph.
|
90
90
|
#
|
91
|
-
# @param
|
91
|
+
# @param vertex The vertex to add to the graph
|
92
92
|
#
|
93
93
|
# @return [void]
|
94
|
-
def add_vertex(
|
95
|
-
return if @vertices.key?(
|
94
|
+
def add_vertex(vertex)
|
95
|
+
return if @vertices.key?(vertex)
|
96
96
|
|
97
|
-
@vertices[
|
97
|
+
@vertices[vertex] = @next_vertex_idx.tap { @next_vertex_idx += 1 }
|
98
98
|
end
|
99
99
|
|
100
100
|
# Deletes all edges going to the given vertex.
|
@@ -101,6 +101,11 @@ module Nanoc
|
|
101
101
|
Nanoc::Int::Pattern.from(other).match?(to_s) ? 0 : nil
|
102
102
|
end
|
103
103
|
|
104
|
+
contract C::Any => C::Bool
|
105
|
+
def match?(other)
|
106
|
+
Nanoc::Int::Pattern.from(other).match?(to_s)
|
107
|
+
end
|
108
|
+
|
104
109
|
contract C::Any => C::Num
|
105
110
|
def <=>(other)
|
106
111
|
to_s <=> other.to_s
|
data/lib/nanoc/base/feature.rb
CHANGED
@@ -120,8 +120,8 @@ module Nanoc::Int
|
|
120
120
|
@graph.add_edge(dst_ref, src_ref, props: props.to_h)
|
121
121
|
end
|
122
122
|
|
123
|
-
def add_vertex_for(
|
124
|
-
@refs2objs[obj2ref(
|
123
|
+
def add_vertex_for(obj)
|
124
|
+
@refs2objs[obj2ref(obj)] = obj
|
125
125
|
end
|
126
126
|
|
127
127
|
# Empties the list of dependencies for the given object. This is necessary
|
@@ -159,8 +159,8 @@ module Nanoc::Int
|
|
159
159
|
refs.map { |r| ref2obj(r) }
|
160
160
|
end
|
161
161
|
|
162
|
-
def props_for(
|
163
|
-
props = @graph.props_for(obj2ref(
|
162
|
+
def props_for(from, to)
|
163
|
+
props = @graph.props_for(obj2ref(from), obj2ref(to)) || {}
|
164
164
|
|
165
165
|
if props.values.any? { |v| v }
|
166
166
|
props
|
@@ -4,17 +4,74 @@ module Nanoc::Int::Compiler::Phases
|
|
4
4
|
class Write < Abstract
|
5
5
|
include Nanoc::Int::ContractsSupport
|
6
6
|
|
7
|
+
class Worker
|
8
|
+
def initialize(queue:, snapshot_repo:)
|
9
|
+
@queue = queue
|
10
|
+
@snapshot_repo = snapshot_repo
|
11
|
+
end
|
12
|
+
|
13
|
+
def start
|
14
|
+
@thread = Thread.new do
|
15
|
+
Thread.current.abort_on_exception = true
|
16
|
+
Thread.current.priority = -1 # schedule I/O work ASAP
|
17
|
+
|
18
|
+
writer = Nanoc::Int::ItemRepWriter.new
|
19
|
+
|
20
|
+
while rep = @queue.pop # rubocop:disable Lint/AssignmentInCondition
|
21
|
+
writer.write_all(rep, @snapshot_repo)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def join
|
27
|
+
@thread.join
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class WorkerPool
|
32
|
+
def initialize(queue:, size:, snapshot_repo:)
|
33
|
+
@workers = Array.new(size) { Worker.new(queue: queue, snapshot_repo: snapshot_repo) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def start
|
37
|
+
@workers.each(&:start)
|
38
|
+
end
|
39
|
+
|
40
|
+
def join
|
41
|
+
@workers.each(&:join)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
QUEUE_SIZE = 40
|
46
|
+
WORKER_POOL_SIZE = 5
|
47
|
+
|
7
48
|
def initialize(snapshot_repo:, wrapped:)
|
8
49
|
super(wrapped: wrapped)
|
9
50
|
|
10
51
|
@snapshot_repo = snapshot_repo
|
52
|
+
|
53
|
+
@queue = SizedQueue.new(QUEUE_SIZE)
|
54
|
+
@worker_pool = WorkerPool.new(queue: @queue, size: WORKER_POOL_SIZE, snapshot_repo: @snapshot_repo)
|
55
|
+
end
|
56
|
+
|
57
|
+
def start
|
58
|
+
super
|
59
|
+
@worker_pool.start
|
60
|
+
end
|
61
|
+
|
62
|
+
def stop
|
63
|
+
super
|
64
|
+
@queue.close
|
65
|
+
@worker_pool.join
|
11
66
|
end
|
12
67
|
|
13
68
|
contract Nanoc::Int::ItemRep, C::KeywordArgs[is_outdated: C::Bool], C::Func[C::None => C::Any] => C::Any
|
14
69
|
def run(rep, is_outdated:) # rubocop:disable Lint/UnusedMethodArgument
|
15
70
|
yield
|
16
71
|
|
17
|
-
|
72
|
+
@queue << rep
|
73
|
+
|
74
|
+
Nanoc::Int::NotificationCenter.post(:rep_write_enqueued, rep)
|
18
75
|
end
|
19
76
|
end
|
20
77
|
end
|
@@ -14,8 +14,12 @@ module Nanoc::Int::Compiler::Stages
|
|
14
14
|
def run
|
15
15
|
outdated_reps = @reps.select { |r| @outdatedness_store.include?(r) }
|
16
16
|
selector = Nanoc::Int::ItemRepSelector.new(outdated_reps)
|
17
|
-
|
18
|
-
|
17
|
+
run_phase_stack do |phase_stack|
|
18
|
+
selector.each do |rep|
|
19
|
+
handle_errors_while(rep) do
|
20
|
+
compile_rep(rep, phase_stack: phase_stack, is_outdated: @outdatedness_store.include?(rep))
|
21
|
+
end
|
22
|
+
end
|
19
23
|
end
|
20
24
|
ensure
|
21
25
|
@outdatedness_store.store
|
@@ -30,40 +34,46 @@ module Nanoc::Int::Compiler::Stages
|
|
30
34
|
raise Nanoc::Int::Errors::CompilationError.new(e, item_rep)
|
31
35
|
end
|
32
36
|
|
33
|
-
def compile_rep(rep, is_outdated:)
|
34
|
-
|
37
|
+
def compile_rep(rep, phase_stack:, is_outdated:)
|
38
|
+
phase_stack.call(rep, is_outdated: is_outdated)
|
35
39
|
end
|
36
40
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def run_phase_stack
|
42
|
+
phase_stack = build_phase_stack
|
43
|
+
phase_stack.start
|
44
|
+
yield(phase_stack)
|
45
|
+
ensure
|
46
|
+
phase_stack.stop
|
47
|
+
end
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
def build_phase_stack
|
50
|
+
recalculate_phase = Nanoc::Int::Compiler::Phases::Recalculate.new(
|
51
|
+
action_sequences: @action_sequences,
|
52
|
+
dependency_store: @dependency_store,
|
53
|
+
compilation_context: @compilation_context,
|
54
|
+
)
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
56
|
+
cache_phase = Nanoc::Int::Compiler::Phases::Cache.new(
|
57
|
+
compiled_content_cache: @compiled_content_cache,
|
58
|
+
snapshot_repo: @compilation_context.snapshot_repo,
|
59
|
+
wrapped: recalculate_phase,
|
60
|
+
)
|
54
61
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
)
|
62
|
+
resume_phase = Nanoc::Int::Compiler::Phases::Resume.new(
|
63
|
+
wrapped: cache_phase,
|
64
|
+
)
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
write_phase = Nanoc::Int::Compiler::Phases::Write.new(
|
67
|
+
snapshot_repo: @compilation_context.snapshot_repo,
|
68
|
+
wrapped: resume_phase,
|
69
|
+
)
|
64
70
|
|
65
|
-
|
66
|
-
|
71
|
+
mark_done_phase = Nanoc::Int::Compiler::Phases::MarkDone.new(
|
72
|
+
wrapped: write_phase,
|
73
|
+
outdatedness_store: @outdatedness_store,
|
74
|
+
)
|
75
|
+
|
76
|
+
mark_done_phase
|
67
77
|
end
|
68
78
|
end
|
69
79
|
end
|
@@ -38,8 +38,8 @@ module Nanoc::Int::Compiler::Stages
|
|
38
38
|
Set.new(items.flat_map { |i| @reps[i] })
|
39
39
|
end
|
40
40
|
|
41
|
-
def outdated?(
|
42
|
-
@outdatedness_store.include?(
|
41
|
+
def outdated?(rep)
|
42
|
+
@outdatedness_store.include?(rep) || @outdatedness_checker.outdated?(rep)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -33,7 +33,7 @@ module Nanoc::Int
|
|
33
33
|
|
34
34
|
# Notify
|
35
35
|
Nanoc::Int::NotificationCenter.post(
|
36
|
-
:
|
36
|
+
:rep_write_started, item_rep, raw_path
|
37
37
|
)
|
38
38
|
|
39
39
|
content = snapshot_repo.get(item_rep, snapshot_name)
|
@@ -54,7 +54,7 @@ module Nanoc::Int
|
|
54
54
|
|
55
55
|
# Notify
|
56
56
|
Nanoc::Int::NotificationCenter.post(
|
57
|
-
:
|
57
|
+
:rep_write_ended, item_rep, content.binary?, raw_path, is_created, is_modified
|
58
58
|
)
|
59
59
|
end
|
60
60
|
|
@@ -23,6 +23,13 @@ module Nanoc
|
|
23
23
|
Fiber.yield(Nanoc::Int::Errors::UnmetDependency.new(@item_rep))
|
24
24
|
end
|
25
25
|
|
26
|
+
# Wait for file to exist
|
27
|
+
if res
|
28
|
+
start = Time.now
|
29
|
+
sleep 0.05 until File.file?(res) || Time.now - start > 1.0
|
30
|
+
raise Nanoc::Int::Errors::InternalInconsistency, "File did not apear in time: #{res}" unless File.file?(res)
|
31
|
+
end
|
32
|
+
|
26
33
|
res
|
27
34
|
end
|
28
35
|
|
data/lib/nanoc/checking.rb
CHANGED
@@ -7,5 +7,8 @@ end
|
|
7
7
|
require_relative 'checking/check'
|
8
8
|
require_relative 'checking/checks'
|
9
9
|
require_relative 'checking/dsl'
|
10
|
-
require_relative 'checking/runner
|
10
|
+
require_relative 'checking/runner'
|
11
|
+
require_relative 'checking/loader'
|
11
12
|
require_relative 'checking/issue'
|
13
|
+
|
14
|
+
Nanoc::Check = Nanoc::Checking::Check
|
data/lib/nanoc/checking/check.rb
CHANGED
@@ -14,6 +14,13 @@ module Nanoc::Checking
|
|
14
14
|
|
15
15
|
attr_reader :issues
|
16
16
|
|
17
|
+
def self.define(ident, &block)
|
18
|
+
klass = Class.new(::Nanoc::Checking::Check) { identifier(ident) }
|
19
|
+
klass.send(:define_method, :run) do
|
20
|
+
instance_exec(&block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
def self.create(site)
|
18
25
|
output_dir = site.config[:output_dir]
|
19
26
|
unless File.exist?(output_dir)
|
@@ -37,8 +37,7 @@ module ::Nanoc::Checking::Checks
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def select_invalid(hrefs)
|
40
|
-
|
41
|
-
col.map { |href| validate(href) }.compact
|
40
|
+
::Parallel.map(hrefs, in_threads: 10) { |href| validate(href) }.compact
|
42
41
|
end
|
43
42
|
|
44
43
|
def validate(href)
|
@@ -46,7 +45,7 @@ module ::Nanoc::Checking::Checks
|
|
46
45
|
url = nil
|
47
46
|
begin
|
48
47
|
url = URI.parse(href)
|
49
|
-
rescue URI::
|
48
|
+
rescue URI::Error
|
50
49
|
return Result.new(href, 'invalid URI')
|
51
50
|
end
|
52
51
|
|
@@ -75,15 +74,8 @@ module ::Nanoc::Checking::Checks
|
|
75
74
|
return Result.new(href, 'too many redirects')
|
76
75
|
end
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
if location !~ /^https?:\/\//
|
81
|
-
base_url = url.dup
|
82
|
-
base_url.path = (location =~ /^\// ? '' : '/')
|
83
|
-
base_url.query = nil
|
84
|
-
base_url.fragment = nil
|
85
|
-
location = base_url.to_s + location
|
86
|
-
end
|
77
|
+
location = extract_location(res, url)
|
78
|
+
return Result.new(href, 'redirection without a target location') if location.nil?
|
87
79
|
|
88
80
|
url = URI.parse(location)
|
89
81
|
elsif res.code == '200'
|
@@ -99,6 +91,23 @@ module ::Nanoc::Checking::Checks
|
|
99
91
|
end
|
100
92
|
end
|
101
93
|
|
94
|
+
def extract_location(res, url)
|
95
|
+
location = res['Location']
|
96
|
+
|
97
|
+
case location
|
98
|
+
when nil
|
99
|
+
nil
|
100
|
+
when /^https?:\/\//
|
101
|
+
location
|
102
|
+
else
|
103
|
+
base_url = url.dup
|
104
|
+
base_url.path = (location =~ /^\// ? '' : '/')
|
105
|
+
base_url.query = nil
|
106
|
+
base_url.fragment = nil
|
107
|
+
base_url.to_s + location
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
102
111
|
def path_for_url(url)
|
103
112
|
path =
|
104
113
|
if url.path.nil? || url.path.empty?
|