nanoc-core 4.11.12 → 4.11.17
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/lib/nanoc/core.rb +37 -0
- data/lib/nanoc/core/basic_item_rep_collection_view.rb +88 -0
- data/lib/nanoc/core/basic_item_rep_view.rb +83 -0
- data/lib/nanoc/core/basic_item_view.rb +54 -0
- data/lib/nanoc/core/changes_stream.rb +55 -0
- data/lib/nanoc/core/checksum_store.rb +1 -1
- data/lib/nanoc/core/checksummer.rb +4 -2
- data/lib/nanoc/core/compilation_item_rep_collection_view.rb +12 -0
- data/lib/nanoc/core/compilation_item_rep_view.rb +57 -0
- data/lib/nanoc/core/compilation_item_view.rb +47 -0
- data/lib/nanoc/core/compilation_phases/abstract.rb +48 -0
- data/lib/nanoc/core/compilation_phases/cache.rb +43 -0
- data/lib/nanoc/core/compilation_phases/mark_done.rb +23 -0
- data/lib/nanoc/core/compilation_phases/notify.rb +19 -0
- data/lib/nanoc/core/compilation_phases/recalculate.rb +49 -0
- data/lib/nanoc/core/compilation_phases/resume.rb +52 -0
- data/lib/nanoc/core/compilation_phases/write.rb +84 -0
- data/lib/nanoc/core/compilation_stages/build_reps.rb +36 -0
- data/lib/nanoc/core/compilation_stages/calculate_checksums.rb +42 -0
- data/lib/nanoc/core/compilation_stages/cleanup.rb +43 -0
- data/lib/nanoc/core/compilation_stages/compile_reps.rb +96 -0
- data/lib/nanoc/core/compilation_stages/determine_outdatedness.rb +49 -0
- data/lib/nanoc/core/compilation_stages/forget_outdated_dependencies.rb +20 -0
- data/lib/nanoc/core/compilation_stages/load_stores.rb +35 -0
- data/lib/nanoc/core/compilation_stages/postprocess.rb +21 -0
- data/lib/nanoc/core/compilation_stages/preprocess.rb +32 -0
- data/lib/nanoc/core/compilation_stages/prune.rb +30 -0
- data/lib/nanoc/core/compilation_stages/store_post_compilation_state.rb +20 -0
- data/lib/nanoc/core/compilation_stages/store_pre_compilation_state.rb +32 -0
- data/lib/nanoc/core/compiled_content_cache.rb +2 -2
- data/lib/nanoc/core/compiler.rb +214 -0
- data/lib/nanoc/core/compiler_loader.rb +48 -0
- data/lib/nanoc/core/config_loader.rb +95 -0
- data/lib/nanoc/core/config_view.rb +67 -0
- data/lib/nanoc/core/configuration.rb +2 -4
- data/lib/nanoc/core/contracts_support.rb +20 -0
- data/lib/nanoc/core/dependency_store.rb +3 -3
- data/lib/nanoc/core/document_view_mixin.rb +87 -0
- data/lib/nanoc/core/errors.rb +108 -0
- data/lib/nanoc/core/executor.rb +134 -0
- data/lib/nanoc/core/feature.rb +92 -0
- data/lib/nanoc/core/filter.rb +269 -0
- data/lib/nanoc/core/identifiable_collection_view.rb +111 -0
- data/lib/nanoc/core/item_collection_with_reps_view.rb +12 -0
- data/lib/nanoc/core/item_collection_without_reps_view.rb +12 -0
- data/lib/nanoc/core/item_rep_builder.rb +54 -0
- data/lib/nanoc/core/item_rep_selector.rb +67 -0
- data/lib/nanoc/core/item_rep_writer.rb +85 -0
- data/lib/nanoc/core/layout_collection_view.rb +12 -0
- data/lib/nanoc/core/layout_view.rb +9 -0
- data/lib/nanoc/core/mutable_config_view.rb +16 -0
- data/lib/nanoc/core/mutable_document_view_mixin.rb +60 -0
- data/lib/nanoc/core/mutable_identifiable_collection_view.rb +19 -0
- data/lib/nanoc/core/mutable_item_collection_view.rb +34 -0
- data/lib/nanoc/core/mutable_item_view.rb +9 -0
- data/lib/nanoc/core/mutable_layout_collection_view.rb +26 -0
- data/lib/nanoc/core/mutable_layout_view.rb +9 -0
- data/lib/nanoc/core/outdatedness_checker.rb +222 -0
- data/lib/nanoc/core/outdatedness_rules/attributes_modified.rb +41 -0
- data/lib/nanoc/core/outdatedness_rules/code_snippets_modified.rb +31 -0
- data/lib/nanoc/core/outdatedness_rules/content_modified.rb +21 -0
- data/lib/nanoc/core/outdatedness_rules/item_collection_extended.rb +20 -0
- data/lib/nanoc/core/outdatedness_rules/layout_collection_extended.rb +20 -0
- data/lib/nanoc/core/outdatedness_rules/not_written.rb +17 -0
- data/lib/nanoc/core/outdatedness_rules/rules_modified.rb +45 -0
- data/lib/nanoc/core/outdatedness_rules/uses_always_outdated_filter.rb +26 -0
- data/lib/nanoc/core/post_compile_item_collection_view.rb +12 -0
- data/lib/nanoc/core/post_compile_item_rep_collection_view.rb +12 -0
- data/lib/nanoc/core/post_compile_item_rep_view.rb +33 -0
- data/lib/nanoc/core/post_compile_item_view.rb +20 -0
- data/lib/nanoc/core/pruner.rb +123 -0
- data/lib/nanoc/core/site_loader.rb +102 -0
- data/lib/nanoc/core/trivial_error.rb +10 -0
- data/lib/nanoc/core/version.rb +1 -1
- data/lib/nanoc/core/view.rb +43 -0
- data/lib/nanoc/core/view_context_for_compilation.rb +6 -6
- metadata +97 -3
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class IdentifiableCollectionView < ::Nanoc::Core::View
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
NOTHING = Object.new
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
def initialize(objects, context)
|
12
|
+
super(context)
|
13
|
+
@objects = objects
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
def _unwrap
|
18
|
+
@objects
|
19
|
+
end
|
20
|
+
|
21
|
+
# @abstract
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
def view_class
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
# Calls the given block once for each object, passing that object as a parameter.
|
29
|
+
#
|
30
|
+
# @yieldparam [#identifier] object
|
31
|
+
#
|
32
|
+
# @yieldreturn [void]
|
33
|
+
#
|
34
|
+
# @return [self]
|
35
|
+
def each
|
36
|
+
@context.dependency_tracker.bounce(_unwrap, raw_content: true)
|
37
|
+
@objects.each { |i| yield view_class.new(i, @context) }
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Integer]
|
42
|
+
def size
|
43
|
+
@context.dependency_tracker.bounce(_unwrap, raw_content: true)
|
44
|
+
@objects.size
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds all objects whose identifier matches the given argument.
|
48
|
+
#
|
49
|
+
# @param [String, Regex] arg
|
50
|
+
#
|
51
|
+
# @return [Enumerable]
|
52
|
+
def find_all(arg = NOTHING, &block)
|
53
|
+
if NOTHING.equal?(arg)
|
54
|
+
@context.dependency_tracker.bounce(_unwrap, raw_content: true)
|
55
|
+
return @objects.map { |i| view_class.new(i, @context) }.select(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
prop_attribute =
|
59
|
+
case arg
|
60
|
+
when String, Nanoc::Core::Identifier
|
61
|
+
[arg.to_s]
|
62
|
+
when Regexp
|
63
|
+
[arg]
|
64
|
+
else
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
@context.dependency_tracker.bounce(_unwrap, raw_content: prop_attribute)
|
69
|
+
@objects.find_all(arg).map { |i| view_class.new(i, @context) }
|
70
|
+
end
|
71
|
+
|
72
|
+
# @overload [](string)
|
73
|
+
#
|
74
|
+
# Finds the object whose identifier matches the given string.
|
75
|
+
#
|
76
|
+
# If the glob syntax is enabled, the string can be a glob, in which case
|
77
|
+
# this method finds the first object that matches the given glob.
|
78
|
+
#
|
79
|
+
# @param [String] string
|
80
|
+
#
|
81
|
+
# @return [nil] if no object matches the string
|
82
|
+
#
|
83
|
+
# @return [#identifier] if an object was found
|
84
|
+
#
|
85
|
+
# @overload [](regex)
|
86
|
+
#
|
87
|
+
# Finds the object whose identifier matches the given regular expression.
|
88
|
+
#
|
89
|
+
# @param [Regex] regex
|
90
|
+
#
|
91
|
+
# @return [nil] if no object matches the regex
|
92
|
+
#
|
93
|
+
# @return [#identifier] if an object was found
|
94
|
+
def [](arg)
|
95
|
+
prop_attribute =
|
96
|
+
case arg
|
97
|
+
when String, Nanoc::Core::Identifier
|
98
|
+
[arg.to_s]
|
99
|
+
when Regexp
|
100
|
+
[arg]
|
101
|
+
else
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
@context.dependency_tracker.bounce(_unwrap, raw_content: prop_attribute)
|
106
|
+
res = @objects[arg]
|
107
|
+
res && view_class.new(res, @context)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
# @api private
|
6
|
+
class ItemRepBuilder
|
7
|
+
include Nanoc::Core::ContractsSupport
|
8
|
+
|
9
|
+
attr_reader :reps
|
10
|
+
|
11
|
+
contract Nanoc::Core::Site, Nanoc::Core::ActionProvider, Nanoc::Core::ItemRepRepo => C::Any
|
12
|
+
def initialize(site, action_provider, reps)
|
13
|
+
@site = site
|
14
|
+
@action_provider = action_provider
|
15
|
+
@reps = reps
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
@site.items.each do |item|
|
20
|
+
@action_provider.rep_names_for(item).each do |rep_name|
|
21
|
+
@reps << Nanoc::Core::ItemRep.new(item, rep_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
action_sequences = Nanoc::Core::ItemRepRouter.new(@reps, @action_provider, @site).run
|
26
|
+
|
27
|
+
@reps.each do |rep|
|
28
|
+
rep.snapshot_defs = self.class.snapshot_defs_for(action_sequences[rep])
|
29
|
+
end
|
30
|
+
|
31
|
+
action_sequences
|
32
|
+
end
|
33
|
+
|
34
|
+
contract Nanoc::Core::ActionSequence => C::ArrayOf[Nanoc::Core::SnapshotDef]
|
35
|
+
def self.snapshot_defs_for(action_sequence)
|
36
|
+
is_binary = action_sequence.item_rep.item.content.binary?
|
37
|
+
snapshot_defs = []
|
38
|
+
|
39
|
+
action_sequence.each do |action|
|
40
|
+
case action
|
41
|
+
when Nanoc::Core::ProcessingActions::Snapshot
|
42
|
+
action.snapshot_names.each do |snapshot_name|
|
43
|
+
snapshot_defs << Nanoc::Core::SnapshotDef.new(snapshot_name, binary: is_binary)
|
44
|
+
end
|
45
|
+
when Nanoc::Core::ProcessingActions::Filter
|
46
|
+
is_binary = Nanoc::Core::Filter.named!(action.filter_name).to_binary?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
snapshot_defs
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
# Yields item reps to compile.
|
6
|
+
class ItemRepSelector
|
7
|
+
def initialize(reps)
|
8
|
+
@reps = reps
|
9
|
+
end
|
10
|
+
|
11
|
+
class MicroGraph
|
12
|
+
def initialize(reps)
|
13
|
+
@reps = Set.new(reps)
|
14
|
+
@stack = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def next
|
18
|
+
if @stack.any?
|
19
|
+
@stack.last
|
20
|
+
elsif @reps.any?
|
21
|
+
@reps.each { |rep| break rep }.tap do |rep|
|
22
|
+
@reps.delete(rep)
|
23
|
+
@stack.push(rep)
|
24
|
+
end
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def mark_ok
|
31
|
+
@stack.pop
|
32
|
+
end
|
33
|
+
|
34
|
+
def mark_failed(dep)
|
35
|
+
if @stack.include?(dep)
|
36
|
+
raise Nanoc::Core::Errors::DependencyCycle.new(@stack + [dep])
|
37
|
+
end
|
38
|
+
|
39
|
+
@reps.delete(dep)
|
40
|
+
@stack.push(dep)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def each
|
45
|
+
mg = MicroGraph.new(@reps)
|
46
|
+
|
47
|
+
loop do
|
48
|
+
rep = mg.next
|
49
|
+
break if rep.nil?
|
50
|
+
|
51
|
+
begin
|
52
|
+
yield(rep)
|
53
|
+
mg.mark_ok
|
54
|
+
rescue => e
|
55
|
+
actual_error = e.is_a?(Nanoc::Core::Errors::CompilationError) ? e.unwrap : e
|
56
|
+
|
57
|
+
if actual_error.is_a?(Nanoc::Core::Errors::UnmetDependency)
|
58
|
+
mg.mark_failed(actual_error.rep)
|
59
|
+
else
|
60
|
+
raise(e)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class ItemRepWriter
|
6
|
+
include Nanoc::Core::ContractsSupport
|
7
|
+
include Nanoc::Core::Assertions::Mixin
|
8
|
+
|
9
|
+
TMP_TEXT_ITEMS_DIR = 'text_items'
|
10
|
+
|
11
|
+
def write_all(item_rep, compiled_content_store)
|
12
|
+
written_paths = Set.new
|
13
|
+
|
14
|
+
item_rep.snapshot_defs.map(&:name).each do |snapshot_name|
|
15
|
+
write(item_rep, compiled_content_store, snapshot_name, written_paths)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(item_rep, compiled_content_store, snapshot_name, written_paths)
|
20
|
+
item_rep.raw_paths.fetch(snapshot_name, []).each do |raw_path|
|
21
|
+
write_single(item_rep, compiled_content_store, snapshot_name, raw_path, written_paths)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_single(item_rep, compiled_content_store, snapshot_name, raw_path, written_paths)
|
26
|
+
assert Nanoc::Core::Assertions::PathIsAbsolute.new(path: raw_path)
|
27
|
+
|
28
|
+
# Don’t write twice
|
29
|
+
# TODO: test written_paths behavior
|
30
|
+
return if written_paths.include?(raw_path)
|
31
|
+
|
32
|
+
written_paths << raw_path
|
33
|
+
|
34
|
+
# Create parent directory
|
35
|
+
FileUtils.mkdir_p(File.dirname(raw_path))
|
36
|
+
|
37
|
+
# Check if file will be created
|
38
|
+
is_created = !File.file?(raw_path)
|
39
|
+
|
40
|
+
# Notify
|
41
|
+
Nanoc::Core::NotificationCenter.post(
|
42
|
+
:rep_write_started, item_rep, raw_path
|
43
|
+
)
|
44
|
+
|
45
|
+
content = compiled_content_store.get(item_rep, snapshot_name)
|
46
|
+
if content.binary?
|
47
|
+
temp_path = content.filename
|
48
|
+
else
|
49
|
+
temp_path = temp_filename
|
50
|
+
File.write(temp_path, content.string)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check whether content was modified
|
54
|
+
is_modified = is_created || !FileUtils.identical?(raw_path, temp_path)
|
55
|
+
|
56
|
+
# Notify ready for diff generation
|
57
|
+
if !is_created && is_modified && !content.binary?
|
58
|
+
Nanoc::Core::NotificationCenter.post(
|
59
|
+
:rep_ready_for_diff, raw_path, File.read(raw_path, encoding: 'UTF-8'), content.string
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Write
|
64
|
+
if is_modified
|
65
|
+
begin
|
66
|
+
FileUtils.ln(temp_path, raw_path, force: true)
|
67
|
+
rescue Errno::EXDEV, Errno::EACCES
|
68
|
+
FileUtils.cp(temp_path, raw_path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
item_rep.modified = is_modified
|
73
|
+
|
74
|
+
# Notify
|
75
|
+
Nanoc::Core::NotificationCenter.post(
|
76
|
+
:rep_write_ended, item_rep, content.binary?, raw_path, is_created, is_modified
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def temp_filename
|
81
|
+
Nanoc::Core::TempFilenameFactory.instance.create(TMP_TEXT_ITEMS_DIR)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
class MutableConfigView < Nanoc::Core::ConfigView
|
6
|
+
# Sets the value for the given attribute.
|
7
|
+
#
|
8
|
+
# @param [Symbol] key
|
9
|
+
#
|
10
|
+
# @see Hash#[]=
|
11
|
+
def []=(key, value)
|
12
|
+
@config[key] = value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nanoc
|
4
|
+
module Core
|
5
|
+
module MutableDocumentViewMixin
|
6
|
+
# @api private
|
7
|
+
class DisallowedAttributeValueError < Nanoc::Core::Error
|
8
|
+
attr_reader :value
|
9
|
+
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
"The #{value.class} cannot be stored inside an attribute. Store its identifier instead."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def raw_content=(arg)
|
20
|
+
_unwrap.content = Nanoc::Core::Content.create(arg)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sets the value for the given attribute.
|
24
|
+
#
|
25
|
+
# @param [Symbol] key
|
26
|
+
#
|
27
|
+
# @see Hash#[]=
|
28
|
+
def []=(key, value)
|
29
|
+
disallowed_value_classes = Set.new([
|
30
|
+
Nanoc::Core::Item,
|
31
|
+
Nanoc::Core::Layout,
|
32
|
+
Nanoc::Core::CompilationItemView,
|
33
|
+
Nanoc::Core::LayoutView,
|
34
|
+
])
|
35
|
+
if disallowed_value_classes.include?(value.class)
|
36
|
+
raise DisallowedAttributeValueError.new(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
_unwrap.set_attribute(key, value)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sets the identifier to the given argument.
|
43
|
+
#
|
44
|
+
# @param [String, Nanoc::Core::Identifier] arg
|
45
|
+
def identifier=(arg)
|
46
|
+
_unwrap.identifier = Nanoc::Core::Identifier.from(arg)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Updates the attributes based on the given hash.
|
50
|
+
#
|
51
|
+
# @param [Hash] hash
|
52
|
+
#
|
53
|
+
# @return [self]
|
54
|
+
def update_attributes(hash)
|
55
|
+
hash.each { |k, v| _unwrap.set_attribute(k, v) }
|
56
|
+
self
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|