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,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# Stores item reps (in memory).
|
6
|
-
#
|
7
|
-
# @api private
|
8
|
-
class ItemRepRepo
|
9
|
-
include Enumerable
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@reps = []
|
13
|
-
@reps_by_item = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def <<(rep)
|
17
|
-
@reps << rep
|
18
|
-
|
19
|
-
@reps_by_item[rep.item] ||= []
|
20
|
-
@reps_by_item[rep.item] << rep
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_a
|
24
|
-
@reps
|
25
|
-
end
|
26
|
-
|
27
|
-
def each(&block)
|
28
|
-
@reps.each(&block)
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def [](item)
|
33
|
-
@reps_by_item.fetch(item, [])
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# @api private
|
6
|
-
class OutdatednessStore < ::Nanoc::Int::Store
|
7
|
-
include Nanoc::Core::ContractsSupport
|
8
|
-
|
9
|
-
contract C::KeywordArgs[config: Nanoc::Core::Configuration] => C::Any
|
10
|
-
def initialize(config:)
|
11
|
-
super(Nanoc::Int::Store.tmp_path_for(config: config, store_name: 'outdatedness'), 1)
|
12
|
-
|
13
|
-
@outdated_refs = Set.new
|
14
|
-
end
|
15
|
-
|
16
|
-
contract Nanoc::Core::ItemRep => C::Bool
|
17
|
-
def include?(obj)
|
18
|
-
@outdated_refs.include?(obj.reference)
|
19
|
-
end
|
20
|
-
|
21
|
-
contract Nanoc::Core::ItemRep => self
|
22
|
-
def add(obj)
|
23
|
-
@outdated_refs << obj.reference
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
|
-
contract Nanoc::Core::ItemRep => self
|
28
|
-
def remove(obj)
|
29
|
-
@outdated_refs.delete(obj.reference)
|
30
|
-
self
|
31
|
-
end
|
32
|
-
|
33
|
-
contract C::None => C::Bool
|
34
|
-
def empty?
|
35
|
-
@outdated_refs.empty?
|
36
|
-
end
|
37
|
-
|
38
|
-
contract C::None => self
|
39
|
-
def clear
|
40
|
-
@outdated_refs = Set.new
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
protected
|
45
|
-
|
46
|
-
def data
|
47
|
-
@outdated_refs
|
48
|
-
end
|
49
|
-
|
50
|
-
def data=(new_data)
|
51
|
-
@outdated_refs = Set.new(new_data)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
class PrefixedDataSource < Nanoc::DataSource
|
6
|
-
def initialize(data_source, items_prefix, layouts_prefix)
|
7
|
-
super({}, '/', '/', {})
|
8
|
-
|
9
|
-
@data_source = data_source
|
10
|
-
@items_prefix = items_prefix
|
11
|
-
@layouts_prefix = layouts_prefix
|
12
|
-
end
|
13
|
-
|
14
|
-
def items
|
15
|
-
@data_source.items.map { |d| d.with_identifier_prefix(@items_prefix) }
|
16
|
-
end
|
17
|
-
|
18
|
-
def layouts
|
19
|
-
@data_source.layouts.map { |d| d.with_identifier_prefix(@layouts_prefix) }
|
20
|
-
end
|
21
|
-
|
22
|
-
def item_changes
|
23
|
-
@data_source.item_changes
|
24
|
-
end
|
25
|
-
|
26
|
-
def layout_changes
|
27
|
-
@data_source.layout_changes
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# An abstract superclass for classes that need to store data to the
|
6
|
-
# filesystem, such as checksums, cached compiled content and dependency
|
7
|
-
# graphs.
|
8
|
-
#
|
9
|
-
# Each store has a version number. When attempting to load data from a store
|
10
|
-
# that has an incompatible version number, no data will be loaded, but
|
11
|
-
# {#version_mismatch_detected} will be called.
|
12
|
-
#
|
13
|
-
# @abstract Subclasses must implement {#data} and {#data=}, and may
|
14
|
-
# implement {#no_data_found} and {#version_mismatch_detected}.
|
15
|
-
#
|
16
|
-
# @api private
|
17
|
-
class Store
|
18
|
-
include Nanoc::Core::ContractsSupport
|
19
|
-
|
20
|
-
# @return [String] The name of the file where data will be loaded from and
|
21
|
-
# stored to.
|
22
|
-
attr_reader :filename
|
23
|
-
|
24
|
-
# @return [Numeric] The version number corresponding to the file format
|
25
|
-
# the data is in. When the file format changes, the version number
|
26
|
-
# should be incremented.
|
27
|
-
attr_reader :version
|
28
|
-
|
29
|
-
# Creates a new store for the given filename.
|
30
|
-
#
|
31
|
-
# @param [String] filename The name of the file where data will be loaded
|
32
|
-
# from and stored to.
|
33
|
-
#
|
34
|
-
# @param [Numeric] version The version number corresponding to the file
|
35
|
-
# format the data is in. When the file format changes, the version
|
36
|
-
# number should be incremented.
|
37
|
-
def initialize(filename, version)
|
38
|
-
@filename = filename
|
39
|
-
@version = version
|
40
|
-
end
|
41
|
-
|
42
|
-
# Logic for building tmp path from active environment and store name
|
43
|
-
# @api private
|
44
|
-
contract C::KeywordArgs[config: Nanoc::Core::Configuration, store_name: String] => C::AbsolutePathString
|
45
|
-
def self.tmp_path_for(store_name:, config:)
|
46
|
-
File.absolute_path(
|
47
|
-
File.join(tmp_path_prefix(config.output_dir), store_name),
|
48
|
-
config.dir,
|
49
|
-
)
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.tmp_path_prefix(output_dir)
|
53
|
-
dir = Digest::SHA1.hexdigest(output_dir)[0..12]
|
54
|
-
File.join('tmp', 'nanoc', dir)
|
55
|
-
end
|
56
|
-
|
57
|
-
# @group Loading and storing data
|
58
|
-
|
59
|
-
# @return The data that should be written to the disk
|
60
|
-
#
|
61
|
-
# @abstract This method must be implemented by the subclass.
|
62
|
-
def data
|
63
|
-
raise NotImplementedError.new('Nanoc::Int::Store subclasses must implement #data and #data=')
|
64
|
-
end
|
65
|
-
|
66
|
-
# @param new_data The data that has been loaded from the disk
|
67
|
-
#
|
68
|
-
# @abstract This method must be implemented by the subclass.
|
69
|
-
#
|
70
|
-
# @return [void]
|
71
|
-
def data=(new_data) # rubocop:disable Lint/UnusedMethodArgument
|
72
|
-
raise NotImplementedError.new('Nanoc::Int::Store subclasses must implement #data and #data=')
|
73
|
-
end
|
74
|
-
|
75
|
-
# Loads the data from the filesystem into memory. This method will set the
|
76
|
-
# loaded data using the {#data=} method.
|
77
|
-
#
|
78
|
-
# @return [void]
|
79
|
-
def load
|
80
|
-
return unless File.file?(filename)
|
81
|
-
|
82
|
-
begin
|
83
|
-
pstore.transaction do
|
84
|
-
return if pstore[:version] != version
|
85
|
-
|
86
|
-
self.data = pstore[:data]
|
87
|
-
end
|
88
|
-
rescue
|
89
|
-
FileUtils.rm_f(filename)
|
90
|
-
load
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Stores the data contained in memory to the filesystem. This method will
|
95
|
-
# use the {#data} method to fetch the data that should be written.
|
96
|
-
#
|
97
|
-
# @return [void]
|
98
|
-
def store
|
99
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
100
|
-
|
101
|
-
pstore.transaction do
|
102
|
-
pstore[:data] = data
|
103
|
-
pstore[:version] = version
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def pstore
|
110
|
-
@pstore ||= PStore.new(filename)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,82 +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 TextualCompiledContentCache < ::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: 'compiled_content'), 2)
|
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
|
-
item_cache[rep.name]
|
27
|
-
end
|
28
|
-
|
29
|
-
contract Nanoc::Core::ItemRep => C::Bool
|
30
|
-
def include?(rep)
|
31
|
-
item_cache = @cache[rep.item.identifier] || {}
|
32
|
-
item_cache.key?(rep.name)
|
33
|
-
end
|
34
|
-
|
35
|
-
contract Nanoc::Core::ItemRep, C::HashOf[Symbol => Nanoc::Core::Content] => C::Any
|
36
|
-
# Sets the compiled content for the given representation.
|
37
|
-
#
|
38
|
-
# This cached compiled content is a hash where the keys are the snapshot
|
39
|
-
# names, and the values the compiled content at the given snapshot.
|
40
|
-
def []=(rep, content)
|
41
|
-
# FIXME: once the binary content cache is properly enabled (no longer
|
42
|
-
# behind a feature flag), change contract to be TextualContent, rather
|
43
|
-
# than Content.
|
44
|
-
|
45
|
-
@cache[rep.item.identifier] ||= {}
|
46
|
-
@cache[rep.item.identifier][rep.name] = content
|
47
|
-
end
|
48
|
-
|
49
|
-
def prune(items:)
|
50
|
-
item_identifiers = Set.new(items.map(&:identifier))
|
51
|
-
|
52
|
-
@cache.each_key do |key|
|
53
|
-
# TODO: remove unused item reps
|
54
|
-
next if item_identifiers.include?(key)
|
55
|
-
|
56
|
-
@cache.delete(key)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# True if there is cached compiled content available for this item, and
|
61
|
-
# all entries are textual.
|
62
|
-
def full_cache_available?(rep)
|
63
|
-
cache = self[rep]
|
64
|
-
cache ? cache.none? { |_snapshot_name, content| content.binary? } : false
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
def data
|
70
|
-
@cache
|
71
|
-
end
|
72
|
-
|
73
|
-
def data=(new_data)
|
74
|
-
@cache = {}
|
75
|
-
|
76
|
-
new_data.each_pair do |item_identifier, content_per_rep|
|
77
|
-
@cache[item_identifier] ||= content_per_rep
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# @api private
|
6
|
-
class DependencyTracker
|
7
|
-
include Nanoc::Core::ContractsSupport
|
8
|
-
|
9
|
-
C_OBJ = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::IdentifiableCollection]
|
10
|
-
C_RAW_CONTENT = C::Or[C::IterOf[C::Or[String, Regexp]], C::Bool]
|
11
|
-
C_ATTR = C::Or[C::IterOf[Symbol], C::Bool]
|
12
|
-
C_ARGS = 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]]
|
13
|
-
|
14
|
-
class Null
|
15
|
-
include Nanoc::Core::ContractsSupport
|
16
|
-
|
17
|
-
contract C_OBJ, C_ARGS => C::Any
|
18
|
-
def enter(_obj, raw_content: false, attributes: false, compiled_content: false, path: false); end
|
19
|
-
|
20
|
-
contract C_OBJ => C::Any
|
21
|
-
def exit; end
|
22
|
-
|
23
|
-
contract C_OBJ, C_ARGS => C::Any
|
24
|
-
def bounce(_obj, raw_content: false, attributes: false, compiled_content: false, path: false); end
|
25
|
-
end
|
26
|
-
|
27
|
-
attr_reader :dependency_store
|
28
|
-
|
29
|
-
def initialize(dependency_store)
|
30
|
-
@dependency_store = dependency_store
|
31
|
-
@stack = []
|
32
|
-
end
|
33
|
-
|
34
|
-
contract C_OBJ, C_ARGS => C::Any
|
35
|
-
def enter(obj, raw_content: false, attributes: false, compiled_content: false, path: false)
|
36
|
-
unless @stack.empty?
|
37
|
-
Nanoc::Core::NotificationCenter.post(:dependency_created, @stack.last, obj)
|
38
|
-
@dependency_store.record_dependency(
|
39
|
-
@stack.last,
|
40
|
-
obj,
|
41
|
-
raw_content: raw_content,
|
42
|
-
attributes: attributes,
|
43
|
-
compiled_content: compiled_content,
|
44
|
-
path: path,
|
45
|
-
)
|
46
|
-
end
|
47
|
-
|
48
|
-
@stack.push(obj)
|
49
|
-
end
|
50
|
-
|
51
|
-
contract C_OBJ => C::Any
|
52
|
-
def exit
|
53
|
-
@stack.pop
|
54
|
-
end
|
55
|
-
|
56
|
-
contract C_OBJ, C_ARGS => C::Any
|
57
|
-
def bounce(obj, raw_content: false, attributes: false, compiled_content: false, path: false)
|
58
|
-
enter(obj, raw_content: raw_content, attributes: attributes, compiled_content: compiled_content, path: path)
|
59
|
-
exit
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# @api private
|
6
|
-
class OutdatednessRule
|
7
|
-
include Nanoc::Core::ContractsSupport
|
8
|
-
include Singleton
|
9
|
-
|
10
|
-
def call(obj, outdatedness_checker)
|
11
|
-
Nanoc::Core::Instrumentor.call(:outdatedness_rule_ran, self.class) do
|
12
|
-
apply(obj, outdatedness_checker)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def apply(_obj, _outdatedness_checker)
|
17
|
-
raise NotImplementedError.new('Nanoc::Int::OutdatednessRule subclasses must implement #apply')
|
18
|
-
end
|
19
|
-
|
20
|
-
contract C::None => String
|
21
|
-
def inspect
|
22
|
-
"#{self.class.name}(#{reason})"
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.affects_props(*names)
|
26
|
-
@affected_props = Set.new(names)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.affected_props
|
30
|
-
@affected_props
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|