nanoc 4.11.8 → 4.11.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +8 -0
- data/lib/nanoc.rb +4 -1
- data/lib/nanoc/base.rb +0 -1
- data/lib/nanoc/base/errors.rb +4 -49
- data/lib/nanoc/base/repos.rb +0 -15
- data/lib/nanoc/base/repos/site_loader.rb +1 -1
- data/lib/nanoc/base/services.rb +0 -2
- data/lib/nanoc/base/services/compiler.rb +1 -1
- data/lib/nanoc/base/services/compiler/phases/recalculate.rb +1 -1
- data/lib/nanoc/base/services/compiler/stages/build_reps.rb +1 -1
- data/lib/nanoc/base/services/compiler/stages/cleanup.rb +1 -1
- data/lib/nanoc/base/services/compiler/stages/load_stores.rb +1 -1
- data/lib/nanoc/base/services/compiler_loader.rb +6 -6
- data/lib/nanoc/base/services/outdatedness_checker.rb +10 -10
- data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +4 -4
- data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +2 -2
- data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +2 -2
- data/lib/nanoc/base/services/outdatedness_rules/item_collection_extended.rb +3 -3
- data/lib/nanoc/base/services/outdatedness_rules/layout_collection_extended.rb +3 -3
- data/lib/nanoc/base/services/outdatedness_rules/not_written.rb +2 -2
- data/lib/nanoc/base/services/outdatedness_rules/rules_modified.rb +3 -3
- data/lib/nanoc/base/services/outdatedness_rules/uses_always_outdated_filter.rb +2 -2
- data/lib/nanoc/base/services/pruner.rb +1 -1
- data/lib/nanoc/base/views/view_context_for_compilation.rb +1 -1
- data/lib/nanoc/base/views/view_context_for_pre_compilation.rb +1 -1
- data/lib/nanoc/base/views/view_context_for_shell.rb +2 -2
- data/lib/nanoc/checking/check.rb +17 -1
- data/lib/nanoc/cli/commands/shell.rb +1 -1
- data/lib/nanoc/cli/error_handler.rb +1 -1
- data/lib/nanoc/filters/handlebars.rb +2 -2
- data/lib/nanoc/filters/sass/importer.rb +3 -2
- data/lib/nanoc/rule_dsl/action_provider.rb +1 -1
- data/lib/nanoc/spec.rb +4 -4
- data/lib/nanoc/version.rb +1 -1
- metadata +5 -21
- data/lib/nanoc/base/entities.rb +0 -7
- data/lib/nanoc/base/entities/outdatedness_reasons.rb +0 -88
- data/lib/nanoc/base/entities/outdatedness_status.rb +0 -27
- data/lib/nanoc/base/repos/action_sequence_store.rb +0 -50
- data/lib/nanoc/base/repos/binary_compiled_content_cache.rb +0 -128
- data/lib/nanoc/base/repos/checksum_store.rb +0 -74
- data/lib/nanoc/base/repos/compiled_content_cache.rb +0 -68
- data/lib/nanoc/base/repos/compiled_content_store.rb +0 -77
- data/lib/nanoc/base/repos/dependency_store.rb +0 -204
- data/lib/nanoc/base/repos/item_rep_repo.rb +0 -37
- data/lib/nanoc/base/repos/outdatedness_store.rb +0 -55
- data/lib/nanoc/base/repos/prefixed_data_source.rb +0 -31
- data/lib/nanoc/base/repos/store.rb +0 -114
- data/lib/nanoc/base/repos/textual_compiled_content_cache.rb +0 -82
- data/lib/nanoc/base/services/dependency_tracker.rb +0 -63
- data/lib/nanoc/base/services/outdatedness_rule.rb +0 -34
@@ -1,128 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# Represents a cache than can be used to store already compiled content,
|
6
|
-
# to prevent it from being needlessly recompiled.
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
class BinaryCompiledContentCache < ::Nanoc::Int::Store
|
10
|
-
include Nanoc::Core::ContractsSupport
|
11
|
-
|
12
|
-
contract C::KeywordArgs[config: Nanoc::Core::Configuration] => C::Any
|
13
|
-
def initialize(config:)
|
14
|
-
super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'binary_content'), 1)
|
15
|
-
|
16
|
-
@cache = {}
|
17
|
-
end
|
18
|
-
|
19
|
-
contract Nanoc::Core::ItemRep => C::Maybe[C::HashOf[Symbol => Nanoc::Core::Content]]
|
20
|
-
# Returns the cached compiled content for the given item representation.
|
21
|
-
#
|
22
|
-
# This cached compiled content is a hash where the keys are the snapshot
|
23
|
-
# names, and the values the compiled content at the given snapshot.
|
24
|
-
def [](rep)
|
25
|
-
item_cache = @cache[rep.item.identifier] || {}
|
26
|
-
|
27
|
-
rep_cache = item_cache[rep.name]
|
28
|
-
return nil if rep_cache.nil?
|
29
|
-
|
30
|
-
rep_cache.transform_values do |filename|
|
31
|
-
Nanoc::Core::Content.create(filename, binary: true)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
contract Nanoc::Core::ItemRep => C::Bool
|
36
|
-
def include?(rep)
|
37
|
-
item_cache = @cache[rep.item.identifier] || {}
|
38
|
-
item_cache.key?(rep.name)
|
39
|
-
end
|
40
|
-
|
41
|
-
contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::BinaryContent] => C::HashOf[Symbol => Nanoc::Core::Content]
|
42
|
-
# Sets the compiled content for the given representation.
|
43
|
-
#
|
44
|
-
# This cached compiled content is a hash where the keys are the snapshot
|
45
|
-
# names, and the values the compiled content at the given snapshot.
|
46
|
-
def []=(rep, content)
|
47
|
-
@cache[rep.item.identifier] ||= {}
|
48
|
-
@cache[rep.item.identifier][rep.name] ||= {}
|
49
|
-
rep_cache = @cache[rep.item.identifier][rep.name]
|
50
|
-
|
51
|
-
content.each do |snapshot, binary_content|
|
52
|
-
filename = build_filename(rep, snapshot)
|
53
|
-
rep_cache[snapshot] = filename
|
54
|
-
|
55
|
-
# Avoid reassigning the same content if this binary cached content was
|
56
|
-
# already used, because it was available and the item wasn’t oudated.
|
57
|
-
next if binary_content.filename == filename
|
58
|
-
|
59
|
-
# Copy
|
60
|
-
#
|
61
|
-
# NOTE: hardlinking is not an option in this case, because hardlinking
|
62
|
-
# would make it possible for the content to be (inadvertently)
|
63
|
-
# changed outside of Nanoc.
|
64
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
65
|
-
FileUtils.cp(binary_content.filename, filename)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def prune(items:)
|
70
|
-
item_identifiers = Set.new(items.map(&:identifier))
|
71
|
-
|
72
|
-
@cache.each_key do |key|
|
73
|
-
# TODO: remove unused item reps
|
74
|
-
next if item_identifiers.include?(key)
|
75
|
-
|
76
|
-
@cache.delete(key)
|
77
|
-
path = dirname_for_item_identifier(key)
|
78
|
-
FileUtils.rm_rf(path)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def data
|
83
|
-
@cache
|
84
|
-
end
|
85
|
-
|
86
|
-
def data=(new_data)
|
87
|
-
@cache = {}
|
88
|
-
|
89
|
-
new_data.each_pair do |item_identifier, content_per_rep|
|
90
|
-
@cache[item_identifier] ||= content_per_rep
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def dirname
|
97
|
-
filename + '_data'
|
98
|
-
end
|
99
|
-
|
100
|
-
def string_to_path_component(string)
|
101
|
-
string.gsub(/[^a-zA-Z0-9]+/, '_') +
|
102
|
-
'-' +
|
103
|
-
Digest::SHA1.hexdigest(string)[0..9]
|
104
|
-
end
|
105
|
-
|
106
|
-
def dirname_for_item_identifier(item_identifier)
|
107
|
-
File.join(
|
108
|
-
dirname,
|
109
|
-
string_to_path_component(item_identifier.to_s),
|
110
|
-
)
|
111
|
-
end
|
112
|
-
|
113
|
-
def dirname_for_item_rep(rep)
|
114
|
-
File.join(
|
115
|
-
dirname_for_item_identifier(rep.item.identifier),
|
116
|
-
string_to_path_component(rep.name.to_s),
|
117
|
-
)
|
118
|
-
end
|
119
|
-
|
120
|
-
def build_filename(rep, snapshot_name)
|
121
|
-
File.join(
|
122
|
-
dirname_for_item_rep(rep),
|
123
|
-
string_to_path_component(snapshot_name.to_s),
|
124
|
-
)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# Stores checksums for objects in order to be able to detect whether a file
|
6
|
-
# has changed since the last site compilation.
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
class ChecksumStore < ::Nanoc::Int::Store
|
10
|
-
include Nanoc::Core::ContractsSupport
|
11
|
-
|
12
|
-
attr_writer :checksums
|
13
|
-
attr_accessor :objects
|
14
|
-
|
15
|
-
c_obj = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::CodeSnippet]
|
16
|
-
|
17
|
-
contract C::KeywordArgs[config: Nanoc::Core::Configuration, objects: C::IterOf[c_obj]] => C::Any
|
18
|
-
def initialize(config:, objects:)
|
19
|
-
super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'checksums'), 2)
|
20
|
-
|
21
|
-
@objects = objects
|
22
|
-
|
23
|
-
@checksums = {}
|
24
|
-
end
|
25
|
-
|
26
|
-
contract c_obj => C::Maybe[String]
|
27
|
-
def [](obj)
|
28
|
-
@checksums[obj.reference]
|
29
|
-
end
|
30
|
-
|
31
|
-
contract c_obj => self
|
32
|
-
def add(obj)
|
33
|
-
if obj.is_a?(Nanoc::Core::Document)
|
34
|
-
@checksums[[obj.reference, :content]] = Nanoc::Core::Checksummer.calc_for_content_of(obj)
|
35
|
-
end
|
36
|
-
|
37
|
-
if obj.is_a?(Nanoc::Core::Document) || obj.is_a?(Nanoc::Core::Configuration)
|
38
|
-
@checksums[[obj.reference, :each_attribute]] = Nanoc::Core::Checksummer.calc_for_each_attribute_of(obj)
|
39
|
-
end
|
40
|
-
|
41
|
-
@checksums[obj.reference] = Nanoc::Core::Checksummer.calc(obj)
|
42
|
-
|
43
|
-
self
|
44
|
-
end
|
45
|
-
|
46
|
-
contract c_obj => C::Maybe[String]
|
47
|
-
def content_checksum_for(obj)
|
48
|
-
@checksums[[obj.reference, :content]]
|
49
|
-
end
|
50
|
-
|
51
|
-
contract c_obj => C::Maybe[C::HashOf[Symbol, String]]
|
52
|
-
def attributes_checksum_for(obj)
|
53
|
-
@checksums[[obj.reference, :each_attribute]]
|
54
|
-
end
|
55
|
-
|
56
|
-
protected
|
57
|
-
|
58
|
-
def data
|
59
|
-
@checksums
|
60
|
-
end
|
61
|
-
|
62
|
-
def data=(new_data)
|
63
|
-
references = Set.new(@objects.map(&:reference))
|
64
|
-
|
65
|
-
@checksums = {}
|
66
|
-
new_data.each_pair do |key, checksum|
|
67
|
-
if references.include?(key) || references.include?(key.first)
|
68
|
-
@checksums[key] = checksum
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# Represents a cache than can be used to store already compiled content,
|
6
|
-
# to prevent it from being needlessly recompiled.
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
class CompiledContentCache < ::Nanoc::Int::Store
|
10
|
-
include Nanoc::Core::ContractsSupport
|
11
|
-
|
12
|
-
contract C::KeywordArgs[config: Nanoc::Core::Configuration] => C::Any
|
13
|
-
def initialize(config:)
|
14
|
-
@textual_cache = Nanoc::Int::TextualCompiledContentCache.new(config: config)
|
15
|
-
@binary_cache = Nanoc::Int::BinaryCompiledContentCache.new(config: config)
|
16
|
-
|
17
|
-
@wrapped_caches = [@textual_cache, @binary_cache]
|
18
|
-
end
|
19
|
-
|
20
|
-
contract Nanoc::Core::ItemRep => C::Maybe[C::HashOf[Symbol => Nanoc::Core::Content]]
|
21
|
-
# Returns the cached compiled content for the given item representation.
|
22
|
-
#
|
23
|
-
# This cached compiled content is a hash where the keys are the snapshot
|
24
|
-
# names. and the values the compiled content at the given snapshot.
|
25
|
-
def [](rep)
|
26
|
-
textual_content_map = @textual_cache[rep]
|
27
|
-
binary_content_map = @binary_cache[rep]
|
28
|
-
|
29
|
-
# If either the textual or the binary content cache is nil, assume the
|
30
|
-
# cache is entirely absent.
|
31
|
-
#
|
32
|
-
# This is necessary to support the case where only textual content is
|
33
|
-
# cached (which was the case in older versions of Nanoc).
|
34
|
-
return nil if [textual_content_map, binary_content_map].any?(&:nil?)
|
35
|
-
|
36
|
-
textual_content_map.merge(binary_content_map)
|
37
|
-
end
|
38
|
-
|
39
|
-
contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::Content] => C::Any
|
40
|
-
# Sets the compiled content for the given representation.
|
41
|
-
#
|
42
|
-
# This cached compiled content is a hash where the keys are the snapshot
|
43
|
-
# names and the values the compiled content at the given snapshot.
|
44
|
-
def []=(rep, content)
|
45
|
-
@textual_cache[rep] = content.select { |_key, c| c.textual? }
|
46
|
-
@binary_cache[rep] = content.select { |_key, c| c.binary? }
|
47
|
-
end
|
48
|
-
|
49
|
-
def prune(*args)
|
50
|
-
@wrapped_caches.each { |w| w.prune(*args) }
|
51
|
-
end
|
52
|
-
|
53
|
-
# True if there is cached compiled content available for this item, and
|
54
|
-
# all entries are present (either textual or binary).
|
55
|
-
def full_cache_available?(rep)
|
56
|
-
@textual_cache.include?(rep) && @binary_cache.include?(rep)
|
57
|
-
end
|
58
|
-
|
59
|
-
def load(*args)
|
60
|
-
@wrapped_caches.each { |w| w.load(*args) }
|
61
|
-
end
|
62
|
-
|
63
|
-
def store(*args)
|
64
|
-
@wrapped_caches.each { |w| w.store(*args) }
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# @api private
|
6
|
-
class CompiledContentStore
|
7
|
-
include Nanoc::Core::ContractsSupport
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@contents = Hash.new { |hash, rep| hash[rep] = {} }
|
11
|
-
@current_content = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
contract Nanoc::Core::ItemRep, Symbol => C::Maybe[Nanoc::Core::Content]
|
15
|
-
def get(rep, snapshot_name)
|
16
|
-
@contents[rep][snapshot_name]
|
17
|
-
end
|
18
|
-
|
19
|
-
contract Nanoc::Core::ItemRep => C::Maybe[Nanoc::Core::Content]
|
20
|
-
def get_current(rep)
|
21
|
-
@current_content[rep]
|
22
|
-
end
|
23
|
-
|
24
|
-
contract Nanoc::Core::ItemRep, Symbol, Nanoc::Core::Content => C::Any
|
25
|
-
def set(rep, snapshot_name, contents)
|
26
|
-
@contents[rep][snapshot_name] = contents
|
27
|
-
end
|
28
|
-
|
29
|
-
contract Nanoc::Core::ItemRep, Nanoc::Core::Content => C::Any
|
30
|
-
def set_current(rep, content)
|
31
|
-
@current_content[rep] = content
|
32
|
-
end
|
33
|
-
|
34
|
-
contract Nanoc::Core::ItemRep => C::HashOf[Symbol => Nanoc::Core::Content]
|
35
|
-
def get_all(rep)
|
36
|
-
@contents[rep]
|
37
|
-
end
|
38
|
-
|
39
|
-
contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::Content] => C::Any
|
40
|
-
def set_all(rep, contents_per_snapshot)
|
41
|
-
@contents[rep] = contents_per_snapshot
|
42
|
-
end
|
43
|
-
|
44
|
-
contract C::KeywordArgs[rep: Nanoc::Core::ItemRep, snapshot: C::Optional[C::Maybe[Symbol]]] => Nanoc::Core::Content
|
45
|
-
def raw_compiled_content(rep:, snapshot: nil)
|
46
|
-
# Get name of last pre-layout snapshot
|
47
|
-
has_pre = rep.snapshot_defs.any? { |sd| sd.name == :pre }
|
48
|
-
snapshot_name = snapshot || (has_pre ? :pre : :last)
|
49
|
-
|
50
|
-
# Check existance of snapshot
|
51
|
-
snapshot_def = rep.snapshot_defs.reverse.find { |sd| sd.name == snapshot_name }
|
52
|
-
unless snapshot_def
|
53
|
-
raise Nanoc::Int::Errors::NoSuchSnapshot.new(rep, snapshot_name)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Return content if it is available
|
57
|
-
content = get(rep, snapshot_name)
|
58
|
-
return content if content
|
59
|
-
|
60
|
-
# Content is unavailable; notify and try again
|
61
|
-
Fiber.yield(Nanoc::Int::Errors::UnmetDependency.new(rep, snapshot_name))
|
62
|
-
get(rep, snapshot_name)
|
63
|
-
end
|
64
|
-
|
65
|
-
contract C::KeywordArgs[rep: Nanoc::Core::ItemRep, snapshot: C::Optional[C::Maybe[Symbol]]] => String
|
66
|
-
def compiled_content(rep:, snapshot: nil)
|
67
|
-
snapshot_content = raw_compiled_content(rep: rep, snapshot: snapshot)
|
68
|
-
|
69
|
-
if snapshot_content.binary?
|
70
|
-
raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(rep)
|
71
|
-
end
|
72
|
-
|
73
|
-
snapshot_content.string
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,204 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# @api private
|
6
|
-
class DependencyStore < ::Nanoc::Int::Store
|
7
|
-
include Nanoc::Core::ContractsSupport
|
8
|
-
|
9
|
-
attr_reader :items
|
10
|
-
attr_reader :layouts
|
11
|
-
|
12
|
-
contract Nanoc::Core::ItemCollection, Nanoc::Core::LayoutCollection, Nanoc::Core::Configuration => C::Any
|
13
|
-
def initialize(items, layouts, config)
|
14
|
-
super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'dependencies'), 5)
|
15
|
-
|
16
|
-
@items = items
|
17
|
-
@layouts = layouts
|
18
|
-
|
19
|
-
@refs2objs = {}
|
20
|
-
items.each { |o| add_vertex_for(o) }
|
21
|
-
layouts.each { |o| add_vertex_for(o) }
|
22
|
-
add_vertex_for(config)
|
23
|
-
add_vertex_for(items)
|
24
|
-
add_vertex_for(layouts)
|
25
|
-
|
26
|
-
@new_objects = []
|
27
|
-
@graph = Nanoc::Core::DirectedGraph.new([nil] + objs2refs(@items) + objs2refs(@layouts))
|
28
|
-
end
|
29
|
-
|
30
|
-
C_OBJ_SRC = Nanoc::Core::Item
|
31
|
-
C_OBJ_DST = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::IdentifiableCollection]
|
32
|
-
|
33
|
-
contract C_OBJ_SRC => C::ArrayOf[Nanoc::Core::Dependency]
|
34
|
-
def dependencies_causing_outdatedness_of(object)
|
35
|
-
objects_causing_outdatedness_of(object).map do |other_object|
|
36
|
-
props = props_for(other_object, object)
|
37
|
-
|
38
|
-
Nanoc::Core::Dependency.new(
|
39
|
-
other_object,
|
40
|
-
object,
|
41
|
-
Nanoc::Core::DependencyProps.new(
|
42
|
-
raw_content: props.fetch(:raw_content, false),
|
43
|
-
attributes: props.fetch(:attributes, false),
|
44
|
-
compiled_content: props.fetch(:compiled_content, false),
|
45
|
-
path: props.fetch(:path, false),
|
46
|
-
),
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def items=(items)
|
52
|
-
@items = items
|
53
|
-
items.each { |o| @refs2objs[obj2ref(o)] = o }
|
54
|
-
add_vertex_for(items)
|
55
|
-
end
|
56
|
-
|
57
|
-
def layouts=(layouts)
|
58
|
-
@layouts = layouts
|
59
|
-
layouts.each { |o| @refs2objs[obj2ref(o)] = o }
|
60
|
-
add_vertex_for(layouts)
|
61
|
-
end
|
62
|
-
|
63
|
-
def new_items
|
64
|
-
@new_objects.select { |o| o.is_a?(Nanoc::Core::Item) }
|
65
|
-
end
|
66
|
-
|
67
|
-
def new_layouts
|
68
|
-
@new_objects.select { |o| o.is_a?(Nanoc::Core::Layout) }
|
69
|
-
end
|
70
|
-
|
71
|
-
# Returns the direct dependencies for the given object.
|
72
|
-
#
|
73
|
-
# The direct dependencies of the given object include the items and
|
74
|
-
# layouts that, when outdated will cause the given object to be marked as
|
75
|
-
# outdated. Indirect dependencies will not be returned (e.g. if A depends
|
76
|
-
# on B which depends on C, then the direct dependencies of A do not
|
77
|
-
# include C).
|
78
|
-
#
|
79
|
-
# The direct predecessors can include nil, which indicates an item that is
|
80
|
-
# no longer present in the site.
|
81
|
-
#
|
82
|
-
# @param [Nanoc::Core::Item, Nanoc::Core::Layout] object The object for
|
83
|
-
# which to fetch the direct predecessors
|
84
|
-
#
|
85
|
-
# @return [Array<Nanoc::Core::Item, Nanoc::Core::Layout, nil>] The direct
|
86
|
-
# predecessors of
|
87
|
-
# the given object
|
88
|
-
def objects_causing_outdatedness_of(object)
|
89
|
-
refs2objs(@graph.direct_predecessors_of(obj2ref(object)))
|
90
|
-
end
|
91
|
-
|
92
|
-
C_RAW_CONTENT = C::Or[C::IterOf[C::Or[String, Regexp]], C::Bool]
|
93
|
-
C_ATTR = C::Or[C::IterOf[Symbol], C::Bool]
|
94
|
-
C_KEYWORD_PROPS = C::KeywordArgs[raw_content: C::Optional[C_RAW_CONTENT], attributes: C::Optional[C_ATTR], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]]
|
95
|
-
|
96
|
-
contract C::Maybe[C_OBJ_SRC], C::Maybe[C_OBJ_DST], C_KEYWORD_PROPS => C::Any
|
97
|
-
# Records a dependency from `src` to `dst` in the dependency graph. When
|
98
|
-
# `dst` is oudated, `src` will also become outdated.
|
99
|
-
#
|
100
|
-
# @param [Nanoc::Core::Item, Nanoc::Core::Layout] src The source of the dependency,
|
101
|
-
# i.e. the object that will become outdated if dst is outdated
|
102
|
-
#
|
103
|
-
# @param [Nanoc::Core::Item, Nanoc::Core::Layout] dst The destination of the
|
104
|
-
# dependency, i.e. the object that will cause the source to become
|
105
|
-
# outdated if the destination is outdated
|
106
|
-
#
|
107
|
-
# @return [void]
|
108
|
-
def record_dependency(src, dst, raw_content: false, attributes: false, compiled_content: false, path: false)
|
109
|
-
return if src == dst
|
110
|
-
|
111
|
-
add_vertex_for(src)
|
112
|
-
add_vertex_for(dst)
|
113
|
-
|
114
|
-
src_ref = obj2ref(src)
|
115
|
-
dst_ref = obj2ref(dst)
|
116
|
-
|
117
|
-
existing_props = Nanoc::Core::DependencyProps.new(@graph.props_for(dst_ref, src_ref) || {})
|
118
|
-
new_props = Nanoc::Core::DependencyProps.new(raw_content: raw_content, attributes: attributes, compiled_content: compiled_content, path: path)
|
119
|
-
props = existing_props.merge(new_props)
|
120
|
-
|
121
|
-
@graph.add_edge(dst_ref, src_ref, props: props.to_h)
|
122
|
-
end
|
123
|
-
|
124
|
-
def add_vertex_for(obj)
|
125
|
-
@refs2objs[obj2ref(obj)] = obj
|
126
|
-
end
|
127
|
-
|
128
|
-
# Empties the list of dependencies for the given object. This is necessary
|
129
|
-
# before recompiling the given object, because otherwise old dependencies
|
130
|
-
# will stick around and new dependencies will appear twice. This function
|
131
|
-
# removes all incoming edges for the given vertex.
|
132
|
-
#
|
133
|
-
# @param [Nanoc::Core::Item, Nanoc::Core::Layout] object The object for which to
|
134
|
-
# forget all dependencies
|
135
|
-
#
|
136
|
-
# @return [void]
|
137
|
-
def forget_dependencies_for(object)
|
138
|
-
@graph.delete_edges_to(obj2ref(object))
|
139
|
-
end
|
140
|
-
|
141
|
-
protected
|
142
|
-
|
143
|
-
def obj2ref(obj)
|
144
|
-
obj&.reference
|
145
|
-
end
|
146
|
-
|
147
|
-
def ref2obj(reference)
|
148
|
-
if reference
|
149
|
-
@refs2objs[reference]
|
150
|
-
else
|
151
|
-
nil
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def objs2refs(objs)
|
156
|
-
objs.map { |o| obj2ref(o) }
|
157
|
-
end
|
158
|
-
|
159
|
-
def refs2objs(refs)
|
160
|
-
refs.map { |r| ref2obj(r) }
|
161
|
-
end
|
162
|
-
|
163
|
-
def props_for(from, to)
|
164
|
-
props = @graph.props_for(obj2ref(from), obj2ref(to)) || {}
|
165
|
-
|
166
|
-
if props.values.any? { |v| v }
|
167
|
-
props
|
168
|
-
else
|
169
|
-
{ raw_content: true, attributes: true, compiled_content: true, path: true }
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def data
|
174
|
-
{
|
175
|
-
edges: @graph.edges,
|
176
|
-
vertices: @graph.vertices,
|
177
|
-
}
|
178
|
-
end
|
179
|
-
|
180
|
-
def data=(new_data)
|
181
|
-
objects = Set.new(@items.to_a + @layouts.to_a)
|
182
|
-
refs = objs2refs(objects)
|
183
|
-
|
184
|
-
# Create new graph
|
185
|
-
@graph = Nanoc::Core::DirectedGraph.new([nil] + refs)
|
186
|
-
|
187
|
-
# Load vertices
|
188
|
-
previous_refs = new_data[:vertices]
|
189
|
-
previous_objects = Set.new(refs2objs(previous_refs))
|
190
|
-
|
191
|
-
# Load edges
|
192
|
-
new_data[:edges].each do |edge|
|
193
|
-
from_index, to_index, props = *edge
|
194
|
-
from = from_index && previous_refs[from_index]
|
195
|
-
to = to_index && previous_refs[to_index]
|
196
|
-
@graph.add_edge(from, to, props: props)
|
197
|
-
end
|
198
|
-
|
199
|
-
# Record dependency from all items on new items
|
200
|
-
@new_objects = objects - previous_objects
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|