activesupport 6.0.0.beta1 → 6.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e983c5003fc2a5e0407ce1c167bd223b633cd8a99f2ac41e220d28ca66e153f3
4
- data.tar.gz: 1e7910b6401c6f5a6f61ee1d24f0ad29a5d0f4d89ac064d7c6e6bf9c7d1becf0
3
+ metadata.gz: dd9c5d9d905a0d78112ed365cdbacb95ec29339f81d972942f6c19d37187d658
4
+ data.tar.gz: df7793adf6dffc15228aa1b1a732a28fc47184a285395891dd3daf3a19e68a71
5
5
  SHA512:
6
- metadata.gz: caa53fcafc4583b3642f3e95dd7f0829779a52dec8035a55f8f3e64f965de73c48268b8fb8819cb6b523dd23da28e7a35d008851dd4f65abd16e1f17c287c874
7
- data.tar.gz: 9ded7b685c180132fbd34950ac9313cb7399bc524e3e3c531f0142fc7c83b9f92ef5dce01e950adff90152561c4132a6fe48f4e55bce1b71fb45da064d2facc1
6
+ metadata.gz: 67827b484981828e79637fae9a2f065f881d393d0081e248f773b2a2907e286d5cfd714e7e540ed94f813fa79059d570227043dde00aabcc141a3117cd2becf0
7
+ data.tar.gz: 497baa82a0453c7c2d7fb091302b0a74096fd496f98f04dbf67b01b45c4e6b53d0780685c5b30b84aadd12b7a674d5fd1c85edcadf7bb5e4f9c94f6362f8a0d5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## Rails 6.0.0.beta2 (February 25, 2019) ##
2
+
3
+ * New autoloading based on [Zeitwerk](https://github.com/fxn/zeitwerk).
4
+
5
+ *Xavier Noria*
6
+
7
+ * Revise `ActiveSupport::Notifications.unsubscribe` to correctly handle Regex or other multiple-pattern subscribers.
8
+
9
+ *Zach Kemp*
10
+
11
+ * Add `before_reset` callback to `CurrentAttributes` and define `after_reset` as an alias of `resets` for symmetry.
12
+
13
+ *Rosa Gutierrez*
14
+
15
+ * Remove the `` Kernel#` `` override that suppresses ENOENT and accidentally returns nil on Unix systems.
16
+
17
+ *Akinori Musha*
18
+
19
+ * Add `ActiveSupport::HashWithIndifferentAccess#assoc`.
20
+
21
+ `assoc` can now be called with either a string or a symbol.
22
+
23
+ *Stefan Schüßler*
24
+
25
+ * Add `Hash#deep_transform_values`, and `Hash#deep_transform_values!`.
26
+
27
+ *Guillermo Iguaran*
28
+
1
29
  ## Rails 6.0.0.beta1 (January 18, 2019) ##
2
30
 
3
31
  * Remove deprecated `Module#reachable?` method.
@@ -18,7 +18,6 @@ module ActiveSupport
18
18
  DIR_FORMATTER = "%03X"
19
19
  FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
20
20
  FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
21
- EXCLUDED_DIRS = [".", ".."].freeze
22
21
  GITKEEP_FILES = [".gitkeep", ".keep"].freeze
23
22
 
24
23
  def initialize(cache_path, options = nil)
@@ -35,7 +34,7 @@ module ActiveSupport
35
34
  # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
36
35
  # config file when using +FileStore+ because everything in that directory will be deleted.
37
36
  def clear(options = nil)
38
- root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
37
+ root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
39
38
  FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
40
39
  rescue Errno::ENOENT
41
40
  end
@@ -154,7 +153,7 @@ module ActiveSupport
154
153
  # Delete empty directories in the cache.
155
154
  def delete_empty_directories(dir)
156
155
  return if File.realpath(dir) == File.realpath(cache_path)
157
- if exclude_from(dir, EXCLUDED_DIRS).empty?
156
+ if Dir.children(dir).empty?
158
157
  Dir.delete(dir) rescue nil
159
158
  delete_empty_directories(File.dirname(dir))
160
159
  end
@@ -167,8 +166,7 @@ module ActiveSupport
167
166
 
168
167
  def search_dir(dir, &callback)
169
168
  return if !File.exist?(dir)
170
- Dir.foreach(dir) do |d|
171
- next if EXCLUDED_DIRS.include?(d)
169
+ Dir.each_child(dir) do |d|
172
170
  name = File.join(dir, d)
173
171
  if File.directory?(name)
174
172
  search_dir(name, &callback)
@@ -193,11 +191,6 @@ module ActiveSupport
193
191
  end
194
192
  end
195
193
  end
196
-
197
- # Exclude entries from source directory
198
- def exclude_from(source, excludes)
199
- Dir.entries(source).reject { |f| excludes.include?(f) }
200
- end
201
194
  end
202
195
  end
203
196
  end
@@ -62,13 +62,13 @@ module ActiveSupport
62
62
  return if pruning?
63
63
  @pruning = true
64
64
  begin
65
- start_time = Time.now
65
+ start_time = Concurrent.monotonic_time
66
66
  cleanup
67
67
  instrument(:prune, target_size, from: @cache_size) do
68
68
  keys = synchronize { @key_access.keys.sort { |a, b| @key_access[a].to_f <=> @key_access[b].to_f } }
69
69
  keys.each do |key|
70
70
  delete_entry(key, options)
71
- return if @cache_size <= target_size || (max_time && Time.now - start_time > max_time)
71
+ return if @cache_size <= target_size || (max_time && Concurrent.monotonic_time - start_time > max_time)
72
72
  end
73
73
  end
74
74
  ensure
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_support/core_ext/hash/conversions"
4
4
  require "active_support/core_ext/hash/deep_merge"
5
+ require "active_support/core_ext/hash/deep_transform_values"
5
6
  require "active_support/core_ext/hash/except"
6
7
  require "active_support/core_ext/hash/indifferent_access"
7
8
  require "active_support/core_ext/hash/keys"
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ # Returns a new hash with all keys converted by the block operation.
5
+ # This includes the keys from the root hash and from all
6
+ # nested hashes and arrays.
7
+ #
8
+ # hash = { person: { name: 'Rob', age: '28' } }
9
+ #
10
+ # hash.deep_transform_values{ |value| value.to_s.upcase }
11
+ # # => {person: {name: "ROB", age: "28"}}
12
+ def deep_transform_values(&block)
13
+ _deep_transform_values_in_object(self, &block)
14
+ end
15
+
16
+ # Destructively converts all values by using the block operation.
17
+ # This includes the values from the root hash and from all
18
+ # nested hashes and arrays.
19
+ def deep_transform_values!(&block)
20
+ _deep_transform_values_in_object!(self, &block)
21
+ end
22
+
23
+ private
24
+ # support methods for deep transforming nested hashes and arrays
25
+ def _deep_transform_values_in_object(object, &block)
26
+ case object
27
+ when Hash
28
+ object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
29
+ when Array
30
+ object.map { |e| _deep_transform_values_in_object(e, &block) }
31
+ else
32
+ yield(object)
33
+ end
34
+ end
35
+
36
+ def _deep_transform_values_in_object!(object, &block)
37
+ case object
38
+ when Hash
39
+ object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
40
+ when Array
41
+ object.map! { |e| _deep_transform_values_in_object!(e, &block) }
42
+ else
43
+ yield(object)
44
+ end
45
+ end
46
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/kernel/agnostics"
4
3
  require "active_support/core_ext/kernel/concern"
5
4
  require "active_support/core_ext/kernel/reporting"
6
5
  require "active_support/core_ext/kernel/singleton_class"
@@ -119,10 +119,16 @@ module ActiveSupport
119
119
  end
120
120
  end
121
121
 
122
+ # Calls this block before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
123
+ def before_reset(&block)
124
+ set_callback :reset, :before, &block
125
+ end
126
+
122
127
  # Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
123
128
  def resets(&block)
124
129
  set_callback :reset, :after, &block
125
130
  end
131
+ alias_method :after_reset, :resets
126
132
 
127
133
  delegate :set, :reset, to: :instance
128
134
 
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/inflections"
4
+
5
+ module ActiveSupport
6
+ module Dependencies
7
+ module ZeitwerkIntegration # :nodoc: all
8
+ module Decorations
9
+ def clear
10
+ Dependencies.unload_interlock do
11
+ Rails.autoloaders.main.reload
12
+ end
13
+ end
14
+
15
+ def constantize(cpath)
16
+ ActiveSupport::Inflector.constantize(cpath)
17
+ end
18
+
19
+ def safe_constantize(cpath)
20
+ ActiveSupport::Inflector.safe_constantize(cpath)
21
+ end
22
+
23
+ def autoloaded_constants
24
+ (Rails.autoloaders.main.loaded + Rails.autoloaders.once.loaded).to_a
25
+ end
26
+
27
+ def autoloaded?(object)
28
+ cpath = object.is_a?(Module) ? object.name : object.to_s
29
+ Rails.autoloaders.any? { |autoloader| autoloader.loaded?(cpath) }
30
+ end
31
+
32
+ def verbose=(verbose)
33
+ l = verbose ? logger || Rails.logger : nil
34
+ Rails.autoloaders.each { |autoloader| autoloader.logger = l }
35
+ end
36
+
37
+ def unhook!
38
+ :no_op
39
+ end
40
+ end
41
+
42
+ module Inflector
43
+ def self.camelize(basename, _abspath)
44
+ basename.camelize
45
+ end
46
+ end
47
+
48
+ class << self
49
+ def take_over
50
+ setup_autoloaders
51
+ freeze_autoload_paths
52
+ decorate_dependencies
53
+ end
54
+
55
+ private
56
+
57
+ def setup_autoloaders
58
+ Rails.autoloaders.each do |autoloader|
59
+ autoloader.inflector = Inflector
60
+ end
61
+
62
+ Dependencies.autoload_paths.each do |autoload_path|
63
+ # Zeitwerk only accepts existing directories in `push_dir` to
64
+ # prevent misconfigurations.
65
+ next unless File.directory?(autoload_path)
66
+
67
+ if autoload_once?(autoload_path)
68
+ Rails.autoloaders.once.push_dir(autoload_path)
69
+ else
70
+ Rails.autoloaders.main.push_dir(autoload_path)
71
+ end
72
+ end
73
+
74
+ Rails.autoloaders.each(&:setup)
75
+ end
76
+
77
+ def autoload_once?(autoload_path)
78
+ Dependencies.autoload_once_paths.include?(autoload_path) ||
79
+ Gem.path.any? { |gem_path| autoload_path.to_s.start_with?(gem_path) }
80
+ end
81
+
82
+ def freeze_autoload_paths
83
+ Dependencies.autoload_paths.freeze
84
+ Dependencies.autoload_once_paths.freeze
85
+ end
86
+
87
+ def decorate_dependencies
88
+ Dependencies.unhook!
89
+ Dependencies.singleton_class.prepend(Decorations)
90
+ Object.class_eval { alias_method :require_dependency, :require }
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "tmpdir"
4
5
  require "active_support/message_encryptor"
5
6
 
6
7
  module ActiveSupport
@@ -67,7 +68,7 @@ module ActiveSupport
67
68
 
68
69
  write(updated_contents) if updated_contents != contents
69
70
  ensure
70
- FileUtils.rm(tmp_path) if tmp_path.exist?
71
+ FileUtils.rm(tmp_path) if tmp_path&.exist?
71
72
  end
72
73
 
73
74
 
@@ -10,7 +10,7 @@ module ActiveSupport
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "beta1"
13
+ PRE = "beta2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -164,6 +164,19 @@ module ActiveSupport
164
164
  super(convert_key(key))
165
165
  end
166
166
 
167
+ # Same as <tt>Hash#assoc</tt> where the key passed as argument can be
168
+ # either a string or a symbol:
169
+ #
170
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
171
+ # counters[:foo] = 1
172
+ #
173
+ # counters.assoc('foo') # => ["foo", 1]
174
+ # counters.assoc(:foo) # => ["foo", 1]
175
+ # counters.assoc(:zoo) # => nil
176
+ def assoc(key)
177
+ super(convert_key(key))
178
+ end
179
+
167
180
  # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
168
181
  # either a string or a symbol:
169
182
  #
@@ -53,7 +53,7 @@ module ActiveSupport
53
53
  # crypt.encrypt_and_sign(parcel, expires_in: 1.month)
54
54
  # crypt.encrypt_and_sign(doowad, expires_at: Time.now.end_of_year)
55
55
  #
56
- # Then the messages can be verified and returned upto the expire time.
56
+ # Then the messages can be verified and returned up to the expire time.
57
57
  # Thereafter, verifying returns +nil+.
58
58
  #
59
59
  # === Rotating keys
@@ -71,7 +71,7 @@ module ActiveSupport
71
71
  # @verifier.generate(parcel, expires_in: 1.month)
72
72
  # @verifier.generate(doowad, expires_at: Time.now.end_of_year)
73
73
  #
74
- # Then the messages can be verified and returned upto the expire time.
74
+ # Then the messages can be verified and returned up to the expire time.
75
75
  # Thereafter, the +verified+ method returns +nil+ while +verify+ raises
76
76
  # <tt>ActiveSupport::MessageVerifier::InvalidSignature</tt>.
77
77
  #
@@ -153,6 +153,15 @@ module ActiveSupport
153
153
  #
154
154
  # ActiveSupport::Notifications.unsubscribe("render")
155
155
  #
156
+ # Subscribers using a regexp or other pattern-matching object will remain subscribed
157
+ # to all events that match their original pattern, unless those events match a string
158
+ # passed to `unsubscribe`:
159
+ #
160
+ # subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
161
+ # ActiveSupport::Notifications.unsubscribe('render_template.action_view')
162
+ # subscriber.matches?('render_template.action_view') # => false
163
+ # subscriber.matches?('render_partial.action_view') # => true
164
+ #
156
165
  # == Default Queue
157
166
  #
158
167
  # Notifications ships with a queue implementation that consumes and publishes events
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "mutex_m"
4
4
  require "concurrent/map"
5
+ require "set"
5
6
 
6
7
  module ActiveSupport
7
8
  module Notifications
@@ -13,7 +14,8 @@ module ActiveSupport
13
14
  include Mutex_m
14
15
 
15
16
  def initialize
16
- @subscribers = []
17
+ @string_subscribers = Hash.new { |h, k| h[k] = [] }
18
+ @other_subscribers = []
17
19
  @listeners_for = Concurrent::Map.new
18
20
  super
19
21
  end
@@ -21,8 +23,13 @@ module ActiveSupport
21
23
  def subscribe(pattern = nil, block = Proc.new)
22
24
  subscriber = Subscribers.new pattern, block
23
25
  synchronize do
24
- @subscribers << subscriber
25
- @listeners_for.clear
26
+ if String === pattern
27
+ @string_subscribers[pattern] << subscriber
28
+ @listeners_for.delete(pattern)
29
+ else
30
+ @other_subscribers << subscriber
31
+ @listeners_for.clear
32
+ end
26
33
  end
27
34
  subscriber
28
35
  end
@@ -31,12 +38,19 @@ module ActiveSupport
31
38
  synchronize do
32
39
  case subscriber_or_name
33
40
  when String
34
- @subscribers.reject! { |s| s.matches?(subscriber_or_name) }
41
+ @string_subscribers[subscriber_or_name].clear
42
+ @listeners_for.delete(subscriber_or_name)
43
+ @other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
35
44
  else
36
- @subscribers.delete(subscriber_or_name)
45
+ pattern = subscriber_or_name.try(:pattern)
46
+ if String === pattern
47
+ @string_subscribers[pattern].delete(subscriber_or_name)
48
+ @listeners_for.delete(pattern)
49
+ else
50
+ @other_subscribers.delete(subscriber_or_name)
51
+ @listeners_for.clear
52
+ end
37
53
  end
38
-
39
- @listeners_for.clear
40
54
  end
41
55
  end
42
56
 
@@ -56,7 +70,8 @@ module ActiveSupport
56
70
  # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
57
71
  @listeners_for[name] || synchronize do
58
72
  # use synchronisation when accessing @subscribers
59
- @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
73
+ @listeners_for[name] ||=
74
+ @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
60
75
  end
61
76
  end
62
77
 
@@ -100,9 +115,33 @@ module ActiveSupport
100
115
  end
101
116
  end
102
117
 
118
+ class Matcher #:nodoc:
119
+ attr_reader :pattern, :exclusions
120
+
121
+ def self.wrap(pattern)
122
+ return pattern if String === pattern
123
+ new(pattern)
124
+ end
125
+
126
+ def initialize(pattern)
127
+ @pattern = pattern
128
+ @exclusions = Set.new
129
+ end
130
+
131
+ def unsubscribe!(name)
132
+ exclusions << -name if pattern === name
133
+ end
134
+
135
+ def ===(name)
136
+ pattern === name && !exclusions.include?(name)
137
+ end
138
+ end
139
+
103
140
  class Evented #:nodoc:
141
+ attr_reader :pattern
142
+
104
143
  def initialize(pattern, delegate)
105
- @pattern = pattern
144
+ @pattern = Matcher.wrap(pattern)
106
145
  @delegate = delegate
107
146
  @can_publish = delegate.respond_to?(:publish)
108
147
  end
@@ -122,11 +161,15 @@ module ActiveSupport
122
161
  end
123
162
 
124
163
  def subscribed_to?(name)
125
- @pattern === name
164
+ pattern === name
126
165
  end
127
166
 
128
167
  def matches?(name)
129
- @pattern && @pattern === name
168
+ pattern && pattern === name
169
+ end
170
+
171
+ def unsubscribe!(name)
172
+ pattern.unsubscribe!(name)
130
173
  end
131
174
  end
132
175
 
@@ -189,6 +232,10 @@ module ActiveSupport
189
232
  true
190
233
  end
191
234
 
235
+ def unsubscribe!(*)
236
+ false
237
+ end
238
+
192
239
  alias :matches? :===
193
240
  end
194
241
  end
@@ -137,7 +137,7 @@ module ActiveSupport
137
137
 
138
138
  private
139
139
  def now
140
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
140
+ Concurrent.monotonic_time
141
141
  end
142
142
 
143
143
  if clock_gettime_supported?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.beta1
4
+ version: 6.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-18 00:00:00.000000000 Z
11
+ date: 2019-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -78,6 +78,26 @@ dependencies:
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: 1.0.2
81
+ - !ruby/object:Gem::Dependency
82
+ name: zeitwerk
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '1.3'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 1.3.1
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.3'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 1.3.1
81
101
  description: A toolkit of support libraries and Ruby core extensions extracted from
82
102
  the Rails framework. Rich support for multibyte strings, internationalization, time
83
103
  zones, and testing.
@@ -148,6 +168,7 @@ files:
148
168
  - lib/active_support/core_ext/hash/compact.rb
149
169
  - lib/active_support/core_ext/hash/conversions.rb
150
170
  - lib/active_support/core_ext/hash/deep_merge.rb
171
+ - lib/active_support/core_ext/hash/deep_transform_values.rb
151
172
  - lib/active_support/core_ext/hash/except.rb
152
173
  - lib/active_support/core_ext/hash/indifferent_access.rb
153
174
  - lib/active_support/core_ext/hash/keys.rb
@@ -159,7 +180,6 @@ files:
159
180
  - lib/active_support/core_ext/integer/multiple.rb
160
181
  - lib/active_support/core_ext/integer/time.rb
161
182
  - lib/active_support/core_ext/kernel.rb
162
- - lib/active_support/core_ext/kernel/agnostics.rb
163
183
  - lib/active_support/core_ext/kernel/concern.rb
164
184
  - lib/active_support/core_ext/kernel/reporting.rb
165
185
  - lib/active_support/core_ext/kernel/singleton_class.rb
@@ -231,6 +251,7 @@ files:
231
251
  - lib/active_support/dependencies.rb
232
252
  - lib/active_support/dependencies/autoload.rb
233
253
  - lib/active_support/dependencies/interlock.rb
254
+ - lib/active_support/dependencies/zeitwerk_integration.rb
234
255
  - lib/active_support/deprecation.rb
235
256
  - lib/active_support/deprecation/behaviors.rb
236
257
  - lib/active_support/deprecation/constant_accessor.rb
@@ -335,8 +356,8 @@ homepage: http://rubyonrails.org
335
356
  licenses:
336
357
  - MIT
337
358
  metadata:
338
- source_code_uri: https://github.com/rails/rails/tree/v6.0.0.beta1/activesupport
339
- changelog_uri: https://github.com/rails/rails/blob/v6.0.0.beta1/activesupport/CHANGELOG.md
359
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.0.beta2/activesupport
360
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.0.beta2/activesupport/CHANGELOG.md
340
361
  post_install_message:
341
362
  rdoc_options:
342
363
  - "--encoding"
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Object
4
- # Makes backticks behave (somewhat more) similarly on all platforms.
5
- # On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
6
- # spawned shell prints a message to stderr and sets $?. We emulate
7
- # Unix on the former but not the latter.
8
- def `(command) #:nodoc:
9
- super
10
- rescue Errno::ENOENT => e
11
- STDERR.puts "#$0: #{e}"
12
- end
13
- end