bundler 1.14.6 → 1.15.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bundler might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +131 -43
- data/.travis.yml +5 -5
- data/CHANGELOG.md +52 -8
- data/CONTRIBUTING.md +10 -29
- data/README.md +13 -6
- data/Rakefile +4 -2
- data/bin/rubocop +1 -1
- data/doc/README.md +30 -0
- data/doc/TROUBLESHOOTING.md +64 -0
- data/doc/contributing/BUG_TRIAGE.md +36 -0
- data/doc/contributing/COMMUNITY.md +13 -0
- data/doc/contributing/GETTING_HELP.md +11 -0
- data/doc/contributing/HOW_YOU_CAN_HELP.md +27 -0
- data/doc/contributing/ISSUES.md +51 -0
- data/doc/contributing/README.md +38 -0
- data/doc/development/NEW_FEATURES.md +10 -0
- data/doc/development/PULL_REQUESTS.md +40 -0
- data/doc/development/README.md +19 -0
- data/doc/development/RELEASING.md +9 -0
- data/doc/development/SETUP.md +29 -0
- data/doc/documentation/README.md +29 -0
- data/doc/documentation/VISION.md +26 -0
- data/doc/documentation/WRITING.md +54 -0
- data/exe/bundle +4 -1
- data/lib/bundler.rb +20 -13
- data/lib/bundler/cli.rb +67 -3
- data/lib/bundler/cli/add.rb +26 -0
- data/lib/bundler/cli/config.rb +24 -6
- data/lib/bundler/cli/gem.rb +13 -8
- data/lib/bundler/cli/info.rb +51 -0
- data/lib/bundler/cli/inject.rb +8 -2
- data/lib/bundler/cli/install.rb +1 -1
- data/lib/bundler/cli/issue.rb +40 -0
- data/lib/bundler/cli/outdated.rb +16 -18
- data/lib/bundler/cli/pristine.rb +33 -0
- data/lib/bundler/cli/viz.rb +1 -1
- data/lib/bundler/definition.rb +64 -48
- data/lib/bundler/dsl.rb +6 -0
- data/lib/bundler/endpoint_specification.rb +3 -9
- data/lib/bundler/env.rb +3 -3
- data/lib/bundler/errors.rb +1 -1
- data/lib/bundler/fetcher/downloader.rb +3 -2
- data/lib/bundler/gem_helper.rb +5 -0
- data/lib/bundler/index.rb +9 -3
- data/lib/bundler/injector.rb +32 -11
- data/lib/bundler/installer.rb +1 -1
- data/lib/bundler/installer/parallel_installer.rb +15 -1
- data/lib/bundler/lazy_specification.rb +6 -0
- data/lib/bundler/lockfile_parser.rb +42 -34
- data/lib/bundler/mirror.rb +2 -0
- data/lib/bundler/plugin.rb +5 -1
- data/lib/bundler/plugin/api/source.rb +1 -1
- data/lib/bundler/plugin/index.rb +2 -0
- data/lib/bundler/remote_specification.rb +16 -7
- data/lib/bundler/resolver.rb +13 -3
- data/lib/bundler/rubygems_ext.rb +8 -3
- data/lib/bundler/rubygems_integration.rb +85 -36
- data/lib/bundler/runtime.rb +4 -1
- data/lib/bundler/settings.rb +2 -1
- data/lib/bundler/setup.rb +1 -1
- data/lib/bundler/shared_helpers.rb +26 -1
- data/lib/bundler/source.rb +17 -1
- data/lib/bundler/source/git.rb +16 -0
- data/lib/bundler/source/path.rb +13 -3
- data/lib/bundler/source/path/installer.rb +2 -2
- data/lib/bundler/source/rubygems.rb +5 -2
- data/lib/bundler/spec_set.rb +22 -13
- data/lib/bundler/stub_specification.rb +64 -2
- data/lib/bundler/templates/Executable +1 -1
- data/lib/bundler/templates/Executable.standalone +5 -5
- data/lib/bundler/templates/newgem/Gemfile.tt +2 -2
- data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
- data/lib/bundler/templates/newgem/README.md.tt +12 -6
- data/lib/bundler/templates/newgem/Rakefile.tt +5 -5
- data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
- data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +6 -6
- data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +4 -4
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +9 -9
- data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +3 -0
- data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +1 -1
- data/lib/bundler/templates/newgem/test/test_helper.rb.tt +3 -3
- data/lib/bundler/ui/shell.rb +9 -6
- data/lib/bundler/vendor/thor/lib/thor.rb +31 -23
- data/lib/bundler/vendor/thor/lib/thor/actions.rb +21 -22
- data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +2 -2
- data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +8 -8
- data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +23 -12
- data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +10 -14
- data/lib/bundler/vendor/thor/lib/thor/base.rb +30 -30
- data/lib/bundler/vendor/thor/lib/thor/command.rb +9 -9
- data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
- data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +7 -5
- data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +94 -63
- data/lib/bundler/vendor/thor/lib/thor/error.rb +3 -3
- data/lib/bundler/vendor/thor/lib/thor/group.rb +12 -12
- data/lib/bundler/vendor/thor/lib/thor/invocation.rb +4 -5
- data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +4 -7
- data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +16 -16
- data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +40 -19
- data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +7 -5
- data/lib/bundler/vendor/thor/lib/thor/runner.rb +25 -25
- data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +41 -26
- data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +4 -4
- data/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
- data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/lib/bundler/version.rb +14 -1
- data/lib/bundler/version_ranges.rb +75 -0
- data/lib/bundler/worker.rb +2 -1
- data/man/bundle-check.ronn +26 -0
- data/man/bundle-clean.ronn +18 -0
- data/man/bundle-config.ronn +4 -1
- data/man/bundle-info.ronn +17 -0
- data/man/bundle-init.ronn +18 -0
- data/man/bundle-inject.ronn +22 -0
- data/man/bundle-open.ronn +19 -0
- data/man/bundle-show.ronn +20 -0
- data/man/bundle-update.ronn +5 -2
- data/man/bundle-viz.ronn +30 -0
- data/man/bundle.ronn +3 -0
- data/man/gemfile.5.ronn +24 -64
- data/task/release.rake +115 -0
- metadata +49 -5
- data/DEVELOPMENT.md +0 -150
- data/ISSUES.md +0 -117
@@ -22,11 +22,8 @@ class Bundler::Thor
|
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
def insert_into_file(destination, *args, &block)
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
data, config = args.shift, args.shift
|
29
|
-
end
|
25
|
+
data = block_given? ? block : args.shift
|
26
|
+
config = args.shift
|
30
27
|
action InjectIntoFile.new(self, destination, data, config)
|
31
28
|
end
|
32
29
|
alias_method :inject_into_file, :insert_into_file
|
@@ -39,9 +36,9 @@ class Bundler::Thor
|
|
39
36
|
|
40
37
|
@behavior, @flag = if @config.key?(:after)
|
41
38
|
[:after, @config.delete(:after)]
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
else
|
40
|
+
[:before, @config.delete(:before)]
|
41
|
+
end
|
45
42
|
|
46
43
|
@replacement = data.is_a?(Proc) ? data.call : data
|
47
44
|
@flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
|
@@ -94,12 +91,11 @@ class Bundler::Thor
|
|
94
91
|
# Adds the content to the file.
|
95
92
|
#
|
96
93
|
def replace!(regexp, string, force)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
94
|
+
return if base.options[:pretend]
|
95
|
+
content = File.binread(destination)
|
96
|
+
if force || !content.include?(replacement)
|
97
|
+
content.gsub!(regexp, string)
|
98
|
+
File.open(destination, "wb") { |file| file.write(content) }
|
103
99
|
end
|
104
100
|
end
|
105
101
|
end
|
@@ -14,11 +14,11 @@ class Bundler::Thor
|
|
14
14
|
autoload :Group, "bundler/vendor/thor/lib/thor/group"
|
15
15
|
|
16
16
|
# Shortcuts for help.
|
17
|
-
HELP_MAPPINGS = %w
|
17
|
+
HELP_MAPPINGS = %w(-h -? --help -D)
|
18
18
|
|
19
19
|
# Bundler::Thor methods that should not be overwritten by the user.
|
20
|
-
THOR_RESERVED_WORDS = %w
|
21
|
-
action add_file create_file in_root inside run run_ruby_script
|
20
|
+
THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root
|
21
|
+
action add_file create_file in_root inside run run_ruby_script)
|
22
22
|
|
23
23
|
TEMPLATE_EXTNAME = ".tt"
|
24
24
|
|
@@ -41,8 +41,8 @@ class Bundler::Thor
|
|
41
41
|
#
|
42
42
|
# config<Hash>:: Configuration for this Bundler::Thor class.
|
43
43
|
#
|
44
|
-
def initialize(args = [], local_options = {}, config = {})
|
45
|
-
parse_options = self.class.class_options
|
44
|
+
def initialize(args = [], local_options = {}, config = {})
|
45
|
+
parse_options = config[:current_command] && config[:current_command].disable_class_options ? {} : self.class.class_options
|
46
46
|
|
47
47
|
# The start method splits inbound arguments at the first argument
|
48
48
|
# that looks like an option (starts with - or --). It then calls
|
@@ -52,11 +52,13 @@ class Bundler::Thor
|
|
52
52
|
command_options = config.delete(:command_options) # hook for start
|
53
53
|
parse_options = parse_options.merge(command_options) if command_options
|
54
54
|
if local_options.is_a?(Array)
|
55
|
-
array_options
|
55
|
+
array_options = local_options
|
56
|
+
hash_options = {}
|
56
57
|
else
|
57
58
|
# Handle the case where the class was explicitly instantiated
|
58
59
|
# with pre-parsed options.
|
59
|
-
array_options
|
60
|
+
array_options = []
|
61
|
+
hash_options = local_options
|
60
62
|
end
|
61
63
|
|
62
64
|
# Let Bundler::Thor::Options parse the options first, so it can remove
|
@@ -205,7 +207,7 @@ class Bundler::Thor
|
|
205
207
|
# ==== Errors
|
206
208
|
# ArgumentError:: Raised if you supply a required argument after a non required one.
|
207
209
|
#
|
208
|
-
def argument(name, options = {})
|
210
|
+
def argument(name, options = {})
|
209
211
|
is_thor_reserved_word?(name, :argument)
|
210
212
|
no_commands { attr_accessor name }
|
211
213
|
|
@@ -219,11 +221,13 @@ class Bundler::Thor
|
|
219
221
|
|
220
222
|
remove_argument name
|
221
223
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
224
|
+
if required
|
225
|
+
arguments.each do |argument|
|
226
|
+
next if argument.required?
|
227
|
+
raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " \
|
228
|
+
"the non-required argument #{argument.human_name.inspect}."
|
229
|
+
end
|
230
|
+
end
|
227
231
|
|
228
232
|
options[:required] = required
|
229
233
|
|
@@ -343,7 +347,7 @@ class Bundler::Thor
|
|
343
347
|
#
|
344
348
|
def all_commands
|
345
349
|
@all_commands ||= from_superclass(:all_commands, Bundler::Thor::CoreExt::OrderedHash.new)
|
346
|
-
@all_commands.merge(commands)
|
350
|
+
@all_commands.merge!(commands)
|
347
351
|
end
|
348
352
|
alias_method :all_tasks, :all_commands
|
349
353
|
|
@@ -467,11 +471,8 @@ class Bundler::Thor
|
|
467
471
|
alias_method :public_task, :public_command
|
468
472
|
|
469
473
|
def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
|
470
|
-
if has_namespace
|
471
|
-
|
472
|
-
else
|
473
|
-
fail UndefinedCommandError, "Could not find command #{command.inspect}."
|
474
|
-
end
|
474
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace." if has_namespace
|
475
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect}."
|
475
476
|
end
|
476
477
|
alias_method :handle_no_task_error, :handle_no_command_error
|
477
478
|
|
@@ -480,7 +481,7 @@ class Bundler::Thor
|
|
480
481
|
msg << "no arguments" if args.empty?
|
481
482
|
msg << "arguments " << args.inspect unless args.empty?
|
482
483
|
msg << "\nUsage: #{banner(command).inspect}"
|
483
|
-
|
484
|
+
raise InvocationError, msg
|
484
485
|
end
|
485
486
|
|
486
487
|
protected
|
@@ -513,14 +514,13 @@ class Bundler::Thor
|
|
513
514
|
padding = options.map { |o| o.aliases.size }.max.to_i * 4
|
514
515
|
|
515
516
|
options.each do |option|
|
516
|
-
|
517
|
-
|
518
|
-
|
517
|
+
next if option.hide
|
518
|
+
item = [option.usage(padding)]
|
519
|
+
item.push(option.description ? "# #{option.description}" : "")
|
519
520
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
end
|
521
|
+
list << item
|
522
|
+
list << ["", "# Default: #{option.default}"] if option.show_default?
|
523
|
+
list << ["", "# Possible values: #{option.enum.join(', ')}"] if option.enum
|
524
524
|
end
|
525
525
|
|
526
526
|
shell.say(group_name ? "#{group_name} options:" : "Options:")
|
@@ -531,7 +531,7 @@ class Bundler::Thor
|
|
531
531
|
# Raises an error if the word given is a Bundler::Thor reserved word.
|
532
532
|
def is_thor_reserved_word?(word, type) #:nodoc:
|
533
533
|
return false unless THOR_RESERVED_WORDS.include?(word.to_s)
|
534
|
-
|
534
|
+
raise "#{word.inspect} is a Bundler::Thor reserved word and cannot be defined as #{type}"
|
535
535
|
end
|
536
536
|
|
537
537
|
# Build an option and adds it to the given scope.
|
@@ -566,7 +566,7 @@ class Bundler::Thor
|
|
566
566
|
elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition
|
567
567
|
commands[name.to_s] = command.clone
|
568
568
|
else
|
569
|
-
|
569
|
+
raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
|
570
570
|
end
|
571
571
|
end
|
572
572
|
alias_method :find_and_refresh_task, :find_and_refresh_command
|
@@ -649,7 +649,7 @@ class Bundler::Thor
|
|
649
649
|
|
650
650
|
# SIGNATURE: The hook invoked by start.
|
651
651
|
def dispatch(command, given_args, given_opts, config) #:nodoc:
|
652
|
-
|
652
|
+
raise NotImplementedError
|
653
653
|
end
|
654
654
|
end
|
655
655
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Bundler::Thor
|
2
|
-
class Command < Struct.new(:name, :description, :long_description, :usage, :options)
|
2
|
+
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :disable_class_options)
|
3
3
|
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
|
4
4
|
|
5
|
-
def initialize(name, description, long_description, usage, options = nil)
|
6
|
-
super(name.to_s, description, long_description, usage, options || {})
|
5
|
+
def initialize(name, description, long_description, usage, options = nil, disable_class_options = false)
|
6
|
+
super(name.to_s, description, long_description, usage, options || {}, disable_class_options)
|
7
7
|
end
|
8
8
|
|
9
9
|
def initialize_copy(other) #:nodoc:
|
@@ -33,7 +33,7 @@ class Bundler::Thor
|
|
33
33
|
rescue ArgumentError => e
|
34
34
|
handle_argument_error?(instance, e, caller) ? instance.class.handle_argument_error(self, e, args, arity) : (raise e)
|
35
35
|
rescue NoMethodError => e
|
36
|
-
handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (
|
36
|
+
handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (raise e)
|
37
37
|
end
|
38
38
|
|
39
39
|
# Returns the formatted usage by injecting given required arguments
|
@@ -50,7 +50,7 @@ class Bundler::Thor
|
|
50
50
|
# Add usage with required arguments
|
51
51
|
formatted << if klass && !klass.arguments.empty?
|
52
52
|
usage.to_s.gsub(/^#{name}/) do |match|
|
53
|
-
match << " " << klass.arguments.map
|
53
|
+
match << " " << klass.arguments.map(&:usage).compact.join(" ")
|
54
54
|
end
|
55
55
|
else
|
56
56
|
usage.to_s
|
@@ -88,7 +88,7 @@ class Bundler::Thor
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def sans_backtrace(backtrace, caller) #:nodoc:
|
91
|
-
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) || (frame =~
|
91
|
+
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) || (frame =~ %r{^kernel/} && RUBY_ENGINE =~ /rbx/) }
|
92
92
|
saned - caller
|
93
93
|
end
|
94
94
|
|
@@ -105,7 +105,7 @@ class Bundler::Thor
|
|
105
105
|
error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
|
106
106
|
end
|
107
107
|
end
|
108
|
-
Task = Command
|
108
|
+
Task = Command
|
109
109
|
|
110
110
|
# A command that is hidden in help messages but still invocable.
|
111
111
|
class HiddenCommand < Command
|
@@ -113,7 +113,7 @@ class Bundler::Thor
|
|
113
113
|
true
|
114
114
|
end
|
115
115
|
end
|
116
|
-
HiddenTask = HiddenCommand
|
116
|
+
HiddenTask = HiddenCommand
|
117
117
|
|
118
118
|
# A dynamic command that handles method missing scenarios.
|
119
119
|
class DynamicCommand < Command
|
@@ -129,5 +129,5 @@ class Bundler::Thor
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
132
|
-
DynamicTask = DynamicCommand
|
132
|
+
DynamicTask = DynamicCommand
|
133
133
|
end
|
@@ -28,6 +28,14 @@ class Bundler::Thor
|
|
28
28
|
super(convert_key(key))
|
29
29
|
end
|
30
30
|
|
31
|
+
def fetch(key, *args)
|
32
|
+
super(convert_key(key), *args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def key?(key)
|
36
|
+
super(convert_key(key))
|
37
|
+
end
|
38
|
+
|
31
39
|
def values_at(*indices)
|
32
40
|
indices.map { |key| self[convert_key(key)] }
|
33
41
|
end
|
@@ -60,7 +68,7 @@ class Bundler::Thor
|
|
60
68
|
# options.shebang # => "/usr/lib/local/ruby"
|
61
69
|
# options.test_framework?(:rspec) # => options[:test_framework] == :rspec
|
62
70
|
#
|
63
|
-
def method_missing(method, *args
|
71
|
+
def method_missing(method, *args)
|
64
72
|
method = method.to_s
|
65
73
|
if method =~ /^(\w+)\?$/
|
66
74
|
if args.empty?
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class IO #:nodoc:
|
2
2
|
class << self
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
unless method_defined? :binread
|
4
|
+
def binread(file, *args)
|
5
|
+
raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
|
6
|
+
File.open(file, "rb") do |f|
|
7
|
+
f.read(*args)
|
8
|
+
end
|
7
9
|
end
|
8
|
-
end
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,96 +1,127 @@
|
|
1
1
|
class Bundler::Thor
|
2
|
-
module CoreExt
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# It keeps the semantics and most of the efficiency of normal hashes
|
10
|
-
# while also keeping track of the order in which elements were set.
|
11
|
-
#
|
12
|
-
class OrderedHash #:nodoc:
|
13
|
-
include Enumerable
|
14
|
-
|
15
|
-
Node = Struct.new(:key, :value, :next, :prev)
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@hash = {}
|
2
|
+
module CoreExt
|
3
|
+
class OrderedHash < ::Hash
|
4
|
+
if RUBY_VERSION < "1.9"
|
5
|
+
def initialize(*args, &block)
|
6
|
+
super
|
7
|
+
@keys = []
|
19
8
|
end
|
20
9
|
|
21
|
-
def
|
22
|
-
|
10
|
+
def initialize_copy(other)
|
11
|
+
super
|
12
|
+
# make a deep copy of keys
|
13
|
+
@keys = other.keys
|
23
14
|
end
|
24
15
|
|
25
16
|
def []=(key, value)
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
node = Node.new(key, value)
|
30
|
-
|
31
|
-
if !defined?(@first) || @first.nil?
|
32
|
-
@first = @last = node
|
33
|
-
else
|
34
|
-
node.prev = @last
|
35
|
-
@last.next = node
|
36
|
-
@last = node
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
@hash[key] = node
|
41
|
-
value
|
17
|
+
@keys << key unless key?(key)
|
18
|
+
super
|
42
19
|
end
|
43
20
|
|
44
21
|
def delete(key)
|
45
|
-
if
|
46
|
-
|
47
|
-
|
22
|
+
if key? key
|
23
|
+
index = @keys.index(key)
|
24
|
+
@keys.delete_at index
|
25
|
+
end
|
26
|
+
super
|
27
|
+
end
|
48
28
|
|
49
|
-
|
50
|
-
|
29
|
+
def delete_if
|
30
|
+
super
|
31
|
+
sync_keys!
|
32
|
+
self
|
33
|
+
end
|
51
34
|
|
52
|
-
|
53
|
-
@last = prev_node if @last == node
|
35
|
+
alias_method :reject!, :delete_if
|
54
36
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@hash.delete(key)
|
59
|
-
value
|
37
|
+
def reject(&block)
|
38
|
+
dup.reject!(&block)
|
60
39
|
end
|
61
40
|
|
62
41
|
def keys
|
63
|
-
|
42
|
+
@keys.dup
|
64
43
|
end
|
65
44
|
|
66
45
|
def values
|
67
|
-
map { |
|
46
|
+
@keys.map { |key| self[key] }
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_hash
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_a
|
54
|
+
@keys.map { |key| [key, self[key]] }
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_key
|
58
|
+
return to_enum(:each_key) unless block_given?
|
59
|
+
@keys.each { |key| yield(key) }
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def each_value
|
64
|
+
return to_enum(:each_value) unless block_given?
|
65
|
+
@keys.each { |key| yield(self[key]) }
|
66
|
+
self
|
68
67
|
end
|
69
68
|
|
70
69
|
def each
|
71
|
-
return
|
72
|
-
|
73
|
-
node = @first
|
74
|
-
yield [node.key, node.value] while node = node.next # rubocop:disable AssignmentInCondition
|
70
|
+
return to_enum(:each) unless block_given?
|
71
|
+
@keys.each { |key| yield([key, self[key]]) }
|
75
72
|
self
|
76
73
|
end
|
77
74
|
|
78
|
-
def
|
79
|
-
|
75
|
+
def each_pair
|
76
|
+
return to_enum(:each_pair) unless block_given?
|
77
|
+
@keys.each { |key| yield(key, self[key]) }
|
78
|
+
self
|
79
|
+
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
alias_method :select, :find_all
|
82
|
+
|
83
|
+
def clear
|
84
|
+
super
|
85
|
+
@keys.clear
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
def shift
|
90
|
+
k = @keys.first
|
91
|
+
v = delete(k)
|
92
|
+
[k, v]
|
93
|
+
end
|
84
94
|
|
85
|
-
|
86
|
-
|
95
|
+
def merge!(other_hash)
|
96
|
+
if block_given?
|
97
|
+
other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
|
98
|
+
else
|
99
|
+
other_hash.each { |k, v| self[k] = v }
|
87
100
|
end
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
alias_method :update, :merge!
|
105
|
+
|
106
|
+
def merge(other_hash, &block)
|
107
|
+
dup.merge!(other_hash, &block)
|
108
|
+
end
|
88
109
|
|
89
|
-
|
110
|
+
# When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
|
111
|
+
def replace(other)
|
112
|
+
super
|
113
|
+
@keys = other.keys
|
114
|
+
self
|
90
115
|
end
|
91
116
|
|
92
|
-
def
|
93
|
-
|
117
|
+
def inspect
|
118
|
+
"#<#{self.class} #{super}>"
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def sync_keys!
|
124
|
+
@keys.delete_if { |k| !key?(k) }
|
94
125
|
end
|
95
126
|
end
|
96
127
|
end
|