nanoc 4.7.13 → 4.7.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6113ac8b3ca8085d1247d4e880144d62af62037
4
- data.tar.gz: 557d2ae493c26da9ebe71735fcb19da59f9aeba4
3
+ metadata.gz: 95f87711482fb7881b63a2a4d0a7fca8fecede30
4
+ data.tar.gz: 6d5b0673fa14f07f4081cc473e24bdd0d558b481
5
5
  SHA512:
6
- metadata.gz: 7a0f046fd0f6b324dfea8451b0ab89142ff32a572e3e948cbf23e13337de70726097069101ed5484805d105f72ccd245ab8de0db2568f8310878e09eb083db4e
7
- data.tar.gz: 06e63734588725c3260fa543ad6844fb94dd7369092bea7249415f1096f363eed66267b752b0cb309e52377d730737688ef8b445b5b19b4029ed13889e7c6894
6
+ metadata.gz: 1ea685c54608f0c56af24542324c2cc2f3a4c7f84718c22d3abfde40288695290b45c83106283570be844b5183b12ca82c9a9239fefe34c47b8e73d9414755ad
7
+ data.tar.gz: cd48b21ea8577192f94e990a462d5237a81ea8a54bf3e60012e8552c69344b43abedafe5d70824d7f3732e95b7963542d59b55a2c331cb1df3e137475d6f89a5
data/NEWS.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.7.14 (2017-07-16)
4
+
5
+ Enhancements:
6
+
7
+ * Various speed improvements (#1195, #1198)
8
+
3
9
  ## 4.7.13 (2017-07-02)
4
10
 
5
11
  Enhancements:
data/bin/nanoc CHANGED
@@ -2,6 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'nanoc'
5
+
6
+ begin
7
+ require 'nanoc-rust'
8
+ NanocRust.activate!
9
+ rescue LoadError
10
+ end
11
+
5
12
  require 'nanoc/cli'
6
13
 
7
14
  if File.file?('Gemfile') && !defined?(Bundler)
@@ -43,7 +43,7 @@ module Nanoc::Int
43
43
  #
44
44
  # @return [Object] An unique reference to this object
45
45
  def reference
46
- [:code_snippet, filename]
46
+ "code_snippet:#{filename}"
47
47
  end
48
48
 
49
49
  def inspect
@@ -164,7 +164,7 @@ module Nanoc::Int
164
164
  #
165
165
  # @return [Object] An unique reference to this object
166
166
  def reference
167
- :config
167
+ 'configuration'
168
168
  end
169
169
 
170
170
  def inspect
@@ -7,27 +7,28 @@ module Nanoc::Int
7
7
  # @example Creating and using a directed graph
8
8
  #
9
9
  # # Create a graph with three vertices
10
- # graph = Nanoc::Int::DirectedGraph.new(%w( a b c d ))
10
+ # graph = Nanoc::Int::DirectedGraph.new(%w( a b c d e ))
11
11
  #
12
12
  # # Add edges
13
13
  # graph.add_edge('a', 'b')
14
14
  # graph.add_edge('b', 'c')
15
15
  # graph.add_edge('c', 'd')
16
+ # graph.add_edge('b', 'e')
16
17
  #
17
- # # Get (direct) predecessors
18
- # graph.direct_predecessors_of('d').sort
19
- # # => %w( c )
20
- # graph.predecessors_of('d').sort
21
- # # => %w( a b c )
18
+ # # Get (direct) successors
19
+ # graph.direct_successors_of('a').sort
20
+ # # => %w( b )
21
+ # graph.successors_of('a').sort
22
+ # # => %w( b c d e )
22
23
  #
23
24
  # # Modify edges
24
- # graph.delete_edge('a', 'b')
25
+ # graph.delete_edges_to('c')
25
26
  #
26
- # # Get (direct) predecessors again
27
- # graph.direct_predecessors_of('d').sort
28
- # # => %w( c )
29
- # graph.predecessors_of('d').sort
30
- # # => %w( b c )
27
+ # # Get (direct) successors again
28
+ # graph.direct_successors_of('a').sort
29
+ # # => %w( b )
30
+ # graph.successors_of('a').sort
31
+ # # => %w( b e )
31
32
  #
32
33
  # @api private
33
34
  class DirectedGraph
@@ -36,8 +37,9 @@ module Nanoc::Int
36
37
  # Creates a new directed graph with the given vertices.
37
38
  def initialize(vertices)
38
39
  @vertices = {}
39
- vertices.each_with_index do |v, i|
40
- @vertices[v] = i
40
+ @next_vertex_idx = 0
41
+ vertices.each do |v|
42
+ @vertices[v] = @next_vertex_idx.tap { @next_vertex_idx += 1 }
41
43
  end
42
44
 
43
45
  @from_graph = {}
@@ -45,8 +47,6 @@ module Nanoc::Int
45
47
 
46
48
  @edge_props = {}
47
49
 
48
- @roots = Set.new(@vertices.keys)
49
-
50
50
  invalidate_caches
51
51
  end
52
52
 
@@ -85,30 +85,6 @@ module Nanoc::Int
85
85
  @edge_props[[from, to]] = props
86
86
  end
87
87
 
88
- @roots.delete(to)
89
-
90
- invalidate_caches
91
- end
92
-
93
- # Removes the edge from the first vertex to the second vertex. If the
94
- # edge does not exist, nothing is done.
95
- #
96
- # @param from Start vertex of the edge
97
- #
98
- # @param to End vertex of the edge
99
- #
100
- # @return [void]
101
- def delete_edge(from, to)
102
- @from_graph[from] ||= Set.new
103
- @from_graph[from].delete(to)
104
-
105
- @to_graph[to] ||= Set.new
106
- @to_graph[to].delete(from)
107
-
108
- @edge_props.delete([from, to])
109
-
110
- @roots.add(to) if @to_graph[to].empty?
111
-
112
88
  invalidate_caches
113
89
  end
114
90
 
@@ -120,25 +96,7 @@ module Nanoc::Int
120
96
  def add_vertex(v)
121
97
  return if @vertices.key?(v)
122
98
 
123
- @vertices[v] = @vertices.size
124
-
125
- @roots << v
126
- end
127
-
128
- # Deletes all edges coming from the given vertex.
129
- #
130
- # @param from Vertex from which all edges should be removed
131
- #
132
- # @return [void]
133
- def delete_edges_from(from)
134
- return if @from_graph[from].nil?
135
-
136
- @from_graph[from].each do |to|
137
- @to_graph[to].delete(from)
138
- @edge_props.delete([from, to])
139
- @roots.add(to) if @to_graph[to].empty?
140
- end
141
- @from_graph.delete(from)
99
+ @vertices[v] = @next_vertex_idx.tap { @next_vertex_idx += 1 }
142
100
  end
143
101
 
144
102
  # Deletes all edges going to the given vertex.
@@ -154,64 +112,12 @@ module Nanoc::Int
154
112
  @edge_props.delete([from, to])
155
113
  end
156
114
  @to_graph.delete(to)
157
- @roots.add(to)
158
- end
159
-
160
- # Removes the given vertex from the graph.
161
- #
162
- # @param v Vertex to remove from the graph
163
- #
164
- # @return [void]
165
- def delete_vertex(v)
166
- delete_edges_to(v)
167
- delete_edges_from(v)
168
115
 
169
- @vertices.delete(v)
170
- @roots.delete(v)
116
+ invalidate_caches
171
117
  end
172
118
 
173
119
  # @group Querying the graph
174
120
 
175
- # Returns a cycle if there is any.
176
- def any_cycle
177
- all_paths.lazy.map { |path| cycle_in_path(path) }.find(&:itself)
178
- end
179
-
180
- # Given a potentially closed path, returns a cycle if there is any.
181
- def cycle_in_path(path)
182
- vertex = path.last
183
- index = path.index(vertex)
184
-
185
- if index < path.size - 1
186
- path[index..-2]
187
- end
188
- end
189
-
190
- # Yields all paths (including potentially closed ones).
191
- def all_paths
192
- Enumerator.new do |y|
193
- @vertices.keys.each do |vertex|
194
- dfs_from(vertex) do |path|
195
- y << path
196
- end
197
- end
198
- end
199
- end
200
-
201
- # Yields all paths (including potentially closed ones) starting from the given vertex.
202
- def dfs_from(vertex, path_so_far = [])
203
- new_path = path_so_far + [vertex]
204
- yield(new_path)
205
-
206
- unless path_so_far.include?(vertex)
207
- direct_successors_of(vertex).each do |next_vertex|
208
- dfs_from(next_vertex, new_path) do |path|
209
- yield(path)
210
- end
211
- end
212
- end
213
- end
214
-
215
121
  # Returns the direct predecessors of the given vertex, i.e. the vertices
216
122
  # x where there is an edge from x to the given vertex y.
217
123
  #
@@ -275,13 +181,6 @@ module Nanoc::Int
275
181
  result
276
182
  end
277
183
 
278
- # Returns all root vertices, i.e. vertices where no edge points to.
279
- #
280
- # @return [Set] The set of all root vertices in this graph.
281
- def roots
282
- @roots
283
- end
284
-
285
184
  private
286
185
 
287
186
  # Invalidates cached data. This method should be called when the internal
@@ -4,7 +4,7 @@ module Nanoc::Int
4
4
  # @api private
5
5
  class Item < ::Nanoc::Int::Document
6
6
  def reference
7
- [:item, identifier.to_s]
7
+ "item:#{identifier}"
8
8
  end
9
9
  end
10
10
  end
@@ -8,7 +8,7 @@ module Nanoc::Int
8
8
  end
9
9
 
10
10
  def reference
11
- :items
11
+ 'items'
12
12
  end
13
13
  end
14
14
  end
@@ -79,7 +79,7 @@ module Nanoc::Int
79
79
 
80
80
  # Returns an object that can be used for uniquely identifying objects.
81
81
  def reference
82
- [:item_rep, item.identifier, name]
82
+ "item_rep:#{item.identifier}:#{name}"
83
83
  end
84
84
 
85
85
  def inspect
@@ -4,7 +4,7 @@ module Nanoc::Int
4
4
  # @api private
5
5
  class Layout < ::Nanoc::Int::Document
6
6
  def reference
7
- [:layout, identifier.to_s]
7
+ "layout:#{identifier}"
8
8
  end
9
9
  end
10
10
  end
@@ -8,7 +8,7 @@ module Nanoc::Int
8
8
  end
9
9
 
10
10
  def reference
11
- :layouts
11
+ 'layouts'
12
12
  end
13
13
  end
14
14
  end
@@ -71,13 +71,14 @@ module Nanoc::Int
71
71
  # Error that is raised during site compilation when an item (directly or
72
72
  # indirectly) includes its own item content, leading to endless recursion.
73
73
  class DependencyCycle < Generic
74
- def initialize(graph)
75
- cycle = graph.any_cycle
74
+ def initialize(stack)
75
+ start_idx = stack.index(stack.last)
76
+ cycle = stack[start_idx..-2]
76
77
 
77
78
  msg_bits = []
78
79
  msg_bits << 'The site cannot be compiled because there is a dependency cycle:'
79
80
  msg_bits << ''
80
- cycle.reverse_each.with_index do |r, i|
81
+ cycle.each.with_index do |r, i|
81
82
  msg_bits << " (#{i + 1}) item #{r.item.identifier}, rep #{r.name.inspect}, uses compiled content of"
82
83
  end
83
84
  msg_bits << msg_bits.pop + ' (1)'
@@ -9,79 +9,58 @@ module Nanoc::Int
9
9
  @reps = reps
10
10
  end
11
11
 
12
- NONE = Object.new
13
-
14
- def each
15
- graph = Nanoc::Int::DirectedGraph.new(@reps)
16
-
17
- prio_dependent = Set.new
18
- prio_in_progress = Set.new
19
- loop do
20
- rep = find(graph, prio_dependent, prio_in_progress)
21
- break if NONE.equal?(rep)
22
-
23
- begin
24
- prio_in_progress << rep
25
- yield(rep)
26
- prio_in_progress.delete(rep)
27
- graph.delete_vertex(rep)
28
- rescue => e
29
- handle_error(e, rep, graph, prio_dependent)
30
- end
12
+ class MicroGraph
13
+ def initialize(reps)
14
+ @reps = Set.new(reps)
15
+ @stack = []
31
16
  end
32
17
 
33
- # Check whether everything was compiled
34
- unless graph.vertices.empty?
35
- raise Nanoc::Int::Errors::DependencyCycle.new(graph)
36
- end
37
- end
38
-
39
- def find(graph, prio_dependent, prio_in_progress)
40
- if graph.roots.empty?
41
- NONE
42
- elsif prio_dependent.any?
43
- find_prio(graph, prio_dependent, prio_dependent, prio_in_progress)
44
- elsif prio_in_progress.any?
45
- find_prio(graph, prio_in_progress, prio_dependent, prio_in_progress)
46
- else
47
- graph.roots.each { |e| break e }
48
- end
49
- end
50
-
51
- def find_prio(graph, prio, prio_dependent, prio_in_progress)
52
- until prio.empty?
53
- rep = prio.each { |e| break e }
54
- if graph.roots.include?(rep)
55
- return rep
18
+ def next
19
+ if @stack.any?
20
+ @stack.last
21
+ elsif @reps.any?
22
+ @reps.each { |rep| break rep }.tap do |rep|
23
+ @reps.delete(rep)
24
+ @stack.push(rep)
25
+ end
56
26
  else
57
- prio.delete(rep)
27
+ nil
58
28
  end
59
29
  end
60
30
 
61
- find(graph, prio_dependent, prio_in_progress)
62
- end
31
+ def mark_ok
32
+ @stack.pop
33
+ end
63
34
 
64
- def handle_error(e, rep, graph, prio_dependent)
65
- actual_error =
66
- if e.is_a?(Nanoc::Int::Errors::CompilationError)
67
- e.unwrap
68
- else
69
- e
35
+ def mark_failed(dep)
36
+ if @stack.include?(dep)
37
+ raise Nanoc::Int::Errors::DependencyCycle.new(@stack + [dep])
70
38
  end
71
39
 
72
- if actual_error.is_a?(Nanoc::Int::Errors::UnmetDependency)
73
- handle_dependency_error(actual_error, rep, graph, prio_dependent)
74
- else
75
- raise(e)
40
+ @reps.delete(dep)
41
+ @stack.push(dep)
76
42
  end
77
43
  end
78
44
 
79
- def handle_dependency_error(e, rep, graph, prio_dependent)
80
- other_rep = e.rep
81
- prio_dependent << other_rep
82
- graph.add_edge(other_rep, rep)
83
- unless graph.vertices.include?(other_rep)
84
- graph.add_vertex(other_rep)
45
+ def each
46
+ mg = MicroGraph.new(@reps)
47
+
48
+ loop do
49
+ rep = mg.next
50
+ break if rep.nil?
51
+
52
+ begin
53
+ yield(rep)
54
+ mg.mark_ok
55
+ rescue => e
56
+ actual_error = e.is_a?(Nanoc::Int::Errors::CompilationError) ? e.unwrap : e
57
+
58
+ if actual_error.is_a?(Nanoc::Int::Errors::UnmetDependency)
59
+ mg.mark_failed(actual_error.rep)
60
+ else
61
+ raise(e)
62
+ end
63
+ end
85
64
  end
86
65
  end
87
66
  end