nanoc-core 4.14.0 → 4.14.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 789cc6b4702b215a8124a7fd9e223bbd5ae0ab388100d2825cc0aab1a2871706
4
- data.tar.gz: 41badc8b04d48a56d08b12394a16677973326c82ff94b61e987c332e27ddcfb5
3
+ metadata.gz: 1eb383ecd0b9f70dab794c7cbbeaea2000372252ec7fca79a88977f4b9ee52e4
4
+ data.tar.gz: 10b983997d7836e81a8d9926f8ccaf2f2208e557fce3a61d67675dc954d8dd4a
5
5
  SHA512:
6
- metadata.gz: 7f65db903bb45e40731a74aff7ed48a9189ed8327e77bc10323a72084e180845fedb2af85b8c4e9f93b1a9b1beb8a9c3b84af562ef89108de994153af7846f79
7
- data.tar.gz: 68ba69732bf619f3b30a73b4029d08cfe38e2e4451da63517aca1fc6040cf8d2451438c023844b5dc626c3c6da3ab4009bcd8c35bffc2b72599f6fad866a5a6f
6
+ metadata.gz: 2a05d9133dfcea7375b3b2dbc86d876701f86d29298bc029eae947b59893071f06df12aeb0491179ec3b6f725770de9ff7af940d16ffbd978c02859acb50e2cb
7
+ data.tar.gz: e374dd038fb6535c7e48ec2228f872ec06a70022a82306da0a4ac35c11ec2133e88aea1bee4f0ec5fbe339965a63e67f2054a34d1afacb8b7275c26de7e5e6c1
@@ -27,7 +27,7 @@ module Nanoc
27
27
  res = @item_rep.raw_path(snapshot:)
28
28
 
29
29
  unless @item_rep.compiled?
30
- Fiber.yield(Nanoc::Core::Errors::UnmetDependency.new(@item_rep, snapshot))
30
+ raise Nanoc::Core::Errors::UnmetDependency.new(@item_rep, snapshot)
31
31
  end
32
32
 
33
33
  # Wait for file to exist
@@ -12,6 +12,9 @@ module Nanoc
12
12
  Nanoc::Core::NotificationCenter.post(:compilation_started, rep)
13
13
  yield
14
14
  Nanoc::Core::NotificationCenter.post(:compilation_ended, rep)
15
+ rescue Nanoc::Core::Errors::UnmetDependency
16
+ Nanoc::Core::NotificationCenter.post(:compilation_suspended, rep)
17
+ raise
15
18
  end
16
19
  end
17
20
  end
@@ -23,10 +23,16 @@ module Nanoc
23
23
 
24
24
  executor = Nanoc::Core::Executor.new(rep, @compilation_context, dependency_tracker)
25
25
 
26
- @compilation_context.compiled_content_store.set_current(rep, rep.item.content)
26
+ # Set initial content, if not already present
27
+ compiled_content_store = @compilation_context.compiled_content_store
28
+ unless compiled_content_store.get_current(rep)
29
+ compiled_content_store.set_current(rep, rep.item.content)
30
+ end
31
+
32
+ actions = pending_action_sequence_for(rep:)
33
+ until actions.empty?
34
+ action = actions.first
27
35
 
28
- actions = @action_sequences[rep]
29
- actions.each do |action|
30
36
  case action
31
37
  when Nanoc::Core::ProcessingActions::Filter
32
38
  executor.filter(action.filter_name, action.params)
@@ -39,10 +45,17 @@ module Nanoc
39
45
  else
40
46
  raise Nanoc::Core::Errors::InternalInconsistency, "unknown action #{action.inspect}"
41
47
  end
48
+
49
+ actions.shift
42
50
  end
43
51
  ensure
44
52
  dependency_tracker.exit
45
53
  end
54
+
55
+ def pending_action_sequence_for(rep:)
56
+ @_pending_action_sequences ||= {}
57
+ @_pending_action_sequences[rep] ||= @action_sequences[rep].to_a
58
+ end
46
59
  end
47
60
  end
48
61
  end
@@ -33,7 +33,12 @@ module Nanoc
33
33
  end
34
34
  end
35
35
 
36
- selector = Nanoc::Core::ItemRepSelector.new(outdated_reps)
36
+ selector = Nanoc::Core::ItemRepSelector.new(
37
+ outdated_reps:,
38
+ reps: @reps,
39
+ dependency_store: @dependency_store,
40
+ )
41
+
37
42
  run_phase_stack do |phase_stack|
38
43
  selector.each do |rep|
39
44
  handle_errors_while(rep) do
@@ -87,13 +92,9 @@ module Nanoc
87
92
  wrapped: recalculate_phase,
88
93
  )
89
94
 
90
- resume_phase = Nanoc::Core::CompilationPhases::Resume.new(
91
- wrapped: cache_phase,
92
- )
93
-
94
95
  write_phase = Nanoc::Core::CompilationPhases::Write.new(
95
96
  compiled_content_store: @compilation_context.compiled_content_store,
96
- wrapped: resume_phase,
97
+ wrapped: cache_phase,
97
98
  )
98
99
 
99
100
  mark_done_phase = Nanoc::Core::CompilationPhases::MarkDone.new(
@@ -57,9 +57,8 @@ module Nanoc
57
57
  content = get(rep, snapshot_name)
58
58
  return content if content
59
59
 
60
- # Content is unavailable; notify and try again
61
- Fiber.yield(Nanoc::Core::Errors::UnmetDependency.new(rep, snapshot_name))
62
- get(rep, snapshot_name)
60
+ # Content is unavailable
61
+ raise Nanoc::Core::Errors::UnmetDependency.new(rep, snapshot_name)
63
62
  end
64
63
 
65
64
  contract C::KeywordArgs[rep: Nanoc::Core::ItemRep, snapshot: C::Optional[C::Maybe[Symbol]]] => String
@@ -33,6 +33,8 @@ module Nanoc
33
33
  # graph.predecessors_of('e').sort
34
34
  # # => %w( c d )
35
35
  class DirectedGraph
36
+ EMPTY_SET = Set.new.freeze
37
+
36
38
  # @group Creating a graph
37
39
 
38
40
  # Creates a new directed graph with the given vertices.
@@ -40,7 +42,8 @@ module Nanoc
40
42
  @vertices = {}
41
43
  @next_vertex_idx = 0
42
44
  vertices.each do |v|
43
- @vertices[v] = @next_vertex_idx.tap { @next_vertex_idx += 1 }
45
+ @vertices[v] = @next_vertex_idx
46
+ @next_vertex_idx += 1
44
47
  end
45
48
 
46
49
  @to_graph = {}
@@ -93,7 +96,8 @@ module Nanoc
93
96
  def add_vertex(vertex)
94
97
  return if @vertices.key?(vertex)
95
98
 
96
- @vertices[vertex] = @next_vertex_idx.tap { @next_vertex_idx += 1 }
99
+ @vertices[vertex] = @next_vertex_idx
100
+ @next_vertex_idx += 1
97
101
  end
98
102
 
99
103
  # Deletes all edges going to the given vertex.
@@ -121,7 +125,7 @@ module Nanoc
121
125
  #
122
126
  # @return [Array] Direct predecessors of the given vertex
123
127
  def direct_predecessors_of(to)
124
- @to_graph.fetch(to, Set.new)
128
+ @to_graph.fetch(to, EMPTY_SET)
125
129
  end
126
130
 
127
131
  # Returns the predecessors of the given vertex, i.e. the vertices x for
@@ -249,11 +249,6 @@ module Nanoc
249
249
  end
250
250
  end
251
251
 
252
- # @api private
253
- def on_main_fiber(&block)
254
- Fiber.yield(block)
255
- end
256
-
257
252
  contract C::ArrayOf[C::Named['Nanoc::Core::BasicItemView']] => C::Any
258
253
  # Creates a dependency from the item that is currently being filtered onto
259
254
  # the given collection of items. In other words, require the given items
@@ -4,17 +4,22 @@ module Nanoc
4
4
  module Core
5
5
  # Yields item reps to compile.
6
6
  class ItemRepSelector
7
- def initialize(reps)
7
+ def initialize(outdated_reps:, reps:, dependency_store:)
8
+ @outdated_reps = outdated_reps
8
9
  @reps = reps
10
+ @dependency_store = dependency_store
9
11
  end
10
12
 
11
13
  # A priority queue that tracks dependencies and can detect circular
12
14
  # dependencies.
13
15
  class ItemRepPriorityQueue
14
- def initialize(reps)
16
+ def initialize(outdated_reps:, reps:, dependency_store:)
17
+ @reps = reps
18
+ @dependency_store = dependency_store
19
+
15
20
  # Prio A: most important; prio C: least important.
16
21
  @prio_a = nil
17
- @prio_b = reps.dup
22
+ @prio_b = outdated_reps.dup
18
23
  @prio_c = []
19
24
 
20
25
  # List of reps that we’ve already seen. Reps from `reps` will end up
@@ -59,30 +64,31 @@ module Nanoc
59
64
  @completed << @this
60
65
  end
61
66
 
62
- def mark_failed(dep)
63
- record_dependency(dep)
67
+ def mark_failed(needed_rep:)
68
+ record_dependency(needed_rep)
64
69
 
65
- # `@this` depends on `dep`, so `dep` has to be compiled first. Thus,
66
- # move `@this` into priority C, and `dep` into priority A.
70
+ # `@this` depends on `needed_rep`, so `needed_rep` has to be compiled
71
+ # first. Thus, move `@this` into priority C, and `needed_rep` into
72
+ # priority A.
67
73
 
68
- # Put `@this` (item rep that needs `dep` to be compiled first) into
69
- # priority C (lowest prio).
74
+ # Put `@this` (item rep that needs `needed_rep` to be compiled first)
75
+ # into priority C (lowest prio).
70
76
  @prio_c.push(@this) unless @prio_c.include?(@this)
71
77
 
72
- # Put `dep` (item rep that needs to be compiled first, before
78
+ # Put `needed_rep` (item rep that needs to be compiled first, before
73
79
  # `@this`) into priority A (highest prio).
74
- @prio_a = dep
80
+ @prio_a = needed_rep
75
81
 
76
- # Remember that we’ve prioritised `dep`. This particular element will
77
- # come from @prio_b at some point in the future, so we’ll have to skip
78
- # it then.
79
- @seen << dep
82
+ # Remember that we’ve prioritised `needed_rep`. This particular
83
+ # element will come from @prio_b at some point in the future, so we’ll
84
+ # have to skip it then.
85
+ @seen << needed_rep
80
86
  end
81
87
 
82
88
  private
83
89
 
84
- def record_dependency(dep)
85
- @dependencies[@this] << dep
90
+ def record_dependency(rep)
91
+ @dependencies[@this] << rep
86
92
 
87
93
  find_cycle(@this, [@this])
88
94
  end
@@ -102,7 +108,11 @@ module Nanoc
102
108
  end
103
109
 
104
110
  def each
105
- pq = ItemRepPriorityQueue.new(@reps)
111
+ pq = ItemRepPriorityQueue.new(
112
+ outdated_reps: @outdated_reps,
113
+ reps: @reps,
114
+ dependency_store: @dependency_store,
115
+ )
106
116
 
107
117
  loop do
108
118
  rep = pq.next
@@ -115,7 +125,7 @@ module Nanoc
115
125
  actual_error = e.is_a?(Nanoc::Core::Errors::CompilationError) ? e.unwrap : e
116
126
 
117
127
  if actual_error.is_a?(Nanoc::Core::Errors::UnmetDependency)
118
- pq.mark_failed(actual_error.rep)
128
+ pq.mark_failed(needed_rep: actual_error.rep)
119
129
  else
120
130
  raise(e)
121
131
  end
@@ -10,46 +10,9 @@ module Nanoc
10
10
  # table of subscribers is not stored in the observable object itself, but in
11
11
  # the notification center.
12
12
  class NotificationCenter
13
- DONE = Object.new
14
- SYNC = Object.new
15
-
16
13
  def initialize
17
- @thread = nil
18
-
19
14
  # name => observers dictionary
20
15
  @notifications = Hash.new { |hash, name| hash[name] = [] }
21
-
22
- @queue = Queue.new
23
-
24
- @sync_queue = Queue.new
25
- on(SYNC, self) { @sync_queue << true }
26
- end
27
-
28
- def start
29
- @thread ||= Thread.new do # rubocop:disable Naming/MemoizedInstanceVariableName
30
- Thread.current.abort_on_exception = true
31
-
32
- loop do
33
- elem = @queue.pop
34
- break if DONE.equal?(elem)
35
-
36
- name = elem[0]
37
- args = elem[1]
38
-
39
- @notifications[name].each do |observer|
40
- observer[:block].call(*args)
41
- end
42
- end
43
- end
44
- end
45
-
46
- def stop
47
- @queue << DONE
48
- @thread.join
49
- end
50
-
51
- def force_stop
52
- @queue << DONE
53
16
  end
54
17
 
55
18
  def on(name, id = nil, &block)
@@ -61,18 +24,16 @@ module Nanoc
61
24
  end
62
25
 
63
26
  def post(name, *args)
64
- @queue << [name, args]
65
- self
66
- end
27
+ @notifications[name].each do |observer|
28
+ observer[:block].call(*args)
29
+ end
67
30
 
68
- def sync
69
- post(SYNC)
70
- @sync_queue.pop
31
+ self
71
32
  end
72
33
 
73
34
  class << self
74
35
  def instance
75
- @_instance ||= new.tap(&:start)
36
+ @_instance ||= new
76
37
  end
77
38
 
78
39
  def on(name, id = nil, &)
@@ -88,18 +49,8 @@ module Nanoc
88
49
  end
89
50
 
90
51
  def reset
91
- instance.stop
92
52
  @_instance = nil
93
53
  end
94
-
95
- def force_reset
96
- instance.force_stop
97
- @_instance = nil
98
- end
99
-
100
- def sync
101
- instance.sync
102
- end
103
54
  end
104
55
  end
105
56
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Nanoc
4
4
  module Core
5
- VERSION = '4.14.0'
5
+ VERSION = '4.14.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.14.0
4
+ version: 4.14.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
@@ -185,7 +185,6 @@ files:
185
185
  - lib/nanoc/core/compilation_phases/mark_done.rb
186
186
  - lib/nanoc/core/compilation_phases/notify.rb
187
187
  - lib/nanoc/core/compilation_phases/recalculate.rb
188
- - lib/nanoc/core/compilation_phases/resume.rb
189
188
  - lib/nanoc/core/compilation_phases/write.rb
190
189
  - lib/nanoc/core/compilation_stage.rb
191
190
  - lib/nanoc/core/compilation_stages/build_reps.rb
@@ -304,7 +303,7 @@ licenses:
304
303
  - MIT
305
304
  metadata:
306
305
  rubygems_mfa_required: 'true'
307
- source_code_uri: https://github.com/nanoc/nanoc/tree/nanoc-core-v4.14.0/nanoc-core
306
+ source_code_uri: https://github.com/nanoc/nanoc/tree/nanoc-core-v4.14.2/nanoc-core
308
307
  rdoc_options: []
309
308
  require_paths:
310
309
  - lib
@@ -319,7 +318,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
318
  - !ruby/object:Gem::Version
320
319
  version: '0'
321
320
  requirements: []
322
- rubygems_version: 3.7.2
321
+ rubygems_version: 3.6.9
323
322
  specification_version: 4
324
323
  summary: Core of Nanoc
325
324
  test_files: []
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Core
5
- module CompilationPhases
6
- # Provides functionality for suspending and resuming item rep compilation (using fibers).
7
- class Resume < Abstract
8
- include Nanoc::Core::ContractsSupport
9
-
10
- DONE = Object.new
11
-
12
- contract Nanoc::Core::ItemRep, C::KeywordArgs[is_outdated: C::Bool], C::Func[C::None => C::Any] => C::Any
13
- def run(rep, is_outdated:, &)
14
- fiber = fiber_for(rep, is_outdated:, &)
15
- while fiber.alive?
16
- res = fiber.resume
17
-
18
- case res
19
- when Nanoc::Core::Errors::UnmetDependency
20
- Nanoc::Core::NotificationCenter.post(:compilation_suspended, rep, res.rep, res.snapshot_name)
21
- raise(res)
22
- when Proc
23
- fiber.resume(res.call)
24
- when DONE
25
- # ignore
26
- else
27
- raise Nanoc::Core::Errors::InternalInconsistency.new(
28
- "Fiber yielded object of unexpected type #{res.class}",
29
- )
30
- end
31
- end
32
- end
33
-
34
- private
35
-
36
- contract Nanoc::Core::ItemRep, C::KeywordArgs[is_outdated: C::Bool], C::Func[C::None => C::Any] => Fiber
37
- def fiber_for(rep, is_outdated:) # rubocop:disable Lint/UnusedMethodArgument
38
- @fibers ||= {}
39
-
40
- @fibers[rep] ||=
41
- Fiber.new do
42
- yield
43
- @fibers.delete(rep)
44
- DONE
45
- end
46
-
47
- @fibers[rep]
48
- end
49
- end
50
- end
51
- end
52
- end