diff --git a/.travis.yml b/.travis.yml index fdf5766e7..104fc45f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,9 @@ before_install: - gem update --system 2.7.9 - gem install bundler:1.17.3 - rvm @global do gem uninstall did_you_mean - - # Travis's rvm 2.5.5 installation comes with bundler 2.0.1 for some reason. - - if [ "$TRAVIS_RUBY_VERSION" = "2.5.5" ]; then rvm @global do gem uninstall bundler -v 2.0.1 -x; fi bundler_args: --without development language: ruby rvm: - - 1.8.7 - - 1.9.3 - 2.0.0 - 2.1.10 - 2.2.10 diff --git a/Gemfile b/Gemfile index dd829a330..4d6779ffd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,42 +1,30 @@ source "https://rubygems.org" gem "rake", "< 11" -gem "rdoc", "~> 4.2.2" # This is to support Ruby 1.8 and 1.9 group :development do gem "pry" platforms :ruby_21 do gem "pry-byebug" end - platforms :ruby_19, :ruby_20 do + platforms :ruby_20 do gem "pry-debugger" gem "pry-stack_explorer" end end group :test do - gem "addressable", "~> 2.3.6", :platforms => [:ruby_18] gem "childlabor" gem "coveralls", ">= 0.8.19" - gem "json", "< 2" # This is to support Ruby 1.8 and 1.9 - gem "mime-types", "~> 1.25", :platforms => [:jruby, :ruby_18] - gem "rest-client", "~> 1.6.0", :platforms => [:jruby, :ruby_18] + gem "mime-types", "~> 1.25", :platforms => [:jruby] + gem "rest-client", "~> 1.6.0", :platforms => [:jruby] gem "rspec", ">= 3" gem "rspec-mocks", ">= 3" - gem "rubocop", ">= 0.19", :platforms => [:ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24] + gem "rubocop", ">= 0.19" gem "simplecov", ">= 0.13" - gem "term-ansicolor", "~> 1.3.2" # This is to support Ruby 1.8 and 1.9 - gem "tins", "< 1.7" # This is to support Ruby 1.8 and 1.9 - if RUBY_VERSION < "1.9.3" - gem "webmock", ">= 1.20", "< 2" # This is to support Ruby 1.8 and 1.9.2 - gem "hashdiff", "< 0.3.6" # Hashdiff 0.3.6 no longer supports Ruby 1.8 - else - gem "webmock" - end - if RUBY_VERSION >= '1.9' - # `did_you_mean` can't build with Ruby 1.8. - gem 'did_you_mean' - end + gem "webmock" end +gem 'did_you_mean' + gemspec diff --git a/lib/thor/base.rb b/lib/thor/base.rb index a07ee6140..a2b8ab34b 100644 --- a/lib/thor/base.rb +++ b/lib/thor/base.rb @@ -1,6 +1,5 @@ require "thor/command" require "thor/core_ext/hash_with_indifferent_access" -require "thor/core_ext/ordered_hash" require "thor/error" require "thor/invocation" require "thor/parser" @@ -354,22 +353,22 @@ def group(name = nil) # Returns the commands for this Thor class. # # ==== Returns - # OrderedHash:: An ordered hash with commands names as keys and Thor::Command - # objects as values. + # Hash:: An ordered hash with commands names as keys and Thor::Command + # objects as values. # def commands - @commands ||= Thor::CoreExt::OrderedHash.new + @commands ||= Hash.new end alias_method :tasks, :commands # Returns the commands for this Thor class and all subclasses. # # ==== Returns - # OrderedHash:: An ordered hash with commands names as keys and Thor::Command - # objects as values. + # Hash:: An ordered hash with commands names as keys and Thor::Command + # objects as values. # def all_commands - @all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new) + @all_commands ||= from_superclass(:all_commands, Hash.new) @all_commands.merge!(commands) end alias_method :all_tasks, :all_commands diff --git a/lib/thor/command.rb b/lib/thor/command.rb index e3487ce5d..56ca79538 100644 --- a/lib/thor/command.rb +++ b/lib/thor/command.rb @@ -97,8 +97,7 @@ def sans_backtrace(backtrace, caller) #:nodoc: def handle_argument_error?(instance, error, caller) not_debugging?(instance) && (error.message =~ /wrong number of arguments/ || error.message =~ /given \d*, expected \d*/) && begin saned = sans_backtrace(error.backtrace, caller) - # Ruby 1.9 always include the called method in the backtrace - saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9") + saned.empty? || saned.size == 1 end end diff --git a/lib/thor/core_ext/ordered_hash.rb b/lib/thor/core_ext/ordered_hash.rb deleted file mode 100644 index 778772f3d..000000000 --- a/lib/thor/core_ext/ordered_hash.rb +++ /dev/null @@ -1,129 +0,0 @@ -class Thor - module CoreExt - class OrderedHash < ::Hash - if RUBY_VERSION < "1.9" - def initialize(*args, &block) - super - @keys = [] - end - - def initialize_copy(other) - super - # make a deep copy of keys - @keys = other.keys - end - - def []=(key, value) - @keys << key unless key?(key) - super - end - - def delete(key) - if key? key - index = @keys.index(key) - @keys.delete_at index - end - super - end - - def delete_if - super - sync_keys! - self - end - - alias_method :reject!, :delete_if - - def reject(&block) - dup.reject!(&block) - end - - def keys - @keys.dup - end - - def values - @keys.map { |key| self[key] } - end - - def to_hash - self - end - - def to_a - @keys.map { |key| [key, self[key]] } - end - - def each_key - return to_enum(:each_key) unless block_given? - @keys.each { |key| yield(key) } - self - end - - def each_value - return to_enum(:each_value) unless block_given? - @keys.each { |key| yield(self[key]) } - self - end - - def each - return to_enum(:each) unless block_given? - @keys.each { |key| yield([key, self[key]]) } - self - end - - def each_pair - return to_enum(:each_pair) unless block_given? - @keys.each { |key| yield(key, self[key]) } - self - end - - alias_method :select, :find_all - - def clear - super - @keys.clear - self - end - - def shift - k = @keys.first - v = delete(k) - [k, v] - end - - def merge!(other_hash) - if block_given? - other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v } - else - other_hash.each { |k, v| self[k] = v } - end - self - end - - alias_method :update, :merge! - - def merge(other_hash, &block) - dup.merge!(other_hash, &block) - end - - # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not. - def replace(other) - super - @keys = other.keys - self - end - - def inspect - "#<#{self.class} #{super}>" - end - - private - - def sync_keys! - @keys.delete_if { |k| !key?(k) } - end - end - end - end -end diff --git a/lib/thor/line_editor/basic.rb b/lib/thor/line_editor/basic.rb index 76cefcd4c..32c3d862f 100644 --- a/lib/thor/line_editor/basic.rb +++ b/lib/thor/line_editor/basic.rb @@ -24,7 +24,7 @@ def get_input $stdin.gets else # Lazy-load io/console since it is gem-ified as of 2.3 - require "io/console" if RUBY_VERSION > "1.9.2" + require "io/console" $stdin.noecho(&:gets) end end diff --git a/lib/thor/line_editor/readline.rb b/lib/thor/line_editor/readline.rb index 32446e333..e4a2c44c3 100644 --- a/lib/thor/line_editor/readline.rb +++ b/lib/thor/line_editor/readline.rb @@ -13,10 +13,7 @@ def self.available? def readline if echo? ::Readline.completion_append_character = nil - # Ruby 1.8.7 does not allow Readline.completion_proc= to receive nil. - if complete = completion_proc - ::Readline.completion_proc = complete - end + ::Readline.completion_proc = completion_proc ::Readline.readline(prompt, add_to_history?) else super diff --git a/spec/core_ext/ordered_hash_spec.rb b/spec/core_ext/ordered_hash_spec.rb deleted file mode 100644 index 614fc89f2..000000000 --- a/spec/core_ext/ordered_hash_spec.rb +++ /dev/null @@ -1,198 +0,0 @@ -require "helper" -require "thor/core_ext/ordered_hash" - -describe Thor::CoreExt::OrderedHash do - subject { Thor::CoreExt::OrderedHash.new } - - def populate_subject - subject[:foo] = "Foo!" - subject[:bar] = "Bar!" - subject[:baz] = "Baz!" - subject[:bop] = "Bop!" - subject[:bat] = "Bat!" - end - - describe "#initialize" do - it "is empty" do - expect(subject).to be_empty - end - end - - describe "#replace" do - before { populate_subject } - it "replaces the keys" do - other_hash = Thor::CoreExt::OrderedHash.new - other_hash[1] = "one" - other_hash[2] = "two" - other_hash[3] = "three" - - subject.replace(other_hash) - expect(subject.keys).to eq [1,2,3] - end - end - - describe "#[]" do - it "returns nil for an undefined key" do - expect(subject[:boom]).to be nil - end - - before { populate_subject } - it "returns the value for each key" do - expect(subject[:foo]).to eq "Foo!" - end - end - - describe "#[]=" do - it "does not duplicate keys" do - subject[:key] = 1 - subject[:key] = 2 - - expect(subject.keys.size).to eq 1 - expect(subject[:key]).to eq 2 - end - - it "does not move an overwritten node to the end of the ordering" do - populate_subject - - subject[:baz] = "Bip!" - expect(subject.values).to eq(["Foo!", "Bar!", "Bip!", "Bop!", "Bat!"]) - - subject[:foo] = "Bip!" - expect(subject.values).to eq(["Bip!", "Bar!", "Bip!", "Bop!", "Bat!"]) - - subject[:bat] = "Bip!" - expect(subject.values).to eq(["Bip!", "Bar!", "Bip!", "Bop!", "Bip!"]) - end - end - - describe "#clear" do - before { populate_subject } - it "clears the keys" do - subject.clear - expect(subject.keys).to be_empty - end - end - - describe "#shift" do - before { populate_subject } - it "pops the first key/value" do - arr = subject.shift - expect(arr).to eq [:foo, "Foo!"] - end - - it "removes the key" do - subject.shift - expect(subject.keys).to_not include(:foo) - end - end - - describe "#each" do - before { populate_subject } - it "iterates through the keys and values in order of assignment" do - arr = [] - subject.each do |key, value| - arr << [key, value] - end - - expect(arr).to eq([[:foo, "Foo!"], [:bar, "Bar!"], [:baz, "Baz!"], - [:bop, "Bop!"], [:bat, "Bat!"]]) - end - end - - describe "#merge!" do - it "modifies the existing object" do - populate_subject - - other_hash = Thor::CoreExt::OrderedHash.new - other_hash[1] = "one" - other_hash[2] = "two" - other_hash[3] = "three" - - subject.merge!(other_hash) - - expect(subject.values).to eq(["Foo!", "Bar!", "Baz!", "Bop!", "Bat!", "one", "two", "three"]) - end - end - - describe "#merge" do - it "appends another ordered hash while preserving ordering" do - populate_subject - - other_hash = Thor::CoreExt::OrderedHash.new - other_hash[1] = "one" - other_hash[2] = "two" - other_hash[3] = "three" - - - merged_list = subject.merge(other_hash) - expect(merged_list.values).to eq(["Foo!", "Bar!", "Baz!", "Bop!", "Bat!", "one", "two", "three"]) - end - - it "overwrites hash keys with matching appended keys" do - populate_subject - - other_hash = Thor::CoreExt::OrderedHash.new - other_hash[:bar] = "bar" - - expect(subject.merge(other_hash)[:bar]).to eq("bar") - expect(subject[:bar]).to eq("Bar!") - end - end - - describe "#to_a" do - before { populate_subject } - it "converts to an array" do - expect(subject.to_a).to eq([[:foo, "Foo!"], [:bar, "Bar!"], [:baz, "Baz!"], [:bop, "Bop!"], [:bat, "Bat!"]]) - end - end - - describe "#keys" do - context "when list is unpopulated" do - it "has an empty keys list" do - expect(subject.keys).to be_empty - end - end - - it "returns the keys in order of insertion" do - populate_subject - expect(subject.keys).to eq([:foo, :bar, :baz, :bop, :bat]) - end - end - - describe "#values" do - it "returns the values in order of insertion" do - populate_subject - expect(subject.values).to eq(["Foo!", "Bar!", "Baz!", "Bop!", "Bat!"]) - end - - context "when list is unpopulated" do - it "has an empty list" do - list = described_class.new - expect(list.values).to be_empty - end - end - end - - describe "#delete" do - before { populate_subject } - it "deletes the value given the key" do - expect(subject.delete(:baz)).to eq("Baz!") - expect(subject.values).to eq(["Foo!", "Bar!", "Bop!", "Bat!"]) - - expect(subject.delete(:foo)).to eq("Foo!") - expect(subject.values).to eq(["Bar!", "Bop!", "Bat!"]) - - expect(subject.delete(:bat)).to eq("Bat!") - expect(subject.values).to eq(["Bar!", "Bop!"]) - end - - it "returns nil if the value to be deleted can't be found" do - expect(subject.delete(:nothing)).to be nil - end - - it "deletes the given key" do - subject.delete(:baz) - expect(subject.keys).to_not include(:baz) - end - end -end diff --git a/spec/helper.rb b/spec/helper.rb index 993448d40..d51d6516c 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -1,15 +1,13 @@ $TESTING = true -if RUBY_VERSION >= "1.9" - require "simplecov" - require "coveralls" +require "simplecov" +require "coveralls" - SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter] +SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter] - SimpleCov.start do - add_filter "/spec" - minimum_coverage(90) - end +SimpleCov.start do + add_filter "/spec" + minimum_coverage(90) end $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) @@ -28,7 +26,6 @@ $0 = "thor" $thor_runner = true ARGV.clear -Encoding.default_external = Encoding::UTF_8 if RUBY_VERSION > '1.8.7' && RUBY_VERSION < '2.0.0' Thor::Base.shell = Thor::Shell::Basic # Load fixtures diff --git a/spec/invocation_spec.rb b/spec/invocation_spec.rb index 3241a1e0d..eb6d805d2 100644 --- a/spec/invocation_spec.rb +++ b/spec/invocation_spec.rb @@ -61,13 +61,7 @@ it "returns the command chain" do expect(I.new.invoke("two")).to eq([:two]) - if RUBY_VERSION < "1.9.3" - result = J.start(%w(one two)) - expect(result).to include(:one) - expect(result).to include(:two) - else - expect(J.start(%w(one two))).to eq([:one, :two]) - end + expect(J.start(%w(one two))).to eq([:one, :two]) end it "dump configuration values to be used in the invoked class" do diff --git a/spec/line_editor/readline_spec.rb b/spec/line_editor/readline_spec.rb index b2b0712d6..df426d3b4 100644 --- a/spec/line_editor/readline_spec.rb +++ b/spec/line_editor/readline_spec.rb @@ -23,14 +23,14 @@ describe "#readline" do it "invokes the readline library" do expect(::Readline).to receive(:readline).with("> ", true).and_return("foo") - expect(::Readline).not_to receive(:completion_proc=) + expect(::Readline).to receive(:completion_proc=) editor = Thor::LineEditor::Readline.new("> ", {}) expect(editor.readline).to eq("foo") end it "supports the add_to_history option" do expect(::Readline).to receive(:readline).with("> ", false).and_return("foo") - expect(::Readline).not_to receive(:completion_proc=) + expect(::Readline).to receive(:completion_proc=) editor = Thor::LineEditor::Readline.new("> ", :add_to_history => false) expect(editor.readline).to eq("foo") end diff --git a/spec/script_exit_status_spec.rb b/spec/script_exit_status_spec.rb index 9d987185c..49ed5439c 100644 --- a/spec/script_exit_status_spec.rb +++ b/spec/script_exit_status_spec.rb @@ -26,4 +26,4 @@ def thor_command(command) it "a command that does not raise a Thor::Error exits with a status of 0" do expect(thor_command("ok")).to eq(0) end -end if RUBY_VERSION > "1.8.7" +end diff --git a/spec/util_spec.rb b/spec/util_spec.rb index af6812053..2182bed89 100644 --- a/spec/util_spec.rb +++ b/spec/util_spec.rb @@ -17,7 +17,7 @@ def self.clear_user_home! end it "returns nil if the namespace can't be found" do - expect(Thor::Util.find_by_namespace("thor:core_ext:ordered_hash")).to be nil + expect(Thor::Util.find_by_namespace("thor:core_ext:hash_with_indifferent_access")).to be nil end it "returns a class if it matches the namespace" do @@ -39,7 +39,7 @@ def self.clear_user_home! end it "accepts class and module objects" do - expect(Thor::Util.namespace_from_thor_class(Thor::CoreExt::OrderedHash)).to eq("thor:core_ext:ordered_hash") + expect(Thor::Util.namespace_from_thor_class(Thor::CoreExt::HashWithIndifferentAccess)).to eq("thor:core_ext:hash_with_indifferent_access") expect(Thor::Util.namespace_from_thor_class(Thor::Util)).to eq("thor:util") end diff --git a/thor.gemspec b/thor.gemspec index b882721c8..a81f5f5bb 100644 --- a/thor.gemspec +++ b/thor.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |spec| spec.licenses = %w(MIT) spec.name = "thor" spec.require_paths = %w(lib) - spec.required_ruby_version = ">= 1.8.7" + spec.required_ruby_version = ">= 2.0.0" spec.required_rubygems_version = ">= 1.3.5" spec.summary = spec.description spec.version = Thor::VERSION