nanoc 4.8.19 → 4.9.0
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/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?
|