nanoc-core 4.11.12 → 4.11.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nanoc/core.rb +37 -0
  3. data/lib/nanoc/core/basic_item_rep_collection_view.rb +88 -0
  4. data/lib/nanoc/core/basic_item_rep_view.rb +83 -0
  5. data/lib/nanoc/core/basic_item_view.rb +54 -0
  6. data/lib/nanoc/core/changes_stream.rb +55 -0
  7. data/lib/nanoc/core/checksum_store.rb +1 -1
  8. data/lib/nanoc/core/checksummer.rb +4 -2
  9. data/lib/nanoc/core/compilation_item_rep_collection_view.rb +12 -0
  10. data/lib/nanoc/core/compilation_item_rep_view.rb +57 -0
  11. data/lib/nanoc/core/compilation_item_view.rb +47 -0
  12. data/lib/nanoc/core/compilation_phases/abstract.rb +48 -0
  13. data/lib/nanoc/core/compilation_phases/cache.rb +43 -0
  14. data/lib/nanoc/core/compilation_phases/mark_done.rb +23 -0
  15. data/lib/nanoc/core/compilation_phases/notify.rb +19 -0
  16. data/lib/nanoc/core/compilation_phases/recalculate.rb +49 -0
  17. data/lib/nanoc/core/compilation_phases/resume.rb +52 -0
  18. data/lib/nanoc/core/compilation_phases/write.rb +84 -0
  19. data/lib/nanoc/core/compilation_stages/build_reps.rb +36 -0
  20. data/lib/nanoc/core/compilation_stages/calculate_checksums.rb +42 -0
  21. data/lib/nanoc/core/compilation_stages/cleanup.rb +43 -0
  22. data/lib/nanoc/core/compilation_stages/compile_reps.rb +96 -0
  23. data/lib/nanoc/core/compilation_stages/determine_outdatedness.rb +49 -0
  24. data/lib/nanoc/core/compilation_stages/forget_outdated_dependencies.rb +20 -0
  25. data/lib/nanoc/core/compilation_stages/load_stores.rb +35 -0
  26. data/lib/nanoc/core/compilation_stages/postprocess.rb +21 -0
  27. data/lib/nanoc/core/compilation_stages/preprocess.rb +32 -0
  28. data/lib/nanoc/core/compilation_stages/prune.rb +30 -0
  29. data/lib/nanoc/core/compilation_stages/store_post_compilation_state.rb +20 -0
  30. data/lib/nanoc/core/compilation_stages/store_pre_compilation_state.rb +32 -0
  31. data/lib/nanoc/core/compiled_content_cache.rb +2 -2
  32. data/lib/nanoc/core/compiler.rb +214 -0
  33. data/lib/nanoc/core/compiler_loader.rb +48 -0
  34. data/lib/nanoc/core/config_loader.rb +95 -0
  35. data/lib/nanoc/core/config_view.rb +67 -0
  36. data/lib/nanoc/core/configuration.rb +2 -4
  37. data/lib/nanoc/core/contracts_support.rb +20 -0
  38. data/lib/nanoc/core/dependency_store.rb +3 -3
  39. data/lib/nanoc/core/document_view_mixin.rb +87 -0
  40. data/lib/nanoc/core/errors.rb +108 -0
  41. data/lib/nanoc/core/executor.rb +134 -0
  42. data/lib/nanoc/core/feature.rb +92 -0
  43. data/lib/nanoc/core/filter.rb +269 -0
  44. data/lib/nanoc/core/identifiable_collection_view.rb +111 -0
  45. data/lib/nanoc/core/item_collection_with_reps_view.rb +12 -0
  46. data/lib/nanoc/core/item_collection_without_reps_view.rb +12 -0
  47. data/lib/nanoc/core/item_rep_builder.rb +54 -0
  48. data/lib/nanoc/core/item_rep_selector.rb +67 -0
  49. data/lib/nanoc/core/item_rep_writer.rb +85 -0
  50. data/lib/nanoc/core/layout_collection_view.rb +12 -0
  51. data/lib/nanoc/core/layout_view.rb +9 -0
  52. data/lib/nanoc/core/mutable_config_view.rb +16 -0
  53. data/lib/nanoc/core/mutable_document_view_mixin.rb +60 -0
  54. data/lib/nanoc/core/mutable_identifiable_collection_view.rb +19 -0
  55. data/lib/nanoc/core/mutable_item_collection_view.rb +34 -0
  56. data/lib/nanoc/core/mutable_item_view.rb +9 -0
  57. data/lib/nanoc/core/mutable_layout_collection_view.rb +26 -0
  58. data/lib/nanoc/core/mutable_layout_view.rb +9 -0
  59. data/lib/nanoc/core/outdatedness_checker.rb +222 -0
  60. data/lib/nanoc/core/outdatedness_rules/attributes_modified.rb +41 -0
  61. data/lib/nanoc/core/outdatedness_rules/code_snippets_modified.rb +31 -0
  62. data/lib/nanoc/core/outdatedness_rules/content_modified.rb +21 -0
  63. data/lib/nanoc/core/outdatedness_rules/item_collection_extended.rb +20 -0
  64. data/lib/nanoc/core/outdatedness_rules/layout_collection_extended.rb +20 -0
  65. data/lib/nanoc/core/outdatedness_rules/not_written.rb +17 -0
  66. data/lib/nanoc/core/outdatedness_rules/rules_modified.rb +45 -0
  67. data/lib/nanoc/core/outdatedness_rules/uses_always_outdated_filter.rb +26 -0
  68. data/lib/nanoc/core/post_compile_item_collection_view.rb +12 -0
  69. data/lib/nanoc/core/post_compile_item_rep_collection_view.rb +12 -0
  70. data/lib/nanoc/core/post_compile_item_rep_view.rb +33 -0
  71. data/lib/nanoc/core/post_compile_item_view.rb +20 -0
  72. data/lib/nanoc/core/pruner.rb +123 -0
  73. data/lib/nanoc/core/site_loader.rb +102 -0
  74. data/lib/nanoc/core/trivial_error.rb +10 -0
  75. data/lib/nanoc/core/version.rb +1 -1
  76. data/lib/nanoc/core/view.rb +43 -0
  77. data/lib/nanoc/core/view_context_for_compilation.rb +6 -6
  78. metadata +97 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf201905e79de9d9711910668d228863a48b53e13a78694a50122932960d6189
4
- data.tar.gz: ffae70af266ec5c189b0d09976bfb9ebada587f5ea1eeb73b12dfeaebeb07d36
3
+ metadata.gz: 748b150c5ee93de8c4ce8dcd31ddc4e4dc64897a73d86dd91be9d743b1ff476d
4
+ data.tar.gz: '008722ff9d57b3c5e13fda3e5ac60dd4860a1240076383067a37664ebb7df2ca'
5
5
  SHA512:
6
- metadata.gz: bf812e2fc282b019b2d907ee39a84fe7999b2b2f8565139cc442e3ca38cb75949ea70f27b07058ef4bd52af9a1291c0ca73e6db53790e431976a729f6a4dd3c8
7
- data.tar.gz: ef670404975dfde21013d6878afbf272e7bd41d7dee120e124cb2c61e37e1ad1f5ac64ccc1f4554f57dcde1d1303cac32ef6e088853d569c24f1c070c72abc7c
6
+ metadata.gz: 49b011afe4838c9150bd91ccaf17acd7150f5d143af69b13e623f542ff2af7965205f4b2a595b07e651babada9e902a98e2c879f923070be21c14fd199c5674d
7
+ data.tar.gz: aefeed726b1ac55565446d4fc7ccce5a3d5293029ad7b0e534e33f8f0ff338d0f7d8f9641dfd964125e5a71dbb243aa95e9cf447d071478fea03d1e2a485ea4c
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Ruby stdlib
4
+ require 'fiber'
5
+ require 'find'
4
6
  require 'pstore'
5
7
  require 'singleton'
6
8
  require 'tmpdir'
9
+ require 'yaml'
7
10
 
8
11
  # External gems
9
12
  require 'json_schema'
@@ -12,10 +15,32 @@ require 'ddmetrics'
12
15
  require 'ddplugin'
13
16
  require 'hamster'
14
17
  require 'slow_enumerator_tools'
18
+ require 'tomlrb'
19
+ require 'tty-platform'
15
20
  require 'zeitwerk'
16
21
 
17
22
  module Nanoc
18
23
  module Core
24
+ # Similar to `nil` except that it can only be compared against using
25
+ # `UNDEFINED.equal?(x)`. Used in places where `nil` already has meaning, and
26
+ # thus cannot be used to mean the presence of nothing.
27
+ UNDEFINED = Object.new
28
+
29
+ # @return [String] A string containing information about this Nanoc version
30
+ # and its environment (Ruby engine and version, Rubygems version if any).
31
+ #
32
+ # @api private
33
+ def self.version_information
34
+ "Nanoc #{Nanoc::VERSION} © 2007–2019 Denis Defreyne.\n" \
35
+ "Running #{RUBY_ENGINE} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) on #{RUBY_PLATFORM} with RubyGems #{Gem::VERSION}.\n"
36
+ end
37
+
38
+ # @return [Boolean] True if the current platform is Windows, false otherwise.
39
+ #
40
+ # @api private
41
+ def self.on_windows?
42
+ @_on_windows ||= TTY::Platform.new.windows?
43
+ end
19
44
  end
20
45
  end
21
46
 
@@ -43,3 +68,15 @@ loader.eager_load
43
68
  require_relative 'core/core_ext/array'
44
69
  require_relative 'core/core_ext/hash'
45
70
  require_relative 'core/core_ext/string'
71
+
72
+ # Tracking issue:
73
+ # https://github.com/nanoc/features/issues/24
74
+ Nanoc::Core::Feature.define('live_cmd', version: '4.11')
75
+
76
+ # Tracking issue:
77
+ # https://github.com/nanoc/features/issues/40
78
+ Nanoc::Core::Feature.define('toml', version: '4.11')
79
+
80
+ # Tracking issue:
81
+ # https://github.com/nanoc/features/issues/20
82
+ Nanoc::Core::Feature.define('binary_compiled_content_cache', version: '4.11')
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemRepCollectionView < ::Nanoc::Core::View
6
+ include Enumerable
7
+
8
+ class NoSuchItemRepError < ::Nanoc::Core::Error
9
+ def initialize(rep_name)
10
+ super("No rep named #{rep_name.inspect} was found.")
11
+ end
12
+ end
13
+
14
+ # @api private
15
+ def initialize(item_reps, context)
16
+ super(context)
17
+ @item_reps = item_reps
18
+ end
19
+
20
+ # @api private
21
+ def _unwrap
22
+ @item_reps
23
+ end
24
+
25
+ # @api private
26
+ def view_class
27
+ Nanoc::Core::BasicItemRepView
28
+ end
29
+
30
+ def to_ary
31
+ @item_reps.map { |ir| view_class.new(ir, @context) }
32
+ end
33
+
34
+ # Calls the given block once for each item rep, passing that item rep as a parameter.
35
+ #
36
+ # @yieldparam [Object] item rep view
37
+ #
38
+ # @yieldreturn [void]
39
+ #
40
+ # @return [self]
41
+ def each
42
+ @item_reps.each { |ir| yield view_class.new(ir, @context) }
43
+ self
44
+ end
45
+
46
+ # @return [Integer]
47
+ def size
48
+ @item_reps.size
49
+ end
50
+
51
+ # Return the item rep with the given name, or nil if no item rep exists.
52
+ #
53
+ # @param [Symbol] rep_name
54
+ #
55
+ # @return [nil] if no item rep with the given name was found
56
+ #
57
+ # @return [Nanoc::Core::BasicItemRepView] if an item rep with the given name was found
58
+ def [](rep_name)
59
+ case rep_name
60
+ when Symbol
61
+ res = @item_reps.find { |ir| ir.name == rep_name }
62
+ res && view_class.new(res, @context)
63
+ when Integer
64
+ raise ArgumentError, "expected BasicItemRepCollectionView#[] to be called with a symbol (you likely want `.reps[:default]` rather than `.reps[#{rep_name}]`)"
65
+ else
66
+ raise ArgumentError, 'expected BasicItemRepCollectionView#[] to be called with a symbol'
67
+ end
68
+ end
69
+
70
+ # Return the item rep with the given name, or raises an exception if there
71
+ # is no rep with the given name.
72
+ #
73
+ # @param [Symbol] rep_name
74
+ #
75
+ # @return [Nanoc::Core::BasicItemRepView]
76
+ #
77
+ # @raise if no rep was found
78
+ def fetch(rep_name)
79
+ res = @item_reps.find { |ir| ir.name == rep_name }
80
+ if res
81
+ view_class.new(res, @context)
82
+ else
83
+ raise NoSuchItemRepError.new(rep_name)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemRepView < ::Nanoc::Core::View
6
+ # @api private
7
+ def initialize(item_rep, context)
8
+ super(context)
9
+ @item_rep = item_rep
10
+ end
11
+
12
+ # @abstract
13
+ def item_view_class
14
+ Nanoc::Core::BasicItemView
15
+ end
16
+
17
+ # @api private
18
+ def _unwrap
19
+ @item_rep
20
+ end
21
+
22
+ # @see Object#==
23
+ def ==(other)
24
+ other.respond_to?(:item) && other.respond_to?(:name) && item == other.item && name == other.name
25
+ end
26
+
27
+ # @see Object#eql?
28
+ def eql?(other)
29
+ other.is_a?(self.class) &&
30
+ item.eql?(other.item) &&
31
+ name.eql?(other.name)
32
+ end
33
+
34
+ # @see Object#hash
35
+ def hash
36
+ self.class.hash ^ item.identifier.hash ^ name.hash
37
+ end
38
+
39
+ # @return [Symbol]
40
+ def name
41
+ @item_rep.name
42
+ end
43
+
44
+ def snapshot?(name)
45
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
46
+ @item_rep.snapshot?(name)
47
+ end
48
+
49
+ # Returns the item rep’s path, as used when being linked to. It starts
50
+ # with a slash and it is relative to the output directory. It does not
51
+ # include the path to the output directory. It will not include the
52
+ # filename if the filename is an index filename.
53
+ #
54
+ # @param [Symbol] snapshot The snapshot for which the path should be
55
+ # returned.
56
+ #
57
+ # @return [String] The item rep’s path.
58
+ def path(snapshot: :last)
59
+ @context.dependency_tracker.bounce(_unwrap.item, path: true)
60
+ @item_rep.path(snapshot: snapshot)
61
+ end
62
+
63
+ # Returns the item that this item rep belongs to.
64
+ #
65
+ # @return [Nanoc::Core::CompilationItemView]
66
+ def item
67
+ item_view_class.new(@item_rep.item, @context)
68
+ end
69
+
70
+ # @api private
71
+ def binary?
72
+ snapshot_def = _unwrap.snapshot_defs.find { |sd| sd.name == :last }
73
+ raise Nanoc::Core::Errors::NoSuchSnapshot.new(_unwrap, :last) if snapshot_def.nil?
74
+
75
+ snapshot_def.binary?
76
+ end
77
+
78
+ def inspect
79
+ "<#{self.class} item.identifier=#{item.identifier} name=#{name}>"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemView < ::Nanoc::Core::View
6
+ include Nanoc::Core::DocumentViewMixin
7
+
8
+ # Returns the children of this item. For items with identifiers that have
9
+ # extensions, returns an empty collection.
10
+ #
11
+ # @return [Enumerable<Nanoc::Core::CompilationItemView>]
12
+ def children
13
+ unless _unwrap.identifier.legacy?
14
+ raise Nanoc::Core::Errors::CannotGetParentOrChildrenOfNonLegacyItem.new(_unwrap.identifier)
15
+ end
16
+
17
+ children_pattern = Nanoc::Core::Pattern.from(_unwrap.identifier.to_s + '*/')
18
+ children = @context.items.select { |i| children_pattern.match?(i.identifier) }
19
+
20
+ children.map { |i| self.class.new(i, @context) }.freeze
21
+ end
22
+
23
+ # Returns the parent of this item, if one exists. For items with identifiers
24
+ # that have extensions, returns nil.
25
+ #
26
+ # @return [Nanoc::Core::CompilationItemView] if the item has a parent
27
+ #
28
+ # @return [nil] if the item has no parent
29
+ def parent
30
+ unless _unwrap.identifier.legacy?
31
+ raise Nanoc::Core::Errors::CannotGetParentOrChildrenOfNonLegacyItem.new(_unwrap.identifier)
32
+ end
33
+
34
+ parent_identifier = '/' + _unwrap.identifier.components[0..-2].join('/') + '/'
35
+ parent_identifier = '/' if parent_identifier == '//'
36
+
37
+ parent = @context.items[parent_identifier]
38
+
39
+ parent && self.class.new(parent, @context)
40
+ end
41
+
42
+ # @return [Boolean] True if the item is binary, false otherwise
43
+ def binary?
44
+ _unwrap.content.binary?
45
+ end
46
+
47
+ # @return [String, nil] The path to the file containing the uncompiled content of this item.
48
+ def raw_filename
49
+ @context.dependency_tracker.bounce(_unwrap, raw_content: true)
50
+ _unwrap.content.filename
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class ChangesStream
6
+ class ChangesListener
7
+ def initialize(y)
8
+ @y = y
9
+ end
10
+
11
+ def unknown
12
+ @y << :unknown
13
+ end
14
+
15
+ def lib
16
+ @y << :lib
17
+ end
18
+
19
+ def to_stop(&block)
20
+ if block_given?
21
+ @to_stop = block
22
+ else
23
+ @to_stop
24
+ end
25
+ end
26
+ end
27
+
28
+ def initialize(enum: nil)
29
+ @enum = enum
30
+ @enum ||=
31
+ Enumerator.new do |y|
32
+ @listener = ChangesListener.new(y)
33
+ yield(@listener)
34
+ end.lazy
35
+ end
36
+
37
+ def stop
38
+ @listener&.to_stop&.call
39
+ end
40
+
41
+ def map
42
+ self.class.new(enum: @enum.map { |e| yield(e) })
43
+ end
44
+
45
+ def to_enum
46
+ @enum
47
+ end
48
+
49
+ def each
50
+ @enum.each { |e| yield(e) }
51
+ nil
52
+ end
53
+ end
54
+ end
55
+ end
@@ -64,7 +64,7 @@ module Nanoc
64
64
 
65
65
  @checksums = {}
66
66
  new_data.each_pair do |key, checksum|
67
- if references.include?(key) || references.include?(key.first)
67
+ if references.include?(key) || (key.respond_to?(:first) && references.include?(key.first))
68
68
  @checksums[key] = checksum
69
69
  end
70
70
  end
@@ -50,8 +50,8 @@ module Nanoc
50
50
  end
51
51
 
52
52
  def calc_for_each_attribute_of(obj, digest_class = CompactDigest)
53
- obj.attributes.each_with_object({}) do |(key, value), memo|
54
- memo[key] = Nanoc::Core::Checksummer.calc(value, digest_class)
53
+ obj.attributes.transform_values do |value|
54
+ Nanoc::Core::Checksummer.calc(value, digest_class)
55
55
  end
56
56
  end
57
57
 
@@ -95,12 +95,14 @@ module Nanoc
95
95
  define_behavior(Nanoc::Core::BinaryContent, BinaryContentUpdateBehavior)
96
96
  define_behavior(Nanoc::Core::Configuration, HashUpdateBehavior)
97
97
  define_behavior(Nanoc::Core::Context, ContextUpdateBehavior)
98
+ define_behavior(Nanoc::Core::CodeSnippet, DataUpdateBehavior)
98
99
  define_behavior(Nanoc::Core::IdentifiableCollection, ArrayUpdateBehavior)
99
100
  define_behavior(Nanoc::Core::Identifier, ToSUpdateBehavior)
100
101
  define_behavior(Nanoc::Core::Item, DocumentUpdateBehavior)
101
102
  define_behavior(Nanoc::Core::ItemRep, ItemRepUpdateBehavior)
102
103
  define_behavior(Nanoc::Core::Layout, DocumentUpdateBehavior)
103
104
  define_behavior(Nanoc::Core::TextualContent, StringUpdateBehavior)
105
+ define_behavior(Nanoc::Core::View, UnwrapUpdateBehavior)
104
106
 
105
107
  @behaviors
106
108
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class CompilationItemRepCollectionView < ::Nanoc::Core::BasicItemRepCollectionView
6
+ # @api private
7
+ def view_class
8
+ Nanoc::Core::CompilationItemRepView
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class CompilationItemRepView < ::Nanoc::Core::BasicItemRepView
6
+ # How long to wait before the requested file appears.
7
+ #
8
+ # This is a bit of a hack -- ideally, Nanoc would know that the file is
9
+ # being generated, and wait the appropriate amount of time.
10
+ FILE_APPEAR_TIMEOUT = 10.0
11
+
12
+ # @abstract
13
+ def item_view_class
14
+ Nanoc::Core::CompilationItemView
15
+ end
16
+
17
+ # Returns the item rep’s raw path. It includes the path to the output
18
+ # directory and the full filename.
19
+ #
20
+ # @param [Symbol] snapshot The snapshot for which the path should be
21
+ # returned.
22
+ #
23
+ # @return [String] The item rep’s raw path.
24
+ def raw_path(snapshot: :last)
25
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
26
+
27
+ res = @item_rep.raw_path(snapshot: snapshot)
28
+
29
+ unless @item_rep.compiled?
30
+ Fiber.yield(Nanoc::Core::Errors::UnmetDependency.new(@item_rep, snapshot))
31
+ end
32
+
33
+ # Wait for file to exist
34
+ if res
35
+ start = Time.now
36
+ sleep 0.05 until File.file?(res) || Time.now - start > FILE_APPEAR_TIMEOUT
37
+ raise Nanoc::Core::Errors::InternalInconsistency, "File did not apear in time: #{res}" unless File.file?(res)
38
+ end
39
+
40
+ res
41
+ end
42
+
43
+ # Returns the compiled content.
44
+ #
45
+ # @param [String] snapshot The name of the snapshot from which to
46
+ # fetch the compiled content. By default, the returned compiled content
47
+ # will be the content compiled right before the first layout call (if
48
+ # any).
49
+ #
50
+ # @return [String] The content at the given snapshot.
51
+ def compiled_content(snapshot: nil)
52
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
53
+ @context.compiled_content_store.compiled_content(rep: _unwrap, snapshot: snapshot)
54
+ end
55
+ end
56
+ end
57
+ end