ruby-changes:37430
From: hsbt <ko1@a...>
Date: Thu, 5 Feb 2015 22:43:02 +0900 (JST)
Subject: [ruby-changes:37430] hsbt:r49511 (trunk): * lib/rubygems: Update to RubyGems HEAD(5c3b6f3).
hsbt 2015-02-05 22:42:45 +0900 (Thu, 05 Feb 2015) New Revision: 49511 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=49511 Log: * lib/rubygems: Update to RubyGems HEAD(5c3b6f3). Fixed #1156, #1142, #1115, #1142, #1139 on rubygems/rubygems * test/rubygems: ditto. Added directories: trunk/lib/rubygems/request_set/lockfile/ Added files: trunk/lib/rubygems/request_set/lockfile/parser.rb trunk/lib/rubygems/request_set/lockfile/tokenizer.rb trunk/test/rubygems/test_gem_request_set_lockfile_parser.rb trunk/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb Modified files: trunk/ChangeLog trunk/lib/rubygems/basic_specification.rb trunk/lib/rubygems/commands/open_command.rb trunk/lib/rubygems/installer.rb trunk/lib/rubygems/request_set/lockfile.rb trunk/lib/rubygems/request_set.rb trunk/lib/rubygems/requirement.rb trunk/lib/rubygems/specification.rb trunk/lib/rubygems/test_case.rb trunk/lib/rubygems/user_interaction.rb trunk/test/rubygems/test_gem_commands_open_command.rb trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb trunk/test/rubygems/test_gem_request_set_lockfile.rb trunk/test/rubygems/test_gem_requirement.rb trunk/test/rubygems/test_gem_specification.rb trunk/test/rubygems/test_gem_stub_specification.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 49510) +++ ChangeLog (revision 49511) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Feb 5 22:42:34 2015 SHIBATA Hiroshi <shibata.hiroshi@g...> + + * 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@r...> * vm_eval.c (send_internal), vm_insnhelper.c (vm_call_opt_send): Index: lib/rubygems/basic_specification.rb =================================================================== --- lib/rubygems/basic_specification.rb (revision 49510) +++ lib/rubygems/basic_specification.rb (revision 49511) @@ -144,7 +144,7 @@ class Gem::BasicSpecification https://github.com/ruby/ruby/blob/trunk/lib/rubygems/basic_specification.rb#L144 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 Index: lib/rubygems/request_set.rb =================================================================== --- lib/rubygems/request_set.rb (revision 49510) +++ lib/rubygems/request_set.rb (revision 49511) @@ -116,7 +116,7 @@ class Gem::RequestSet https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set.rb#L116 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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set.rb#L275 @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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set.rb#L416 require 'rubygems/request_set/gem_dependency_api' require 'rubygems/request_set/lockfile' +require 'rubygems/request_set/lockfile/tokenizer' Index: lib/rubygems/specification.rb =================================================================== --- lib/rubygems/specification.rb (revision 49510) +++ lib/rubygems/specification.rb (revision 49511) @@ -1028,8 +1028,8 @@ class Gem::Specification < Gem::BasicSpe https://github.com/ruby/ruby/blob/trunk/lib/rubygems/specification.rb#L1028 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::BasicSpe https://github.com/ruby/ruby/blob/trunk/lib/rubygems/specification.rb#L1040 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::BasicSpe https://github.com/ruby/ruby/blob/trunk/lib/rubygems/specification.rb#L1350 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 Index: lib/rubygems/commands/open_command.rb =================================================================== --- lib/rubygems/commands/open_command.rb (revision 49510) +++ lib/rubygems/commands/open_command.rb (revision 49511) @@ -61,7 +61,9 @@ class Gem::Commands::OpenCommand < Gem:: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/open_command.rb#L61 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 Index: lib/rubygems/requirement.rb =================================================================== --- lib/rubygems/requirement.rb (revision 49510) +++ lib/rubygems/requirement.rb (revision 49511) @@ -171,7 +171,7 @@ class Gem::Requirement https://github.com/ruby/ruby/blob/trunk/lib/rubygems/requirement.rb#L171 end def hash # :nodoc: - requirements.hash + requirements.sort.hash end def marshal_dump # :nodoc: Index: lib/rubygems/user_interaction.rb =================================================================== --- lib/rubygems/user_interaction.rb (revision 49510) +++ lib/rubygems/user_interaction.rb (revision 49511) @@ -396,10 +396,6 @@ class Gem::StreamUI https://github.com/ruby/ruby/blob/trunk/lib/rubygems/user_interaction.rb#L396 # 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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/user_interaction.rb#L529 # 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) Index: lib/rubygems/request_set/lockfile/tokenizer.rb =================================================================== --- lib/rubygems/request_set/lockfile/tokenizer.rb (revision 0) +++ lib/rubygems/request_set/lockfile/tokenizer.rb (revision 49511) @@ -0,0 +1,108 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile/tokenizer.rb#L1 +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 Index: lib/rubygems/request_set/lockfile/parser.rb =================================================================== --- lib/rubygems/request_set/lockfile/parser.rb (revision 0) +++ lib/rubygems/request_set/lockfile/parser.rb (revision 49511) @@ -0,0 +1,334 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile/parser.rb#L1 +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 + Index: lib/rubygems/request_set/lockfile.rb =================================================================== --- lib/rubygems/request_set/lockfile.rb (revision 49510) +++ lib/rubygems/request_set/lockfile.rb (revision 49511) @@ -1,12 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L1 -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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L34 @path = path super "#{message} (at line #{line} column #{column})" end - end ## @@ -57,11 +53,7 @@ class Gem::RequestSet::Lockfile https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L53 @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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L72 [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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L98 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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/request_set/lockfile.rb#L128 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 https://github.com/ruby/ruby/blob/trun (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/