nanoc 4.8.16 → 4.8.17

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
  SHA256:
3
- metadata.gz: cfa738915a0c601d828aa97183ebbfee9613ee9e2b955ad0f52e6a3dbea6545e
4
- data.tar.gz: 6f0989008933306c049073a1b384c9715969116dafb8fc0279390b1b4ec003dd
3
+ metadata.gz: 2b0135cd287173e9725acef9bb921109f8158d9e6453bd8e7ae194e23cdd25ef
4
+ data.tar.gz: 115b6b3baf84924b26cacac37925023f0aacbb9530721bd093386a74102fbd10
5
5
  SHA512:
6
- metadata.gz: 8d7af61ff23c5a1f80e2d1b4e80bdb22f684ddca32391e9f19bb3fc44630a675d4cb29f7fbe9e1764f899e691dff0fad7d252e59e34bca86544edf397a07e0a5
7
- data.tar.gz: 58286c12cf1b0037db772e116c456f4d851d53c64d7ede2a151b9c30611f71b4a9e35cd5b5f7f3609b2b1323b2aa2eec82540393b5d4b6ba9c47f97fb709b81e
6
+ metadata.gz: c8aa8b0d5005dfbaa7664d08baaeee74bc7e5fb15cd2873d18bb0d4847c4c76203539852a258c4ad7c5187cb6503db1396e0a43752926f51fe89ea66b04dce12
7
+ data.tar.gz: 19fd6556430be0ffda0d733f0e8546a0ac646e7deb8da0e62df17c9caae4e99c166f4cc6bf8aadfc39376d5a1df44f53c542f104fefbf404686b840b4d18ced0
data/NEWS.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.8.17 (2017-12-16)
4
+
5
+ Enhancements:
6
+
7
+ * Made `LoadError` be printed more nicely (#1273, #1274, #1275)
8
+
3
9
  ## 4.8.16 (2017-12-09)
4
10
 
5
11
  Fixes:
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Load external dependencies
4
+ require 'addressable'
5
+ require 'ddplugin'
6
+ require 'hamster'
7
+ require 'ref'
8
+ require 'slow_enumerator_tools'
9
+ require 'ddmemoize'
10
+ require 'ddtelemetry'
11
+
3
12
  module Nanoc
4
13
  # @return [String] A string containing information about this Nanoc version
5
14
  # and its environment (Ruby engine and version, Rubygems version if any).
@@ -16,15 +25,9 @@ module Nanoc
16
25
  def self.on_windows?
17
26
  RUBY_PLATFORM =~ /windows|bccwin|cygwin|djgpp|mingw|mswin|wince/i
18
27
  end
19
- end
20
28
 
21
- # Load external dependencies
22
- require 'addressable'
23
- require 'ddplugin'
24
- require 'hamster'
25
- require 'ref'
26
- require 'slow_enumerator_tools'
27
- require 'ddtelemetry'
29
+ MEMOIZATION_TELEMETRY = DDTelemetry.new
30
+ end
28
31
 
29
32
  # Load general requirements
30
33
  require 'cgi'
@@ -6,7 +6,6 @@ end
6
6
 
7
7
  require_relative 'base/core_ext'
8
8
  require_relative 'base/contracts_support'
9
- require_relative 'base/memoization'
10
9
  require_relative 'base/error'
11
10
  require_relative 'base/errors'
12
11
  require_relative 'base/changes_stream'
@@ -4,7 +4,7 @@ module Nanoc::Int
4
4
  class ActionSequence
5
5
  include Nanoc::Int::ContractsSupport
6
6
  include Enumerable
7
- extend Nanoc::Int::Memoization
7
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
8
8
 
9
9
  attr_reader :item_rep
10
10
  attr_reader :actions
@@ -3,7 +3,6 @@
3
3
  module Nanoc::Int
4
4
  class ChecksumCollection
5
5
  include Nanoc::Int::ContractsSupport
6
- extend Nanoc::Int::Memoization
7
6
 
8
7
  c_obj = C::Or[Nanoc::Int::Item, Nanoc::Int::Layout, Nanoc::Int::Configuration, Nanoc::Int::CodeSnippet]
9
8
 
@@ -3,10 +3,11 @@
3
3
  module Nanoc::Int
4
4
  # @api private
5
5
  class IdentifiableCollection
6
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
7
+
6
8
  include Nanoc::Int::ContractsSupport
7
9
  include Enumerable
8
10
 
9
- extend Nanoc::Int::Memoization
10
11
  extend Forwardable
11
12
 
12
13
  def_delegator :@objects, :each
@@ -6,7 +6,7 @@ module Nanoc::Int
6
6
  # @api private
7
7
  class OutdatednessChecker
8
8
  class Basic
9
- extend Nanoc::Int::Memoization
9
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
10
10
 
11
11
  include Nanoc::Int::ContractsSupport
12
12
 
@@ -97,7 +97,7 @@ module Nanoc::Int
97
97
  end
98
98
  end
99
99
 
100
- extend Nanoc::Int::Memoization
100
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
101
101
 
102
102
  include Nanoc::Int::ContractsSupport
103
103
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Nanoc::Int::OutdatednessRules
4
4
  class CodeSnippetsModified < Nanoc::Int::OutdatednessRule
5
- extend Nanoc::Int::Memoization
5
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
6
6
 
7
7
  include Nanoc::Int::ContractsSupport
8
8
 
@@ -100,14 +100,6 @@ module Nanoc::CLI::Commands::CompileListeners
100
100
 
101
101
  @telemetry.summary(:phases).observe(stopwatch.duration, phase_name)
102
102
  end
103
-
104
- on(:memoization_miss) do |label|
105
- @telemetry.counter(:memoization).increment([label, :miss])
106
- end
107
-
108
- on(:memoization_hit) do |label|
109
- @telemetry.counter(:memoization).increment([label, :hit])
110
- end
111
103
  end
112
104
 
113
105
  # @see Listener#stop
@@ -146,32 +138,12 @@ module Nanoc::CLI::Commands::CompileListeners
146
138
  [headers] + rows
147
139
  end
148
140
 
149
- def table_for_memoization
150
- headers = %w[memoization hit miss %]
151
-
152
- rows_raw = @telemetry.counter(:memoization).map do |(name, type), counter|
153
- { name: name, type: type, count: counter.value }
154
- end
155
-
156
- rows = rows_raw.group_by { |r| r[:name] }.map do |name, rows_for_name|
157
- rows_by_type = rows_for_name.group_by { |r| r[:type] }
158
-
159
- num_hit = rows_by_type.fetch(:hit, []).fetch(0, {}).fetch(:count, 0)
160
- num_miss = rows_by_type.fetch(:miss, []).fetch(0, {}).fetch(:count, 0)
161
- pct = num_hit.to_f / (num_hit + num_miss).to_f
162
-
163
- [name, num_hit.to_s, num_miss.to_s, "#{format('%3.1f', pct * 100)}%"]
164
- end
165
-
166
- [headers] + rows
167
- end
168
-
169
141
  def print_profiling_feedback
170
142
  print_table_for_summary(:filters)
171
143
  print_table_for_summary(:phases) if Nanoc::CLI.verbosity >= 2
172
144
  print_table_for_summary_duration(:stages) if Nanoc::CLI.verbosity >= 2
173
145
  print_table_for_summary(:outdatedness_rules) if Nanoc::CLI.verbosity >= 2
174
- print_table_for_memoization if Nanoc::CLI.verbosity >= 2
146
+ DDMemoize.print_telemetry(Nanoc::MEMOIZATION_TELEMETRY) if Nanoc::CLI.verbosity >= 2
175
147
  end
176
148
 
177
149
  def print_table_for_summary(name)
@@ -188,13 +160,6 @@ module Nanoc::CLI::Commands::CompileListeners
188
160
  print_table(table_for_summary_durations(name))
189
161
  end
190
162
 
191
- def print_table_for_memoization
192
- return if @telemetry.counter(:memoization).empty?
193
-
194
- puts
195
- print_table(table_for_memoization)
196
- end
197
-
198
163
  def print_table(rows)
199
164
  puts DDTelemetry::Table.new(rows).to_s
200
165
  end
@@ -58,12 +58,20 @@ module Nanoc::CLI
58
58
  rescue Interrupt
59
59
  exit(1)
60
60
  rescue StandardError, ScriptError => e
61
- if trivial?(e)
62
- $stderr.puts "Error: #{e.message}"
63
- resolution = resolution_for(e)
64
- $stderr.puts resolution if resolution
61
+ handle_error(e, exit_on_error: exit_on_error)
62
+ end
63
+
64
+ def handle_error(error, exit_on_error:)
65
+ if trivial?(error)
66
+ $stderr.puts
67
+ $stderr.puts "Error: #{error.message}"
68
+ resolution = resolution_for(error)
69
+ if resolution
70
+ $stderr.puts
71
+ $stderr.puts resolution
72
+ end
65
73
  else
66
- print_error(e)
74
+ print_error(error)
67
75
  end
68
76
  exit(1) if exit_on_error
69
77
  end
@@ -148,6 +156,18 @@ module Nanoc::CLI
148
156
  feature_enabled || ruby_2_5_used
149
157
  end
150
158
 
159
+ # @api private
160
+ def trivial?(error)
161
+ case error
162
+ when Nanoc::Int::Errors::GenericTrivial, Errno::EADDRINUSE
163
+ true
164
+ when LoadError
165
+ GEM_NAMES.keys.include?(gem_name_from_load_error(error))
166
+ else
167
+ false
168
+ end
169
+ end
170
+
151
171
  protected
152
172
 
153
173
  # @return [Hash<String, Array>] A hash containing the gem names as keys and gem versions as value
@@ -196,15 +216,6 @@ module Nanoc::CLI
196
216
  'w3c_validators' => 'w3c_validators',
197
217
  }.freeze
198
218
 
199
- def trivial?(error)
200
- case error
201
- when Nanoc::Int::Errors::GenericTrivial, Errno::EADDRINUSE
202
- true
203
- else
204
- false
205
- end
206
- end
207
-
208
219
  # Attempts to find a resolution for the given error, or nil if no
209
220
  # resolution can be automatically obtained.
210
221
  #
@@ -216,15 +227,15 @@ module Nanoc::CLI
216
227
 
217
228
  case error
218
229
  when LoadError
219
- # Get gem name
220
- matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
221
- return nil if matches.nil?
222
- gem_name = GEM_NAMES[matches[2]]
230
+ gem_name = gem_name_from_load_error(error)
223
231
 
224
- # Build message
225
232
  if gem_name
226
233
  if using_bundler?
227
- 'Make sure the gem is added to Gemfile and run `bundle install`.'
234
+ <<~RES
235
+ 1. Add `gem '#{gem_name}'` to your Gemfile
236
+ 2. Run `bundle install`
237
+ 3. Re-run this command
238
+ RES
228
239
  else
229
240
  "Install the '#{gem_name}' gem using `gem install #{gem_name}`."
230
241
  end
@@ -241,6 +252,12 @@ module Nanoc::CLI
241
252
  end
242
253
  end
243
254
 
255
+ def gem_name_from_load_error(error)
256
+ matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
257
+ return nil if matches.nil?
258
+ GEM_NAMES[matches[2]]
259
+ end
260
+
244
261
  def using_bundler?
245
262
  defined?(Bundler) && Bundler::SharedHelpers.in_bundle?
246
263
  end
@@ -6,7 +6,7 @@ module Nanoc::RuleDSL
6
6
  #
7
7
  # @api private
8
8
  class ActionSequenceCalculator
9
- extend Nanoc::Int::Memoization
9
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
10
10
 
11
11
  class UnsupportedObjectTypeException < ::Nanoc::Error
12
12
  def initialize(obj)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nanoc
4
4
  # The current Nanoc version.
5
- VERSION = '4.8.16'
5
+ VERSION = '4.8.17'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.16
4
+ version: 4.8.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-09 00:00:00.000000000 Z
11
+ date: 2017-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ddmemoize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0a2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0a2
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: ddplugin
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -162,7 +176,6 @@ files:
162
176
  - lib/nanoc/base/error.rb
163
177
  - lib/nanoc/base/errors.rb
164
178
  - lib/nanoc/base/feature.rb
165
- - lib/nanoc/base/memoization.rb
166
179
  - lib/nanoc/base/repos.rb
167
180
  - lib/nanoc/base/repos/action_sequence_store.rb
168
181
  - lib/nanoc/base/repos/aggregate_data_source.rb
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Int
4
- # Adds support for memoizing functions.
5
- #
6
- # @api private
7
- module Memoization
8
- class Value
9
- attr_reader :value
10
-
11
- def initialize(value)
12
- @value = value
13
- end
14
- end
15
-
16
- NONE = Object.new
17
-
18
- # Memoizes the method with the given name. The modified method will cache
19
- # the results of the original method, so that calling a method twice with
20
- # the same arguments will short-circuit and return the cached results
21
- # immediately.
22
- #
23
- # Memoization assumes that the current object as well as the function
24
- # arguments are immutable. Mutating the object or the arguments will not
25
- # cause memoized methods to recalculate their results. There is no way to
26
- # un-memoize a result, and calculation results will remain in memory even
27
- # if they are no longer needed.
28
- #
29
- # @example A fast fib function due to memoization
30
- #
31
- # class FibFast
32
- #
33
- # extend Nanoc::Int::Memoization
34
- #
35
- # def run(n)
36
- # if n == 0
37
- # 0
38
- # elsif n == 1
39
- # 1
40
- # else
41
- # run(n-1) + run(n-2)
42
- # end
43
- # end
44
- # memoize :run
45
- #
46
- # end
47
- #
48
- # @param [Symbol, String] method_name The name of the method to memoize
49
- #
50
- # @return [void]
51
- def memoize(method_name)
52
- original_method_name = '__nonmemoized_' + method_name.to_s
53
- alias_method original_method_name, method_name
54
-
55
- instance_cache = Hash.new { |hash, key| hash[key] = {} }
56
-
57
- define_method(method_name) do |*args|
58
- instance_method_cache = instance_cache[self]
59
-
60
- value = NONE
61
- if instance_method_cache.key?(args)
62
- object = instance_method_cache[args].object
63
- value = object ? object.value : NONE
64
- end
65
-
66
- counter_label = is_a?(Class) ? "#{self}.#{method_name}" : "#{self.class}##{method_name}"
67
- if value.equal?(NONE)
68
- Nanoc::Int::NotificationCenter.post(:memoization_miss, counter_label)
69
- send(original_method_name, *args).tap do |r|
70
- instance_method_cache[args] = Ref::SoftReference.new(Value.new(r))
71
- end
72
- else
73
- Nanoc::Int::NotificationCenter.post(:memoization_hit, counter_label)
74
- value
75
- end
76
- end
77
- end
78
- alias memoized memoize
79
- end
80
- end