summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-02-05 13:42:45 +0000
committerhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-02-05 13:42:45 +0000
commitc3546c76c8f1c9d61e65d08e8b2dfca2e2098736 (patch)
tree6f3288db1b5970c4d4c65d7736719ef15b44a328
parent69be3620302aab57c43014aca08629c9d7b7ce44 (diff)
* lib/rubygems: Update to RubyGems HEAD(5c3b6f3).
Fixed #1156, #1142, #1115, #1142, #1139 on rubygems/rubygems * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49511 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--lib/rubygems/basic_specification.rb2
-rw-r--r--lib/rubygems/commands/open_command.rb4
-rw-r--r--lib/rubygems/installer.rb2
-rw-r--r--lib/rubygems/request_set.rb12
-rw-r--r--lib/rubygems/request_set/lockfile.rb445
-rw-r--r--lib/rubygems/request_set/lockfile/parser.rb334
-rw-r--r--lib/rubygems/request_set/lockfile/tokenizer.rb108
-rw-r--r--lib/rubygems/requirement.rb2
-rw-r--r--lib/rubygems/specification.rb18
-rw-r--r--lib/rubygems/test_case.rb4
-rw-r--r--lib/rubygems/user_interaction.rb8
-rw-r--r--test/rubygems/test_gem_commands_open_command.rb12
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb19
-rw-r--r--test/rubygems/test_gem_request_set_lockfile.rb810
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_parser.rb543
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_tokenizer.rb305
-rw-r--r--test/rubygems/test_gem_requirement.rb10
-rw-r--r--test/rubygems/test_gem_specification.rb8
-rw-r--r--test/rubygems/test_gem_stub_specification.rb2
20 files changed, 1391 insertions, 1263 deletions
diff --git a/ChangeLog b/ChangeLog
index 181000d..590f16c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Feb 5 22:42:34 2015 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
+
+ * lib/rubygems: Update to RubyGems HEAD(5c3b6f3).
+ Fixed #1156, #1142, #1115, #1142, #1139 on rubygems/rubygems
+ * test/rubygems: ditto.
+
Thu Feb 5 13:41:01 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_eval.c (send_internal), vm_insnhelper.c (vm_call_opt_send):
diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb
index d1cee4f..e27b261 100644
--- a/lib/rubygems/basic_specification.rb
+++ b/lib/rubygems/basic_specification.rb
@@ -144,7 +144,7 @@ class Gem::BasicSpecification
File.join full_gem_path, path
end
- full_paths.unshift extension_dir unless @extensions.nil? || @extensions.empty?
+ full_paths << extension_dir unless @extensions.nil? || @extensions.empty?
full_paths
end
diff --git a/lib/rubygems/commands/open_command.rb b/lib/rubygems/commands/open_command.rb
index 91963bb..254a742 100644
--- a/lib/rubygems/commands/open_command.rb
+++ b/lib/rubygems/commands/open_command.rb
@@ -61,7 +61,9 @@ class Gem::Commands::OpenCommand < Gem::Command
end
def open_editor path
- system(*@editor.split(/\s+/) + [path])
+ Dir.chdir(path) do
+ system(*@editor.split(/\s+/) + [path])
+ end
end
def spec_for name
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 877cb21..10fc1a3 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -681,7 +681,7 @@ TEXT
# return the stub script text used to launch the true Ruby script
def windows_stub_script(bindir, bin_file_name)
- ruby = Gem.ruby.chomp('"').tr(File::SEPARATOR, "\\")
+ ruby = Gem.ruby.gsub(/^\"|\"$/, "").tr(File::SEPARATOR, "\\")
return <<-TEXT
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index 05bfcbe..819a1d8 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -116,7 +116,7 @@ class Gem::RequestSet
if dep = @dependency_names[name] then
dep.requirement.concat reqs
else
- dep = Gem::Dependency.new name, reqs
+ dep = Gem::Dependency.new name, *reqs
@dependency_names[name] = dep
@dependencies << dep
end
@@ -275,8 +275,13 @@ class Gem::RequestSet
@git_set.root_dir = @install_dir
- lockfile = Gem::RequestSet::Lockfile.new self, path
- lockfile.parse
+ lock_file = "#{File.expand_path(path)}.lock"
+ begin
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file lock_file
+ parser = tokenizer.make_parser self, []
+ parser.parse
+ rescue Errno::ENOENT
+ end
gf = Gem::RequestSet::GemDependencyAPI.new self, path
gf.installing = installing
@@ -411,3 +416,4 @@ end
require 'rubygems/request_set/gem_dependency_api'
require 'rubygems/request_set/lockfile'
+require 'rubygems/request_set/lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index 4f2fa09..2c788fb 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -1,12 +1,9 @@
-require 'strscan'
-
##
# Parses a gem.deps.rb.lock file and constructs a LockSet containing the
# dependencies found inside. If the lock file is missing no LockSet is
# constructed.
class Gem::RequestSet::Lockfile
-
##
# Raised when a lockfile cannot be parsed
@@ -37,7 +34,6 @@ class Gem::RequestSet::Lockfile
@path = path
super "#{message} (at line #{line} column #{column})"
end
-
end
##
@@ -57,11 +53,7 @@ class Gem::RequestSet::Lockfile
@gem_deps_file.untaint unless gem_deps_file.tainted?
- @current_token = nil
- @line = 0
- @line_pos = 0
@platforms = []
- @tokens = []
end
def add_DEPENDENCIES out # :nodoc:
@@ -80,7 +72,7 @@ class Gem::RequestSet::Lockfile
[name, requirement_string]
end
else
- @requests.sort_by { |r| r.name }.map do |request|
+ requests.sort_by { |r| r.name }.map do |request|
spec = request.spec
name = request.name
requirement = request.request.dependency.requirement
@@ -106,10 +98,10 @@ class Gem::RequestSet::Lockfile
out << nil
end
- def add_GEM out # :nodoc:
- return if @spec_groups.empty?
+ def add_GEM out, spec_groups # :nodoc:
+ return if spec_groups.empty?
- source_groups = @spec_groups.values.flatten.group_by do |request|
+ source_groups = spec_groups.values.flatten.group_by do |request|
request.spec.source.uri
end
@@ -136,9 +128,8 @@ class Gem::RequestSet::Lockfile
end
end
- def add_GIT out
- return unless git_requests =
- @spec_groups.delete(Gem::Resolver::GitSpecification)
+ def add_GIT out, git_requests
+ return if git_requests.empty?
by_repository_revision = git_requests.group_by do |request|
source = request.spec.source
@@ -179,9 +170,8 @@ class Gem::RequestSet::Lockfile
end
end
- def add_PATH out # :nodoc:
- return unless path_requests =
- @spec_groups.delete(Gem::Resolver::VendorSpecification)
+ def add_PATH out, path_requests # :nodoc:
+ return if path_requests.empty?
out << "PATH"
path_requests.each do |request|
@@ -198,7 +188,7 @@ class Gem::RequestSet::Lockfile
def add_PLATFORMS out # :nodoc:
out << "PLATFORMS"
- platforms = @requests.map { |request| request.spec.platform }.uniq
+ platforms = requests.map { |request| request.spec.platform }.uniq
platforms = platforms.sort_by { |platform| platform.to_s }
@@ -209,319 +199,8 @@ class Gem::RequestSet::Lockfile
out << nil
end
- ##
- # Gets the next token for a Lockfile
-
- def get expected_types = nil, expected_value = nil # :nodoc:
- @current_token = @tokens.shift
-
- type, value, column, line = @current_token
-
- if expected_types and not Array(expected_types).include? type then
- unget
-
- message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
- "expected #{expected_types.inspect}"
-
- raise ParseError.new message, column, line, "#{@gem_deps_file}.lock"
- end
-
- if expected_value and expected_value != value then
- unget
-
- message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
- "expected [#{expected_types.inspect}, " +
- "#{expected_value.inspect}]"
-
- raise ParseError.new message, column, line, "#{@gem_deps_file}.lock"
- end
-
- @current_token
- end
-
- def parse # :nodoc:
- tokenize
-
- until @tokens.empty? do
- type, data, column, line = get
-
- case type
- when :section then
- skip :newline
-
- case data
- when 'DEPENDENCIES' then
- parse_DEPENDENCIES
- when 'GIT' then
- parse_GIT
- when 'GEM' then
- parse_GEM
- when 'PATH' then
- parse_PATH
- when 'PLATFORMS' then
- parse_PLATFORMS
- else
- type, = get until @tokens.empty? or peek.first == :section
- end
- else
- raise "BUG: unhandled token #{type} (#{data.inspect}) at line #{line} column #{column}"
- end
- end
- end
-
- def parse_DEPENDENCIES # :nodoc:
- while not @tokens.empty? and :text == peek.first do
- _, name, = get :text
-
- requirements = []
-
- case peek[0]
- when :bang then
- get :bang
-
- requirements << pinned_requirement(name)
- when :l_paren then
- get :l_paren
-
- loop do
- _, op, = get :requirement
- _, version, = get :text
-
- requirements << "#{op} #{version}"
-
- break unless peek[0] == :comma
-
- get :comma
- end
-
- get :r_paren
-
- if peek[0] == :bang then
- requirements.clear
- requirements << pinned_requirement(name)
-
- get :bang
- end
- end
-
- @set.gem name, *requirements
-
- skip :newline
- end
- end
-
- def parse_GEM # :nodoc:
- sources = []
-
- while [:entry, 'remote'] == peek.first(2) do
- get :entry, 'remote'
- _, data, = get :text
- skip :newline
-
- sources << Gem::Source.new(data)
- end
-
- sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty?
-
- get :entry, 'specs'
-
- skip :newline
-
- set = Gem::Resolver::LockSet.new sources
- last_specs = nil
-
- while not @tokens.empty? and :text == peek.first do
- _, name, column, = get :text
-
- case peek[0]
- when :newline then
- last_specs.each do |spec|
- spec.add_dependency Gem::Dependency.new name if column == 6
- end
- when :l_paren then
- get :l_paren
-
- type, data, = get [:text, :requirement]
-
- if type == :text and column == 4 then
- version, platform = data.split '-', 2
-
- platform =
- platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
-
- last_specs = set.add name, version, platform
- else
- dependency = parse_dependency name, data
-
- last_specs.each do |spec|
- spec.add_dependency dependency
- end
- end
-
- get :r_paren
- else
- raise "BUG: unknown token #{peek}"
- end
-
- skip :newline
- end
-
- @set.sets << set
- end
-
- def parse_GIT # :nodoc:
- get :entry, 'remote'
- _, repository, = get :text
-
- skip :newline
-
- get :entry, 'revision'
- _, revision, = get :text
-
- skip :newline
-
- type, value = peek.first 2
- if type == :entry and %w[branch ref tag].include? value then
- get
- get :text
-
- skip :newline
- end
-
- get :entry, 'specs'
-
- skip :newline
-
- set = Gem::Resolver::GitSet.new
- set.root_dir = @set.install_dir
-
- last_spec = nil
-
- while not @tokens.empty? and :text == peek.first do
- _, name, column, = get :text
-
- case peek[0]
- when :newline then
- last_spec.add_dependency Gem::Dependency.new name if column == 6
- when :l_paren then
- get :l_paren
-
- type, data, = get [:text, :requirement]
-
- if type == :text and column == 4 then
- last_spec = set.add_git_spec name, data, repository, revision, true
- else
- dependency = parse_dependency name, data
-
- last_spec.add_dependency dependency
- end
-
- get :r_paren
- else
- raise "BUG: unknown token #{peek}"
- end
-
- skip :newline
- end
-
- @set.sets << set
- end
-
- def parse_PATH # :nodoc:
- get :entry, 'remote'
- _, directory, = get :text
-
- skip :newline
-
- get :entry, 'specs'
-
- skip :newline
-
- set = Gem::Resolver::VendorSet.new
- last_spec = nil
-
- while not @tokens.empty? and :text == peek.first do
- _, name, column, = get :text
-
- case peek[0]
- when :newline then
- last_spec.add_dependency Gem::Dependency.new name if column == 6
- when :l_paren then
- get :l_paren
-
- type, data, = get [:text, :requirement]
-
- if type == :text and column == 4 then
- last_spec = set.add_vendor_gem name, directory
- else
- dependency = parse_dependency name, data
-
- last_spec.dependencies << dependency
- end
-
- get :r_paren
- else
- raise "BUG: unknown token #{peek}"
- end
-
- skip :newline
- end
-
- @set.sets << set
- end
-
- def parse_PLATFORMS # :nodoc:
- while not @tokens.empty? and :text == peek.first do
- _, name, = get :text
-
- @platforms << name
-
- skip :newline
- end
- end
-
- ##
- # Parses the requirements following the dependency +name+ and the +op+ for
- # the first token of the requirements and returns a Gem::Dependency object.
-
- def parse_dependency name, op # :nodoc:
- return Gem::Dependency.new name, op unless peek[0] == :text
-
- _, version, = get :text
-
- requirements = ["#{op} #{version}"]
-
- while peek[0] == :comma do
- get :comma
- _, op, = get :requirement
- _, version, = get :text
-
- requirements << "#{op} #{version}"
- end
-
- Gem::Dependency.new name, requirements
- end
-
- ##
- # Peeks at the next token for Lockfile
-
- def peek # :nodoc:
- @tokens.first || [:EOF]
- end
-
- def pinned_requirement name # :nodoc:
- spec = @set.sets.select { |set|
- Gem::Resolver::GitSet === set or
- Gem::Resolver::VendorSet === set
- }.map { |set|
- set.specs[name]
- }.compact.first
-
- spec.version
- end
-
- def skip type # :nodoc:
- get while not @tokens.empty? and peek.first == type
+ def spec_groups
+ requests.group_by { |request| request.spec.class }
end
##
@@ -532,17 +211,13 @@ class Gem::RequestSet::Lockfile
out = []
- @requests = @set.sorted_requests
-
- @spec_groups = @requests.group_by do |request|
- request.spec.class
- end
+ groups = spec_groups
- add_PATH out
+ add_PATH out, groups.delete(Gem::Resolver::VendorSpecification) { [] }
- add_GIT out
+ add_GIT out, groups.delete(Gem::Resolver::GitSpecification) { [] }
- add_GEM out
+ add_GEM out, groups
add_PLATFORMS out
@@ -552,90 +227,6 @@ class Gem::RequestSet::Lockfile
end
##
- # Calculates the column (by byte) and the line of the current token based on
- # +byte_offset+.
-
- def token_pos byte_offset # :nodoc:
- [byte_offset - @line_pos, @line]
- end
-
- ##
- # Converts a lock file into an Array of tokens. If the lock file is missing
- # an empty Array is returned.
-
- def tokenize # :nodoc:
- @line = 0
- @line_pos = 0
-
- @platforms = []
- @tokens = []
- @current_token = nil
-
- lock_file = "#{@gem_deps_file}.lock"
-
- @input = File.read lock_file
- s = StringScanner.new @input
-
- until s.eos? do
- pos = s.pos
-
- pos = s.pos if leading_whitespace = s.scan(/ +/)
-
- if s.scan(/[<|=>]{7}/) then
- message = "your #{lock_file} contains merge conflict markers"
- column, line = token_pos pos
-
- raise ParseError.new message, column, line, lock_file
- end
-
- @tokens <<
- case
- when s.scan(/\r?\n/) then
- token = [:newline, nil, *token_pos(pos)]
- @line_pos = s.pos
- @line += 1
- token
- when s.scan(/[A-Z]+/) then
- if leading_whitespace then
- text = s.matched
- text += s.scan(/[^\s)]*/).to_s # in case of no match
- [:text, text, *token_pos(pos)]
- else
- [:section, s.matched, *token_pos(pos)]
- end
- when s.scan(/([a-z]+):\s/) then
- s.pos -= 1 # rewind for possible newline
- [:entry, s[1], *token_pos(pos)]
- when s.scan(/\(/) then
- [:l_paren, nil, *token_pos(pos)]
- when s.scan(/\)/) then
- [:r_paren, nil, *token_pos(pos)]
- when s.scan(/<=|>=|=|~>|<|>|!=/) then
- [:requirement, s.matched, *token_pos(pos)]
- when s.scan(/,/) then
- [:comma, nil, *token_pos(pos)]
- when s.scan(/!/) then
- [:bang, nil, *token_pos(pos)]
- when s.scan(/[^\s),!]*/) then
- [:text, s.matched, *token_pos(pos)]
- else
- raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}"
- end
- end
-
- @tokens
- rescue Errno::ENOENT
- @tokens
- end
-
- ##
- # Ungets the last token retrieved by #get
-
- def unget # :nodoc:
- @tokens.unshift @current_token
- end
-
- ##
# Writes the lock file alongside the gem dependencies file
def write
@@ -646,5 +237,11 @@ class Gem::RequestSet::Lockfile
end
end
+ private
+
+ def requests
+ @set.sorted_requests
+ end
end
+require 'rubygems/request_set/lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/lockfile/parser.rb b/lib/rubygems/request_set/lockfile/parser.rb
new file mode 100644
index 0000000..7778b7a
--- /dev/null
+++ b/lib/rubygems/request_set/lockfile/parser.rb
@@ -0,0 +1,334 @@
+class Gem::RequestSet::Lockfile::Parser
+ ###
+ # Parses lockfiles
+
+ def initialize tokenizer, set, platforms, filename = nil
+ @tokens = tokenizer
+ @filename = filename
+ @set = set
+ @platforms = platforms
+ end
+
+ def parse
+ until @tokens.empty? do
+ type, data, column, line = get
+
+ case type
+ when :section then
+ @tokens.skip :newline
+
+ case data
+ when 'DEPENDENCIES' then
+ parse_DEPENDENCIES
+ when 'GIT' then
+ parse_GIT
+ when 'GEM' then
+ parse_GEM
+ when 'PATH' then
+ parse_PATH
+ when 'PLATFORMS' then
+ parse_PLATFORMS
+ else
+ type, = get until @tokens.empty? or peek.first == :section
+ end
+ else
+ raise "BUG: unhandled token #{type} (#{data.inspect}) at line #{line} column #{column}"
+ end
+ end
+ end
+
+ ##
+ # Gets the next token for a Lockfile
+
+ def get expected_types = nil, expected_value = nil # :nodoc:
+ current_token = @tokens.shift
+
+ type, value, column, line = current_token
+
+ if expected_types and not Array(expected_types).include? type then
+ unget current_token
+
+ message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
+ "expected #{expected_types.inspect}"
+
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
+ end
+
+ if expected_value and expected_value != value then
+ unget current_token
+
+ message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
+ "expected [#{expected_types.inspect}, " +
+ "#{expected_value.inspect}]"
+
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
+ end
+
+ current_token
+ end
+
+ def parse_DEPENDENCIES # :nodoc:
+ while not @tokens.empty? and :text == peek.first do
+ _, name, = get :text
+
+ requirements = []
+
+ case peek[0]
+ when :bang then
+ get :bang
+
+ requirements << pinned_requirement(name)
+ when :l_paren then
+ get :l_paren
+
+ loop do
+ _, op, = get :requirement
+ _, version, = get :text
+
+ requirements << "#{op} #{version}"
+
+ break unless peek[0] == :comma
+
+ get :comma
+ end
+
+ get :r_paren
+
+ if peek[0] == :bang then
+ requirements.clear
+ requirements << pinned_requirement(name)
+
+ get :bang
+ end
+ end
+
+ @set.gem name, *requirements
+
+ skip :newline
+ end
+ end
+
+ def parse_GEM # :nodoc:
+ sources = []
+
+ while [:entry, 'remote'] == peek.first(2) do
+ get :entry, 'remote'
+ _, data, = get :text
+ skip :newline
+
+ sources << Gem::Source.new(data)
+ end
+
+ sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty?
+
+ get :entry, 'specs'
+
+ skip :newline
+
+ set = Gem::Resolver::LockSet.new sources
+ last_specs = nil
+
+ while not @tokens.empty? and :text == peek.first do
+ _, name, column, = get :text
+
+ case peek[0]
+ when :newline then
+ last_specs.each do |spec|
+ spec.add_dependency Gem::Dependency.new name if column == 6
+ end
+ when :l_paren then
+ get :l_paren
+
+ type, data, = get [:text, :requirement]
+
+ if type == :text and column == 4 then
+ version, platform = data.split '-', 2
+
+ platform =
+ platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
+
+ last_specs = set.add name, version, platform
+ else
+ dependency = parse_dependency name, data
+
+ last_specs.each do |spec|
+ spec.add_dependency dependency
+ end
+ end
+
+ get :r_paren
+ else
+ raise "BUG: unknown token #{peek}"
+ end
+
+ skip :newline
+ end
+
+ @set.sets << set
+ end
+
+ def parse_GIT # :nodoc:
+ get :entry, 'remote'
+ _, repository, = get :text
+
+ skip :newline
+
+ get :entry, 'revision'
+ _, revision, = get :text
+
+ skip :newline
+
+ type, value = peek.first 2
+ if type == :entry and %w[branch ref tag].include? value then
+ get
+ get :text
+
+ skip :newline
+ end
+
+ get :entry, 'specs'
+
+ skip :newline
+
+ set = Gem::Resolver::GitSet.new
+ set.root_dir = @set.install_dir
+
+ last_spec = nil
+
+ while not @tokens.empty? and :text == peek.first do
+ _, name, column, = get :text
+
+ case peek[0]
+ when :newline then
+ last_spec.add_dependency Gem::Dependency.new name if column == 6
+ when :l_paren then
+ get :l_paren
+
+ type, data, = get [:text, :requirement]
+
+ if type == :text and column == 4 then
+ last_spec = set.add_git_spec name, data, repository, revision, true
+ else
+ dependency = parse_dependency name, data
+
+ last_spec.add_dependency dependency
+ end
+
+ get :r_paren
+ else
+ raise "BUG: unknown token #{peek}"
+ end
+
+ skip :newline
+ end
+
+ @set.sets << set
+ end
+
+ def parse_PATH # :nodoc:
+ get :entry, 'remote'
+ _, directory, = get :text
+
+ skip :newline
+
+ get :entry, 'specs'
+
+ skip :newline
+
+ set = Gem::Resolver::VendorSet.new
+ last_spec = nil
+
+ while not @tokens.empty? and :text == peek.first do
+ _, name, column, = get :text
+
+ case peek[0]
+ when :newline then
+ last_spec.add_dependency Gem::Dependency.new name if column == 6
+ when :l_paren then
+ get :l_paren
+
+ type, data, = get [:text, :requirement]
+
+ if type == :text and column == 4 then
+ last_spec = set.add_vendor_gem name, directory
+ else
+ dependency = parse_dependency name, data
+
+ last_spec.dependencies << dependency
+ end
+
+ get :r_paren
+ else
+ raise "BUG: unknown token #{peek}"
+ end
+
+ skip :newline
+ end
+
+ @set.sets << set
+ end
+
+ def parse_PLATFORMS # :nodoc:
+ while not @tokens.empty? and :text == peek.first do
+ _, name, = get :text
+
+ @platforms << name
+
+ skip :newline
+ end
+ end
+
+ ##
+ # Parses the requirements following the dependency +name+ and the +op+ for
+ # the first token of the requirements and returns a Gem::Dependency object.
+
+ def parse_dependency name, op # :nodoc:
+ return Gem::Dependency.new name, op unless peek[0] == :text
+
+ _, version, = get :text
+
+ requirements = ["#{op} #{version}"]
+
+ while peek[0] == :comma do
+ get :comma
+ _, op, = get :requirement
+ _, version, = get :text
+
+ requirements << "#{op} #{version}"
+ end
+
+ Gem::Dependency.new name, requirements
+ end
+
+ private
+
+ def skip type # :nodoc:
+ @tokens.skip type
+ end
+
+ ##
+ # Peeks at the next token for Lockfile
+
+ def peek # :nodoc:
+ @tokens.peek
+ end
+
+ def pinned_requirement name # :nodoc:
+ spec = @set.sets.select { |set|
+ Gem::Resolver::GitSet === set or
+ Gem::Resolver::VendorSet === set
+ }.map { |set|
+ set.specs[name]
+ }.compact.first
+
+ spec.version
+ end
+
+ ##
+ # Ungets the last token retrieved by #get
+
+ def unget token # :nodoc:
+ @tokens.unshift token
+ end
+end
+
diff --git a/lib/rubygems/request_set/lockfile/tokenizer.rb b/lib/rubygems/request_set/lockfile/tokenizer.rb
new file mode 100644
index 0000000..73c9a83
--- /dev/null
+++ b/lib/rubygems/request_set/lockfile/tokenizer.rb
@@ -0,0 +1,108 @@
+require 'strscan'
+require 'rubygems/request_set/lockfile/parser'
+
+class Gem::RequestSet::Lockfile::Tokenizer
+ def self.from_file file
+ new File.read(file), file
+ end
+
+ def initialize input, filename = nil, line = 0, pos = 0
+ @line = line
+ @line_pos = pos
+ @tokens = []
+ @filename = filename
+ tokenize input
+ end
+
+ def make_parser set, platforms
+ Gem::RequestSet::Lockfile::Parser.new self, set, platforms, @filename
+ end
+
+ def to_a
+ @tokens
+ end
+
+ def skip type
+ @tokens.shift while not @tokens.empty? and peek.first == type
+ end
+
+ ##
+ # Calculates the column (by byte) and the line of the current token based on
+ # +byte_offset+.
+
+ def token_pos byte_offset # :nodoc:
+ [byte_offset - @line_pos, @line]
+ end
+
+ def empty?
+ @tokens.empty?
+ end
+
+ def unshift token
+ @tokens.unshift token
+ end
+
+ def next_token
+ @tokens.shift
+ end
+ alias :shift :next_token
+
+ def peek
+ @tokens.first || [:EOF]
+ end
+
+ private
+
+ def tokenize input
+ s = StringScanner.new input
+
+ until s.eos? do
+ pos = s.pos
+
+ pos = s.pos if leading_whitespace = s.scan(/ +/)
+
+ if s.scan(/[<|=>]{7}/) then
+ message = "your #{@filename} contains merge conflict markers"
+ column, line = token_pos pos
+
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
+ end
+
+ @tokens <<
+ case
+ when s.scan(/\r?\n/) then
+ token = [:newline, nil, *token_pos(pos)]
+ @line_pos = s.pos
+ @line += 1
+ token
+ when s.scan(/[A-Z]+/) then
+ if leading_whitespace then
+ text = s.matched
+ text += s.scan(/[^\s)]*/).to_s # in case of no match
+ [:text, text, *token_pos(pos)]
+ else
+ [:section, s.matched, *token_pos(pos)]
+ end
+ when s.scan(/([a-z]+):\s/) then
+ s.pos -= 1 # rewind for possible newline
+ [:entry, s[1], *token_pos(pos)]
+ when s.scan(/\(/) then
+ [:l_paren, nil, *token_pos(pos)]
+ when s.scan(/\)/) then
+ [:r_paren, nil, *token_pos(pos)]
+ when s.scan(/<=|>=|=|~>|<|>|!=/) then
+ [:requirement, s.matched, *token_pos(pos)]
+ when s.scan(/,/) then
+ [:comma, nil, *token_pos(pos)]
+ when s.scan(/!/) then
+ [:bang, nil, *token_pos(pos)]
+ when s.scan(/[^\s),!]*/) then
+ [:text, s.matched, *token_pos(pos)]
+ else
+ raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}"
+ end
+ end
+
+ @tokens
+ end
+end
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 8b6a816..bcf5fb9 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -171,7 +171,7 @@ class Gem::Requirement
end
def hash # :nodoc:
- requirements.hash
+ requirements.sort.hash
end
def marshal_dump # :nodoc:
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 631bb7a..eb89c4c 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -1028,8 +1028,8 @@ class Gem::Specification < Gem::BasicSpecification
file = file.dup.untaint
return unless File.file?(file)
- spec = LOAD_CACHE[file]
- return spec if spec
+ _spec = LOAD_CACHE[file]
+ return _spec if _spec
code = if defined? Encoding
File.read file, :mode => 'r:UTF-8:-'
@@ -1040,15 +1040,15 @@ class Gem::Specification < Gem::BasicSpecification
code.untaint
begin
- spec = eval code, binding, file
+ _spec = eval code, binding, file
- if Gem::Specification === spec
- spec.loaded_from = File.expand_path file.to_s
- LOAD_CACHE[file] = spec
- return spec
+ if Gem::Specification === _spec
+ _spec.loaded_from = File.expand_path file.to_s
+ LOAD_CACHE[file] = _spec
+ return _spec
end
- warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
+ warn "[#{file}] isn't a Gem::Specification (#{_spec.class} instead)."
rescue SignalException, SystemExit
raise
rescue SyntaxError, Exception => e
@@ -1350,7 +1350,7 @@ class Gem::Specification < Gem::BasicSpecification
end
unless dependency.respond_to?(:name) &&
- dependency.respond_to?(:version_requirements)
+ dependency.respond_to?(:requirement)
dependency = Gem::Dependency.new(dependency.to_s, requirements, type)
end
diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb
index 5dc7a1b..cb2e2b8 100644
--- a/lib/rubygems/test_case.rb
+++ b/lib/rubygems/test_case.rb
@@ -1427,4 +1427,6 @@ Also, a list:
end
require 'rubygems/test_utilities'
-
+ENV['GEM_HOME'] = Dir.mktmpdir "home"
+ENV['GEM_PATH'] = Dir.mktmpdir "path"
+Gem.clear_paths
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 44ff2d3..78d3790 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -396,10 +396,6 @@ class Gem::StreamUI
# Return a progress reporter object chosen from the current verbosity.
def progress_reporter(*args)
- if self.kind_of?(Gem::SilentUI)
- return SilentProgressReporter.new(@outs, *args)
- end
-
case Gem.configuration.verbose
when nil, false
SilentProgressReporter.new(@outs, *args)
@@ -533,10 +529,6 @@ class Gem::StreamUI
# Return a download reporter object chosen from the current verbosity
def download_reporter(*args)
- if self.kind_of?(Gem::SilentUI)
- return SilentDownloadReporter.new(@outs, *args)
- end
-
case Gem.configuration.verbose
when nil, false
SilentDownloadReporter.new(@outs, *args)
diff --git a/test/rubygems/test_gem_commands_open_command.rb b/test/rubygems/test_gem_commands_open_command.rb
index 25f22c8..c1c76f9 100644
--- a/test/rubygems/test_gem_commands_open_command.rb
+++ b/test/rubygems/test_gem_commands_open_command.rb
@@ -15,18 +15,24 @@ class TestGemCommandsOpenCommand < Gem::TestCase
end
write_file File.join(*%W[gems #{spec.full_name} lib #{name}.rb])
write_file File.join(*%W[gems #{spec.full_name} Rakefile])
+ spec
end
def test_execute
@cmd.options[:args] = %w[foo]
@cmd.options[:editor] = "#{Gem.ruby} -e0 --"
- gem 'foo'
+ spec = gem 'foo'
+ mock = MiniTest::Mock.new
+ mock.expect(:call, true, [spec.full_gem_path])
- use_ui @ui do
- @cmd.execute
+ Dir.stub(:chdir, mock) do
+ use_ui @ui do
+ @cmd.execute
+ end
end
+ assert mock.verify
assert_equal "", @ui.error
end
diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
index 65b30f8..32c03ba 100644
--- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb
+++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
@@ -50,6 +50,25 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
Gem.instance_variables.include? :@ruby_version
end
+ def test_gempspec_with_multiple_runtime_deps
+ gda = Class.new(@GDA) do
+ # implement find_gemspec so we don't need one on the FS
+ def find_gemspec name, path
+ Gem::Specification.new do |s|
+ s.name = 'foo'
+ s.version = '1.0'
+ s.add_runtime_dependency 'bar', '>= 1.6.0', '< 1.6.4'
+ end
+ end
+ end
+ instance = gda.new @set, __FILE__
+ instance.gemspec
+ assert_equal %w{ foo bar }.sort, @set.dependencies.map(&:name).sort
+ bar = @set.dependencies.find { |d| d.name == 'bar' }
+ assert_equal [[">=", Gem::Version.create('1.6.0')],
+ ["<", Gem::Version.create('1.6.4')]], bar.requirement.requirements
+ end
+
def test_gemspec_without_group
@gda.send :add_dependencies, [:development], [dep('a', '= 1')]
diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb
index 7c5cd5a..f825a8b 100644
--- a/test/rubygems/test_gem_request_set_lockfile.rb
+++ b/test/rubygems/test_gem_request_set_lockfile.rb
@@ -24,12 +24,6 @@ class TestGemRequestSetLockfile < Gem::TestCase
@lockfile = Gem::RequestSet::Lockfile.new @set, @gem_deps_file
end
- def write_gem_deps gem_deps
- open @gem_deps_file, 'w' do |io|
- io.write gem_deps
- end
- end
-
def write_lockfile lockfile
@lock_file = File.expand_path "#{@gem_deps_file}.lock"
@@ -47,7 +41,6 @@ class TestGemRequestSetLockfile < Gem::TestCase
@set.gem 'a'
@set.resolve
- @lockfile.instance_variable_set :@requests, @set.sorted_requests
out = []
@@ -75,7 +68,6 @@ class TestGemRequestSetLockfile < Gem::TestCase
@set.resolve
@lockfile =
Gem::RequestSet::Lockfile.new @set, @gem_deps_file, dependencies
- @lockfile.instance_variable_set :@requests, @set.sorted_requests
out = []
@@ -105,17 +97,10 @@ class TestGemRequestSetLockfile < Gem::TestCase
@set.gem 'a'
@set.gem 'bundler'
@set.resolve
- @lockfile.instance_variable_set :@requests, @set.sorted_requests
-
- spec_groups = @set.sorted_requests.group_by do |request|
- request.spec.class
- end
- @lockfile.instance_variable_set :@spec_groups, spec_groups
-
out = []
- @lockfile.add_GEM out
+ @lockfile.add_GEM out, @lockfile.spec_groups
expected = [
'GEM',
@@ -143,7 +128,6 @@ class TestGemRequestSetLockfile < Gem::TestCase
@set.gem 'a'
@set.resolve
- @lockfile.instance_variable_set :@requests, @set.sorted_requests
out = []
@@ -159,518 +143,6 @@ class TestGemRequestSetLockfile < Gem::TestCase
assert_equal expected, out
end
- def test_get
- @lockfile.instance_variable_set :@tokens, [:token]
-
- assert_equal :token, @lockfile.get
- end
-
- def test_get_type_mismatch
- @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.get :text
- end
-
- expected =
- 'unexpected token [:section, "x"], expected :text (at line 1 column 5)'
-
- assert_equal expected, e.message
-
- assert_equal 1, e.line
- assert_equal 5, e.column
- assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
- end
-
- def test_get_type_multiple
- @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
-
- assert @lockfile.get [:text, :section]
- end
-
- def test_get_type_value_mismatch
- @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]]
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.get :section, 'y'
- end
-
- expected =
- 'unexpected token [:section, "x"], expected [:section, "y"] (at line 1 column 5)'
-
- assert_equal expected, e.message
-
- assert_equal 1, e.line
- assert_equal 5, e.column
- assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
- end
-
- def test_parse
- write_lockfile <<-LOCKFILE.strip
-GEM
- remote: #{@gem_repo}
- specs:
- a (2)
-
-PLATFORMS
- #{Gem::Platform::RUBY}
-
-DEPENDENCIES
- a
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a')], @set.dependencies
-
- assert_equal [Gem::Platform::RUBY], @lockfile.platforms
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- assert lockfile_set, 'could not find a LockSet'
-
- assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
- end
-
- def test_parse_dependencies
- write_lockfile <<-LOCKFILE
-GEM
- remote: #{@gem_repo}
- specs:
- a (2)
-
-PLATFORMS
- #{Gem::Platform::RUBY}
-
-DEPENDENCIES
- a (>= 1, <= 2)
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '>= 1', '<= 2')], @set.dependencies
-
- assert_equal [Gem::Platform::RUBY], @lockfile.platforms
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- assert lockfile_set, 'could not find a LockSet'
-
- assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
- end
-
- def test_parse_DEPENDENCIES_git
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://git.example/josevalim/rails-footnotes.git
- revision: 3a6ac1971e91d822f057650cc5916ebfcbd6ee37
- specs:
- rails-footnotes (3.7.9)
- rails (>= 3.0.0)
-
-GIT
- remote: git://git.example/svenfuchs/i18n-active_record.git
- revision: 55507cf59f8f2173d38e07e18df0e90d25b1f0f6
- specs:
- i18n-active_record (0.0.2)
- i18n (>= 0.5.0)
-
-GEM
- remote: http://gems.example/
- specs:
- i18n (0.6.9)
- rails (4.0.0)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- i18n-active_record!
- rails-footnotes!
- LOCKFILE
-
- @lockfile.parse
-
- expected = [
- dep('i18n-active_record', '= 0.0.2'),
- dep('rails-footnotes', '= 3.7.9'),
- ]
-
- assert_equal expected, @set.dependencies
- end
-
- def test_parse_DEPENDENCIES_git_version
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://github.com/progrium/ruby-jwt.git
- revision: 8d74770c6cd92ea234b428b5d0c1f18306a4f41c
- specs:
- jwt (1.1)
-
-GEM
- remote: http://gems.example/
- specs:
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- jwt (= 1.1)!
- LOCKFILE
-
- @lockfile.parse
-
- expected = [
- dep('jwt', '= 1.1'),
- ]
-
- assert_equal expected, @set.dependencies
- end
-
- def test_parse_GEM
- write_lockfile <<-LOCKFILE
-GEM
- specs:
- a (2)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- a
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '>= 0')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- assert lockfile_set, 'found a LockSet'
-
- assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name }
- end
-
- def test_parse_GEM_remote_multiple
- write_lockfile <<-LOCKFILE
-GEM
- remote: https://gems.example/
- remote: https://other.example/
- specs:
- a (2)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- a
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '>= 0')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- assert lockfile_set, 'found a LockSet'
-
- assert_equal %w[a-2 a-2], lockfile_set.specs.map { |s| s.full_name }
-
- assert_equal %w[https://gems.example/ https://other.example/],
- lockfile_set.specs.map { |s| s.source.uri.to_s }
- end
-
- def test_parse_GIT
- @set.instance_variable_set :@install_dir, 'install_dir'
-
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://example/a.git
- revision: master
- specs:
- a (2)
- b (>= 3)
- c
-
-DEPENDENCIES
- a!
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '= 2')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set, 'fount a LockSet'
-
- git_set = @set.sets.find do |set|
- Gem::Resolver::GitSet === set
- end
-
- assert git_set, 'could not find a GitSet'
-
- assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name }
-
- assert_equal [dep('b', '>= 3'), dep('c')],
- git_set.specs.values.first.dependencies
-
- expected = {
- 'a' => %w[git://example/a.git master],
- }
-
- assert_equal expected, git_set.repositories
- assert_equal 'install_dir', git_set.root_dir
- end
-
- def test_parse_GIT_branch
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://example/a.git
- revision: 1234abc
- branch: 0-9-12-stable
- specs:
- a (2)
- b (>= 3)
-
-DEPENDENCIES
- a!
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '= 2')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set, 'fount a LockSet'
-
- git_set = @set.sets.find do |set|
- Gem::Resolver::GitSet === set
- end
-
- assert git_set, 'could not find a GitSet'
-
- expected = {
- 'a' => %w[git://example/a.git 1234abc],
- }
-
- assert_equal expected, git_set.repositories
- end
-
- def test_parse_GIT_ref
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://example/a.git
- revision: 1234abc
- ref: 1234abc
- specs:
- a (2)
- b (>= 3)
-
-DEPENDENCIES
- a!
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '= 2')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set, 'fount a LockSet'
-
- git_set = @set.sets.find do |set|
- Gem::Resolver::GitSet === set
- end
-
- assert git_set, 'could not find a GitSet'
-
- expected = {
- 'a' => %w[git://example/a.git 1234abc],
- }
-
- assert_equal expected, git_set.repositories
- end
-
- def test_parse_GIT_tag
- write_lockfile <<-LOCKFILE
-GIT
- remote: git://example/a.git
- revision: 1234abc
- tag: v0.9.12
- specs:
- a (2)
- b (>= 3)
-
-DEPENDENCIES
- a!
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '= 2')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set, 'fount a LockSet'
-
- git_set = @set.sets.find do |set|
- Gem::Resolver::GitSet === set
- end
-
- assert git_set, 'could not find a GitSet'
-
- expected = {
- 'a' => %w[git://example/a.git 1234abc],
- }
-
- assert_equal expected, git_set.repositories
- end
-
- def test_parse_PATH
- _, _, directory = vendor_gem
-
- write_lockfile <<-LOCKFILE
-PATH
- remote: #{directory}
- specs:
- a (1)
- b (2)
-
-DEPENDENCIES
- a!
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a', '= 1')], @set.dependencies
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set, 'found a LockSet'
-
- vendor_set = @set.sets.find do |set|
- Gem::Resolver::VendorSet === set
- end
-
- assert vendor_set, 'could not find a VendorSet'
-
- assert_equal %w[a-1], vendor_set.specs.values.map { |s| s.full_name }
-
- spec = vendor_set.load_spec 'a', nil, nil, nil
-
- assert_equal [dep('b', '= 2')], spec.dependencies
- end
-
- def test_parse_dependency
- write_lockfile ' 1)'
-
- @lockfile.tokenize
-
- parsed = @lockfile.parse_dependency 'a', '='
-
- assert_equal dep('a', '= 1'), parsed
-
- write_lockfile ')'
-
- @lockfile.tokenize
-
- parsed = @lockfile.parse_dependency 'a', '2'
-
- assert_equal dep('a', '= 2'), parsed
- end
-
- def test_parse_gem_specs_dependency
- write_lockfile <<-LOCKFILE
-GEM
- remote: #{@gem_repo}
- specs:
- a (2)
- b (= 3)
- c (~> 4)
- d
- e (~> 5.0, >= 5.0.1)
- b (3-x86_64-linux)
-
-PLATFORMS
- #{Gem::Platform::RUBY}
-
-DEPENDENCIES
- a
- LOCKFILE
-
- @lockfile.parse
-
- assert_equal [dep('a')], @set.dependencies
-
- assert_equal [Gem::Platform::RUBY], @lockfile.platforms
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- assert lockfile_set, 'could not find a LockSet'
-
- assert_equal %w[a-2 b-3], lockfile_set.specs.map { |tuple| tuple.full_name }
-
- expected = [
- Gem::Platform::RUBY,
- Gem::Platform.new('x86_64-linux'),
- ]
-
- assert_equal expected, lockfile_set.specs.map { |tuple| tuple.platform }
-
- spec = lockfile_set.specs.first
-
- expected = [
- dep('b', '= 3'),
- dep('c', '~> 4'),
- dep('d'),
- dep('e', '~> 5.0', '>= 5.0.1'),
- ]
-
- assert_equal expected, spec.dependencies
- end
-
- def test_parse_missing
- @lockfile.parse
-
- lockfile_set = @set.sets.find do |set|
- Gem::Resolver::LockSet === set
- end
-
- refute lockfile_set
- end
-
- def test_peek
- @lockfile.instance_variable_set :@tokens, [:token]
-
- assert_equal :token, @lockfile.peek
-
- assert_equal :token, @lockfile.get
-
- assert_equal [:EOF], @lockfile.peek
- end
-
def test_relative_path_from
path = @lockfile.relative_path_from '/foo', '/foo/bar'
@@ -681,276 +153,6 @@ DEPENDENCIES
assert_equal '.', path
end
- def test_skip
- tokens = [[:token]]
-
- @lockfile.instance_variable_set :@tokens, tokens
-
- @lockfile.skip :token
-
- assert_empty tokens
- end
-
- def test_token_pos
- assert_equal [5, 0], @lockfile.token_pos(5)
-
- @lockfile.instance_variable_set :@line_pos, 2
- @lockfile.instance_variable_set :@line, 1
-
- assert_equal [3, 1], @lockfile.token_pos(5)
- end
-
- def test_tokenize
- write_lockfile <<-LOCKFILE
-GEM
- remote: #{@gem_repo}
- specs:
- a (2)
- b (= 2)
- c (!= 3)
- d (> 4)
- e (< 5)
- f (>= 6)
- g (<= 7)
- h (~> 8)
-
-PLATFORMS
- #{Gem::Platform::RUBY}
-
-DEPENDENCIES
- a
- LOCKFILE
-
- expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
-
- [:entry, 'remote', 2, 1],
- [:text, @gem_repo, 10, 1],
- [:newline, nil, 34, 1],
-
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
-
- [:text, 'a', 4, 3],
- [:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
- [:r_paren, nil, 8, 3],
- [:newline, nil, 9, 3],
-
- [:text, 'b', 6, 4],
- [:l_paren, nil, 8, 4],
- [:requirement, '=', 9, 4],
- [:text, '2', 11, 4],
- [:r_paren, nil, 12, 4],
- [:newline, nil, 13, 4],
-
- [:text, 'c', 6, 5],
- [:l_paren, nil, 8, 5],
- [:requirement, '!=', 9, 5],
- [:text, '3', 12, 5],
- [:r_paren, nil, 13, 5],
- [:newline, nil, 14, 5],
-
- [:text, 'd', 6, 6],
- [:l_paren, nil, 8, 6],
- [:requirement, '>', 9, 6],
- [:text, '4', 11, 6],
- [:r_paren, nil, 12, 6],
- [:newline, nil, 13, 6],
-
- [:text, 'e', 6, 7],
- [:l_paren, nil, 8, 7],
- [:requirement, '<', 9, 7],
- [:text, '5', 11, 7],
- [:r_paren, nil, 12, 7],
- [:newline, nil, 13, 7],
-
- [:text, 'f', 6, 8],
- [:l_paren, nil, 8, 8],
- [:requirement, '>=', 9, 8],
- [:text, '6', 12, 8],
- [:r_paren, nil, 13, 8],
- [:newline, nil, 14, 8],
-
- [:text, 'g', 6, 9],
- [:l_paren, nil, 8, 9],
- [:requirement, '<=', 9, 9],
- [:text, '7', 12, 9],
- [:r_paren, nil, 13, 9],
- [:newline, nil, 14, 9],
-
- [:text, 'h', 6, 10],
- [:l_paren, nil, 8, 10],
- [:requirement, '~>', 9, 10],
- [:text, '8', 12, 10],
- [:r_paren, nil, 13, 10],
- [:newline, nil, 14, 10],
-
- [:newline, nil, 0, 11],
-
- [:section, 'PLATFORMS', 0, 12],
- [:newline, nil, 9, 12],
-
- [:text, Gem::Platform::RUBY, 2, 13],
- [:newline, nil, 6, 13],
-
- [:newline, nil, 0, 14],
-
- [:section, 'DEPENDENCIES', 0, 15],
- [:newline, nil, 12, 15],
-
- [:text, 'a', 2, 16],
- [:newline, nil, 3, 16],
- ]
-
- assert_equal expected, @lockfile.tokenize
- end
-
- def test_tokenize_capitals
- write_lockfile <<-LOCKFILE
-GEM
- remote: #{@gem_repo}
- specs:
- Ab (2)
-
-PLATFORMS
- #{Gem::Platform::RUBY}
-
-DEPENDENCIES
- Ab
- LOCKFILE
-
- expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
- [:entry, 'remote', 2, 1],
- [:text, @gem_repo, 10, 1],
- [:newline, nil, 34, 1],
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
- [:text, 'Ab', 4, 3],
- [:l_paren, nil, 7, 3],
- [:text, '2', 8, 3],
- [:r_paren, nil, 9, 3],
- [:newline, nil, 10, 3],
- [:newline, nil, 0, 4],
- [:section, 'PLATFORMS', 0, 5],
- [:newline, nil, 9, 5],
- [:text, Gem::Platform::RUBY, 2, 6],
- [:newline, nil, 6, 6],
- [:newline, nil, 0, 7],
- [:section, 'DEPENDENCIES', 0, 8],
- [:newline, nil, 12, 8],
- [:text, 'Ab', 2, 9],
- [:newline, nil, 4, 9],
- ]
-
- assert_equal expected, @lockfile.tokenize
- end
-
- def test_tokenize_conflict_markers
- write_lockfile '<<<<<<<'
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.tokenize
- end
-
- assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
- e.message
-
- write_lockfile '|||||||'
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.tokenize
- end
-
- assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
- e.message
-
- write_lockfile '======='
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.tokenize
- end
-
- assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
- e.message
-
- write_lockfile '>>>>>>>'
-
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
- @lockfile.tokenize
- end
-
- assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
- e.message
- end
-
- def test_tokenize_git
- write_lockfile <<-LOCKFILE
-DEPENDENCIES
- a!
- LOCKFILE
-
- expected = [
- [:section, 'DEPENDENCIES', 0, 0],
- [:newline, nil, 12, 0],
-
- [:text, 'a', 2, 1],
- [:bang, nil, 3, 1],
- [:newline, nil, 4, 1],
- ]
-
- assert_equal expected, @lockfile.tokenize
- end
-
- def test_tokenize_missing
- tokens = @lockfile.tokenize
-
- assert_empty tokens
- end
-
- def test_tokenize_multiple
- write_lockfile <<-LOCKFILE
-GEM
- remote: #{@gem_repo}
- specs:
- a (2)
- b (~> 3.0, >= 3.0.1)
- LOCKFILE
-
- expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
-
- [:entry, 'remote', 2, 1],
- [:text, @gem_repo, 10, 1],
- [:newline, nil, 34, 1],
-
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
-
- [:text, 'a', 4, 3],
- [:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
- [:r_paren, nil, 8, 3],
- [:newline, nil, 9, 3],
-
- [:text, 'b', 6, 4],
- [:l_paren, nil, 8, 4],
- [:requirement, '~>', 9, 4],
- [:text, '3.0', 12, 4],
- [:comma, nil, 15, 4],
- [:requirement, '>=', 17, 4],
- [:text, '3.0.1', 20, 4],
- [:r_paren, nil, 25, 4],
- [:newline, nil, 26, 4],
- ]
-
- assert_equal expected, @lockfile.tokenize
- end
-
def test_to_s_gem
spec_fetcher do |fetcher|
fetcher.spec 'a', 2
@@ -1236,14 +438,6 @@ DEPENDENCIES
assert_equal expected, @lockfile.to_s
end
- def test_unget
- @lockfile.instance_variable_set :@current_token, :token
-
- @lockfile.unget
-
- assert_equal :token, @lockfile.get
- end
-
def test_write
@lockfile.write
@@ -1271,6 +465,4 @@ DEPENDENCIES
assert_equal 'hello', File.read(gem_deps_lock_file)
end
-
end
-
diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb
new file mode 100644
index 0000000..c5b2b19
--- /dev/null
+++ b/test/rubygems/test_gem_request_set_lockfile_parser.rb
@@ -0,0 +1,543 @@
+require 'rubygems/test_case'
+require 'rubygems/request_set'
+require 'rubygems/request_set/lockfile'
+require 'rubygems/request_set/lockfile/tokenizer'
+require 'rubygems/request_set/lockfile/parser'
+
+class TestGemRequestSetLockfileParser < Gem::TestCase
+ def setup
+ super
+ @gem_deps_file = 'gem.deps.rb'
+ @lock_file = File.expand_path "#{@gem_deps_file}.lock"
+ @set = Gem::RequestSet.new
+ end
+
+ def test_get
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n"
+ parser = tokenizer.make_parser nil, nil
+
+ assert_equal :newline, parser.get.first
+ end
+
+ def test_get_type_mismatch
+ filename = File.expand_path("#{@gem_deps_file}.lock")
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "foo", filename, 1, 0
+ parser = tokenizer.make_parser nil, nil
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ parser.get :section
+ end
+
+ expected =
+ 'unexpected token [:text, "foo"], expected :section (at line 1 column 0)'
+
+ assert_equal expected, e.message
+
+ assert_equal 1, e.line
+ assert_equal 0, e.column
+ assert_equal filename, e.path
+ end
+
+ def test_get_type_multiple
+ filename = File.expand_path("#{@gem_deps_file}.lock")
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1
+ parser = tokenizer.make_parser nil, nil
+
+ assert parser.get [:text, :section]
+ end
+
+ def test_get_type_value_mismatch
+ filename = File.expand_path("#{@gem_deps_file}.lock")
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1
+ parser = tokenizer.make_parser nil, nil
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ parser.get :text, 'y'
+ end
+
+ expected =
+ 'unexpected token [:text, "x"], expected [:text, "y"] (at line 1 column 0)'
+
+ assert_equal expected, e.message
+
+ assert_equal 1, e.line
+ assert_equal 0, e.column
+ assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path
+ end
+
+
+ def test_parse
+ write_lockfile <<-LOCKFILE.strip
+GEM
+ remote: #{@gem_repo}
+ specs:
+ a (2)
+
+PLATFORMS
+ #{Gem::Platform::RUBY}
+
+DEPENDENCIES
+ a
+ LOCKFILE
+
+ platforms = []
+ parse_lockfile @set, platforms
+
+ assert_equal [dep('a')], @set.dependencies
+
+ assert_equal [Gem::Platform::RUBY], platforms
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ assert lockfile_set, 'could not find a LockSet'
+
+ assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
+ end
+
+ def test_parse_dependencies
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: #{@gem_repo}
+ specs:
+ a (2)
+
+PLATFORMS
+ #{Gem::Platform::RUBY}
+
+DEPENDENCIES
+ a (>= 1, <= 2)
+ LOCKFILE
+
+ platforms = []
+ parse_lockfile @set, platforms
+
+ assert_equal [dep('a', '>= 1', '<= 2')], @set.dependencies
+
+ assert_equal [Gem::Platform::RUBY], platforms
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ assert lockfile_set, 'could not find a LockSet'
+
+ assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
+ end
+
+ def test_parse_DEPENDENCIES_git
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://git.example/josevalim/rails-footnotes.git
+ revision: 3a6ac1971e91d822f057650cc5916ebfcbd6ee37
+ specs:
+ rails-footnotes (3.7.9)
+ rails (>= 3.0.0)
+
+GIT
+ remote: git://git.example/svenfuchs/i18n-active_record.git
+ revision: 55507cf59f8f2173d38e07e18df0e90d25b1f0f6
+ specs:
+ i18n-active_record (0.0.2)
+ i18n (>= 0.5.0)
+
+GEM
+ remote: http://gems.example/
+ specs:
+ i18n (0.6.9)
+ rails (4.0.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ i18n-active_record!
+ rails-footnotes!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ expected = [
+ dep('i18n-active_record', '= 0.0.2'),
+ dep('rails-footnotes', '= 3.7.9'),
+ ]
+
+ assert_equal expected, @set.dependencies
+ end
+
+ def test_parse_DEPENDENCIES_git_version
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://github.com/progrium/ruby-jwt.git
+ revision: 8d74770c6cd92ea234b428b5d0c1f18306a4f41c
+ specs:
+ jwt (1.1)
+
+GEM
+ remote: http://gems.example/
+ specs:
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ jwt (= 1.1)!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ expected = [
+ dep('jwt', '= 1.1'),
+ ]
+
+ assert_equal expected, @set.dependencies
+ end
+
+ def test_parse_GEM
+ write_lockfile <<-LOCKFILE
+GEM
+ specs:
+ a (2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ a
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '>= 0')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ assert lockfile_set, 'found a LockSet'
+
+ assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name }
+ end
+
+ def test_parse_GEM_remote_multiple
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: https://gems.example/
+ remote: https://other.example/
+ specs:
+ a (2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ a
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '>= 0')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ assert lockfile_set, 'found a LockSet'
+
+ assert_equal %w[a-2 a-2], lockfile_set.specs.map { |s| s.full_name }
+
+ assert_equal %w[https://gems.example/ https://other.example/],
+ lockfile_set.specs.map { |s| s.source.uri.to_s }
+ end
+
+ def test_parse_GIT
+ @set.instance_variable_set :@install_dir, 'install_dir'
+
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://example/a.git
+ revision: master
+ specs:
+ a (2)
+ b (>= 3)
+ c
+
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '= 2')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set, 'fount a LockSet'
+
+ git_set = @set.sets.find do |set|
+ Gem::Resolver::GitSet === set
+ end
+
+ assert git_set, 'could not find a GitSet'
+
+ assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name }
+
+ assert_equal [dep('b', '>= 3'), dep('c')],
+ git_set.specs.values.first.dependencies
+
+ expected = {
+ 'a' => %w[git://example/a.git master],
+ }
+
+ assert_equal expected, git_set.repositories
+ assert_equal 'install_dir', git_set.root_dir
+ end
+
+ def test_parse_GIT_branch
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://example/a.git
+ revision: 1234abc
+ branch: 0-9-12-stable
+ specs:
+ a (2)
+ b (>= 3)
+
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '= 2')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set, 'fount a LockSet'
+
+ git_set = @set.sets.find do |set|
+ Gem::Resolver::GitSet === set
+ end
+
+ assert git_set, 'could not find a GitSet'
+
+ expected = {
+ 'a' => %w[git://example/a.git 1234abc],
+ }
+
+ assert_equal expected, git_set.repositories
+ end
+
+ def test_parse_GIT_ref
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://example/a.git
+ revision: 1234abc
+ ref: 1234abc
+ specs:
+ a (2)
+ b (>= 3)
+
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '= 2')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set, 'fount a LockSet'
+
+ git_set = @set.sets.find do |set|
+ Gem::Resolver::GitSet === set
+ end
+
+ assert git_set, 'could not find a GitSet'
+
+ expected = {
+ 'a' => %w[git://example/a.git 1234abc],
+ }
+
+ assert_equal expected, git_set.repositories
+ end
+
+ def test_parse_GIT_tag
+ write_lockfile <<-LOCKFILE
+GIT
+ remote: git://example/a.git
+ revision: 1234abc
+ tag: v0.9.12
+ specs:
+ a (2)
+ b (>= 3)
+
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '= 2')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set, 'fount a LockSet'
+
+ git_set = @set.sets.find do |set|
+ Gem::Resolver::GitSet === set
+ end
+
+ assert git_set, 'could not find a GitSet'
+
+ expected = {
+ 'a' => %w[git://example/a.git 1234abc],
+ }
+
+ assert_equal expected, git_set.repositories
+ end
+
+ def test_parse_PATH
+ _, _, directory = vendor_gem
+
+ write_lockfile <<-LOCKFILE
+PATH
+ remote: #{directory}
+ specs:
+ a (1)
+ b (2)
+
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ parse_lockfile @set, []
+
+ assert_equal [dep('a', '= 1')], @set.dependencies
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set, 'found a LockSet'
+
+ vendor_set = @set.sets.find do |set|
+ Gem::Resolver::VendorSet === set
+ end
+
+ assert vendor_set, 'could not find a VendorSet'
+
+ assert_equal %w[a-1], vendor_set.specs.values.map { |s| s.full_name }
+
+ spec = vendor_set.load_spec 'a', nil, nil, nil
+
+ assert_equal [dep('b', '= 2')], spec.dependencies
+ end
+
+ def test_parse_dependency
+ write_lockfile ' 1)'
+
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file
+ parser = tokenizer.make_parser nil, nil
+
+ parsed = parser.parse_dependency 'a', '='
+
+ assert_equal dep('a', '= 1'), parsed
+
+ write_lockfile ')'
+
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file
+ parser = tokenizer.make_parser nil, nil
+
+ parsed = parser.parse_dependency 'a', '2'
+
+ assert_equal dep('a', '= 2'), parsed
+ end
+
+ def test_parse_gem_specs_dependency
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: #{@gem_repo}
+ specs:
+ a (2)
+ b (= 3)
+ c (~> 4)
+ d
+ e (~> 5.0, >= 5.0.1)
+ b (3-x86_64-linux)
+
+PLATFORMS
+ #{Gem::Platform::RUBY}
+
+DEPENDENCIES
+ a
+ LOCKFILE
+
+ platforms = []
+ parse_lockfile @set, platforms
+
+ assert_equal [dep('a')], @set.dependencies
+
+ assert_equal [Gem::Platform::RUBY], platforms
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ assert lockfile_set, 'could not find a LockSet'
+
+ assert_equal %w[a-2 b-3], lockfile_set.specs.map { |tuple| tuple.full_name }
+
+ expected = [
+ Gem::Platform::RUBY,
+ Gem::Platform.new('x86_64-linux'),
+ ]
+
+ assert_equal expected, lockfile_set.specs.map { |tuple| tuple.platform }
+
+ spec = lockfile_set.specs.first
+
+ expected = [
+ dep('b', '= 3'),
+ dep('c', '~> 4'),
+ dep('d'),
+ dep('e', '~> 5.0', '>= 5.0.1'),
+ ]
+
+ assert_equal expected, spec.dependencies
+ end
+
+ def test_parse_missing
+ assert_raises(Errno::ENOENT) do
+ parse_lockfile @set, []
+ end
+
+ lockfile_set = @set.sets.find do |set|
+ Gem::Resolver::LockSet === set
+ end
+
+ refute lockfile_set
+ end
+
+ def write_lockfile lockfile
+ open @lock_file, 'w' do |io|
+ io.write lockfile
+ end
+ end
+
+ def parse_lockfile set, platforms
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file
+ parser = tokenizer.make_parser set, platforms
+ parser.parse
+ end
+end
diff --git a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
new file mode 100644
index 0000000..bf56f50
--- /dev/null
+++ b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
@@ -0,0 +1,305 @@
+require 'rubygems/test_case'
+require 'rubygems/request_set'
+require 'rubygems/request_set/lockfile'
+require 'rubygems/request_set/lockfile/tokenizer'
+require 'rubygems/request_set/lockfile/parser'
+
+class TestGemRequestSetLockfileTokenizer < Gem::TestCase
+ def setup
+ super
+
+ @gem_deps_file = 'gem.deps.rb'
+ @lock_file = File.expand_path "#{@gem_deps_file}.lock"
+ end
+
+ def test_peek
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n"
+
+ assert_equal :newline, tokenizer.peek.first
+
+ assert_equal :newline, tokenizer.next_token.first
+
+ assert_equal [:EOF], tokenizer.peek
+ end
+
+ def test_skip
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n"
+
+ refute_predicate tokenizer, :empty?
+
+ tokenizer.skip :newline
+
+ assert_empty tokenizer
+ end
+
+ def test_token_pos
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new ''
+ assert_equal [5, 0], tokenizer.token_pos(5)
+
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new '', nil, 1, 2
+ assert_equal [3, 1], tokenizer.token_pos(5)
+ end
+
+ def test_tokenize
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: #{@gem_repo}
+ specs:
+ a (2)
+ b (= 2)
+ c (!= 3)
+ d (> 4)
+ e (< 5)
+ f (>= 6)
+ g (<= 7)
+ h (~> 8)
+
+PLATFORMS
+ #{Gem::Platform::RUBY}
+
+DEPENDENCIES
+ a
+ LOCKFILE
+
+ expected = [
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+
+ [:entry, 'remote', 2, 1],
+ [:text, @gem_repo, 10, 1],
+ [:newline, nil, 34, 1],
+
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+
+ [:text, 'a', 4, 3],
+ [:l_paren, nil, 6, 3],
+ [:text, '2', 7, 3],
+ [:r_paren, nil, 8, 3],
+ [:newline, nil, 9, 3],
+
+ [:text, 'b', 6, 4],
+ [:l_paren, nil, 8, 4],
+ [:requirement, '=', 9, 4],
+ [:text, '2', 11, 4],
+ [:r_paren, nil, 12, 4],
+ [:newline, nil, 13, 4],
+
+ [:text, 'c', 6, 5],
+ [:l_paren, nil, 8, 5],
+ [:requirement, '!=', 9, 5],
+ [:text, '3', 12, 5],
+ [:r_paren, nil, 13, 5],
+ [:newline, nil, 14, 5],
+
+ [:text, 'd', 6, 6],
+ [:l_paren, nil, 8, 6],
+ [:requirement, '>', 9, 6],
+ [:text, '4', 11, 6],
+ [:r_paren, nil, 12, 6],
+ [:newline, nil, 13, 6],
+
+ [:text, 'e', 6, 7],
+ [:l_paren, nil, 8, 7],
+ [:requirement, '<', 9, 7],
+ [:text, '5', 11, 7],
+ [:r_paren, nil, 12, 7],
+ [:newline, nil, 13, 7],
+
+ [:text, 'f', 6, 8],
+ [:l_paren, nil, 8, 8],
+ [:requirement, '>=', 9, 8],
+ [:text, '6', 12, 8],
+ [:r_paren, nil, 13, 8],
+ [:newline, nil, 14, 8],
+
+ [:text, 'g', 6, 9],
+ [:l_paren, nil, 8, 9],
+ [:requirement, '<=', 9, 9],
+ [:text, '7', 12, 9],
+ [:r_paren, nil, 13, 9],
+ [:newline, nil, 14, 9],
+
+ [:text, 'h', 6, 10],
+ [:l_paren, nil, 8, 10],
+ [:requirement, '~>', 9, 10],
+ [:text, '8', 12, 10],
+ [:r_paren, nil, 13, 10],
+ [:newline, nil, 14, 10],
+
+ [:newline, nil, 0, 11],
+
+ [:section, 'PLATFORMS', 0, 12],
+ [:newline, nil, 9, 12],
+
+ [:text, Gem::Platform::RUBY, 2, 13],
+ [:newline, nil, 6, 13],
+
+ [:newline, nil, 0, 14],
+
+ [:section, 'DEPENDENCIES', 0, 15],
+ [:newline, nil, 12, 15],
+
+ [:text, 'a', 2, 16],
+ [:newline, nil, 3, 16],
+ ]
+
+ assert_equal expected, tokenize_lockfile
+ end
+
+ def test_tokenize_capitals
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: #{@gem_repo}
+ specs:
+ Ab (2)
+
+PLATFORMS
+ #{Gem::Platform::RUBY}
+
+DEPENDENCIES
+ Ab
+ LOCKFILE
+
+ expected = [
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+ [:entry, 'remote', 2, 1],
+ [:text, @gem_repo, 10, 1],
+ [:newline, nil, 34, 1],
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+ [:text, 'Ab', 4, 3],
+ [:l_paren, nil, 7, 3],
+ [:text, '2', 8, 3],
+ [:r_paren, nil, 9, 3],
+ [:newline, nil, 10, 3],
+ [:newline, nil, 0, 4],
+ [:section, 'PLATFORMS', 0, 5],
+ [:newline, nil, 9, 5],
+ [:text, Gem::Platform::RUBY, 2, 6],
+ [:newline, nil, 6, 6],
+ [:newline, nil, 0, 7],
+ [:section, 'DEPENDENCIES', 0, 8],
+ [:newline, nil, 12, 8],
+ [:text, 'Ab', 2, 9],
+ [:newline, nil, 4, 9],
+ ]
+
+ assert_equal expected, tokenize_lockfile
+ end
+
+ def test_tokenize_conflict_markers
+ write_lockfile '<<<<<<<'
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ tokenize_lockfile
+ end
+
+ assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
+ e.message
+
+ write_lockfile '|||||||'
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ tokenize_lockfile
+ end
+
+ assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
+ e.message
+
+ write_lockfile '======='
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ tokenize_lockfile
+ end
+
+ assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
+ e.message
+
+ write_lockfile '>>>>>>>'
+
+ e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ tokenize_lockfile
+ end
+
+ assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
+ e.message
+ end
+
+ def test_tokenize_git
+ write_lockfile <<-LOCKFILE
+DEPENDENCIES
+ a!
+ LOCKFILE
+
+ expected = [
+ [:section, 'DEPENDENCIES', 0, 0],
+ [:newline, nil, 12, 0],
+
+ [:text, 'a', 2, 1],
+ [:bang, nil, 3, 1],
+ [:newline, nil, 4, 1],
+ ]
+
+ assert_equal expected, tokenize_lockfile
+ end
+
+ def test_tokenize_multiple
+ write_lockfile <<-LOCKFILE
+GEM
+ remote: #{@gem_repo}
+ specs:
+ a (2)
+ b (~> 3.0, >= 3.0.1)
+ LOCKFILE
+
+ expected = [
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+
+ [:entry, 'remote', 2, 1],
+ [:text, @gem_repo, 10, 1],
+ [:newline, nil, 34, 1],
+
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+
+ [:text, 'a', 4, 3],
+ [:l_paren, nil, 6, 3],
+ [:text, '2', 7, 3],
+ [:r_paren, nil, 8, 3],
+ [:newline, nil, 9, 3],
+
+ [:text, 'b', 6, 4],
+ [:l_paren, nil, 8, 4],
+ [:requirement, '~>', 9, 4],
+ [:text, '3.0', 12, 4],
+ [:comma, nil, 15, 4],
+ [:requirement, '>=', 17, 4],
+ [:text, '3.0.1', 20, 4],
+ [:r_paren, nil, 25, 4],
+ [:newline, nil, 26, 4],
+ ]
+
+ assert_equal expected, tokenize_lockfile
+ end
+
+ def test_unget
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n"
+ tokenizer.unshift :token
+ parser = tokenizer.make_parser nil, nil
+
+ assert_equal :token, parser.get
+ end
+
+ def write_lockfile lockfile
+ open @lock_file, 'w' do |io|
+ io.write lockfile
+ end
+ end
+
+ def tokenize_lockfile
+ Gem::RequestSet::Lockfile::Tokenizer.from_file(@lock_file).to_a
+ end
+end
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index 6974ff0..234edb4 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -347,6 +347,16 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.0.0.1", "= 1.0"
end
+ def test_hash_with_multiple_versions
+ r1 = req('1.0', '2.0')
+ r2 = req('2.0', '1.0')
+ assert_equal r1.hash, r2.hash
+
+ r1 = req('1.0', '2.0').tap { |r| r.concat(['3.0']) }
+ r2 = req('3.0', '1.0').tap { |r| r.concat(['2.0']) }
+ assert_equal r1.hash, r2.hash
+ end
+
# Assert that two requirements are equal. Handles Gem::Requirements,
# strings, arrays, numbers, and versions.
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 3cadc55..020cfb2 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -1080,6 +1080,12 @@ dependencies: []
assert_equal %w[true gem_name], gem.dependencies.map { |dep| dep.name }
end
+ def test_add_dependency_from_existing_dependency
+ dep = Gem::Dependency.new("existing_dep", Gem::Requirement.new('> 1'), :runtime)
+ spec = Gem::Specification.new { |s| s.add_dependency dep }
+ assert_equal dep, spec.dependencies.first
+ end
+
def test_add_dependency_with_type_explicit
gem = util_spec "awesome", "1.0" do |awesome|
awesome.add_development_dependency "monkey"
@@ -1856,8 +1862,8 @@ dependencies: []
@ext.require_paths = 'lib'
expected = [
- @ext.extension_dir,
File.join(@gemhome, 'gems', @ext.original_name, 'lib'),
+ @ext.extension_dir,
]
assert_equal expected, @ext.full_require_paths
diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb
index 914b06a..9d27312 100644
--- a/test/rubygems/test_gem_stub_specification.rb
+++ b/test/rubygems/test_gem_stub_specification.rb
@@ -65,8 +65,8 @@ class TestStubSpecification < Gem::TestCase
stub = stub_with_extension
expected = [
- stub.extension_dir,
File.join(stub.full_gem_path, 'lib'),
+ stub.extension_dir,
]
assert_equal expected, stub.full_require_paths