From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001
From: Jari Vetoniemi <jari.vetoniemi@indooratlas.com>
Date: Mon, 16 Mar 2020 18:49:26 +0900
Subject: Fresh start

---
 jni/ruby/lib/rubygems/source/git.rb           | 240 ++++++++++++++++++++++++++
 jni/ruby/lib/rubygems/source/installed.rb     |  40 +++++
 jni/ruby/lib/rubygems/source/local.rb         | 129 ++++++++++++++
 jni/ruby/lib/rubygems/source/lock.rb          |  48 ++++++
 jni/ruby/lib/rubygems/source/specific_file.rb |  72 ++++++++
 jni/ruby/lib/rubygems/source/vendor.rb        |  27 +++
 6 files changed, 556 insertions(+)
 create mode 100644 jni/ruby/lib/rubygems/source/git.rb
 create mode 100644 jni/ruby/lib/rubygems/source/installed.rb
 create mode 100644 jni/ruby/lib/rubygems/source/local.rb
 create mode 100644 jni/ruby/lib/rubygems/source/lock.rb
 create mode 100644 jni/ruby/lib/rubygems/source/specific_file.rb
 create mode 100644 jni/ruby/lib/rubygems/source/vendor.rb

(limited to 'jni/ruby/lib/rubygems/source')

diff --git a/jni/ruby/lib/rubygems/source/git.rb b/jni/ruby/lib/rubygems/source/git.rb
new file mode 100644
index 0000000..35c2270
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/git.rb
@@ -0,0 +1,240 @@
+require 'digest'
+require 'rubygems/util'
+
+##
+# A git gem for use in a gem dependencies file.
+#
+# Example:
+#
+#   source =
+#     Gem::Source::Git.new 'rake', 'git@example:rake.git', 'rake-10.1.0', false
+#
+#   source.specs
+
+class Gem::Source::Git < Gem::Source
+
+  ##
+  # The name of the gem created by this git gem.
+
+  attr_reader :name
+
+  ##
+  # The commit reference used for checking out this git gem.
+
+  attr_reader :reference
+
+  ##
+  # When false the cache for this repository will not be updated.
+
+  attr_accessor :remote
+
+  ##
+  # The git repository this gem is sourced from.
+
+  attr_reader :repository
+
+  ##
+  # The directory for cache and git gem installation
+
+  attr_accessor :root_dir
+
+  ##
+  # Does this repository need submodules checked out too?
+
+  attr_reader :need_submodules
+
+  ##
+  # Creates a new git gem source for a gems from loaded from +repository+ at
+  # the given +reference+.  The +name+ is only used to track the repository
+  # back to a gem dependencies file, it has no real significance as a git
+  # repository may contain multiple gems.  If +submodules+ is true, submodules
+  # will be checked out when the gem is installed.
+
+  def initialize name, repository, reference, submodules = false
+    super repository
+
+    @name            = name
+    @repository      = repository
+    @reference       = reference
+    @need_submodules = submodules
+
+    @remote   = true
+    @root_dir = Gem.dir
+    @git      = ENV['git'] || 'git'
+  end
+
+  def <=> other
+    case other
+    when Gem::Source::Git then
+      0
+    when Gem::Source::Vendor,
+         Gem::Source::Lock then
+      -1
+    when Gem::Source then
+      1
+    else
+      nil
+    end
+  end
+
+  def == other # :nodoc:
+    super and
+      @name            == other.name and
+      @repository      == other.repository and
+      @reference       == other.reference and
+      @need_submodules == other.need_submodules
+  end
+
+  ##
+  # Checks out the files for the repository into the install_dir.
+
+  def checkout # :nodoc:
+    cache
+
+    return false unless File.exist? repo_cache_dir
+
+    unless File.exist? install_dir then
+      system @git, 'clone', '--quiet', '--no-checkout',
+             repo_cache_dir, install_dir
+    end
+
+    Dir.chdir install_dir do
+      system @git, 'fetch', '--quiet', '--force', '--tags', install_dir
+
+      success = system @git, 'reset', '--quiet', '--hard', rev_parse
+
+      success &&=
+        Gem::Util.silent_system @git, 'submodule', 'update',
+               '--quiet', '--init', '--recursive' if @need_submodules
+
+      success
+    end
+  end
+
+  ##
+  # Creates a local cache repository for the git gem.
+
+  def cache # :nodoc:
+    return unless @remote
+
+    if File.exist? repo_cache_dir then
+      Dir.chdir repo_cache_dir do
+        system @git, 'fetch', '--quiet', '--force', '--tags',
+               @repository, 'refs/heads/*:refs/heads/*'
+      end
+    else
+      system @git, 'clone', '--quiet', '--bare', '--no-hardlinks',
+             @repository, repo_cache_dir
+    end
+  end
+
+  ##
+  # Directory where git gems get unpacked and so-forth.
+
+  def base_dir # :nodoc:
+    File.join @root_dir, 'bundler'
+  end
+
+  ##
+  # A short reference for use in git gem directories
+
+  def dir_shortref # :nodoc:
+    rev_parse[0..11]
+  end
+
+  ##
+  # Nothing to download for git gems
+
+  def download full_spec, path # :nodoc:
+  end
+
+  ##
+  # The directory where the git gem will be installed.
+
+  def install_dir # :nodoc:
+    return unless File.exist? repo_cache_dir
+
+    File.join base_dir, 'gems', "#{@name}-#{dir_shortref}"
+  end
+
+  def pretty_print q # :nodoc:
+    q.group 2, '[Git: ', ']' do
+      q.breakable
+      q.text @repository
+
+      q.breakable
+      q.text @reference
+    end
+  end
+
+  ##
+  # The directory where the git gem's repository will be cached.
+
+  def repo_cache_dir # :nodoc:
+    File.join @root_dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}"
+  end
+
+  ##
+  # Converts the git reference for the repository into a commit hash.
+
+  def rev_parse # :nodoc:
+    hash = nil
+
+    Dir.chdir repo_cache_dir do
+      hash = Gem::Util.popen(@git, 'rev-parse', @reference).strip
+    end
+
+    raise Gem::Exception,
+          "unable to find reference #{@reference} in #{@repository}" unless
+            $?.success?
+
+    hash
+  end
+
+  ##
+  # Loads all gemspecs in the repository
+
+  def specs
+    checkout
+
+    return [] unless install_dir
+
+    Dir.chdir install_dir do
+      Dir['{,*,*/*}.gemspec'].map do |spec_file|
+        directory = File.dirname spec_file
+        file      = File.basename spec_file
+
+        Dir.chdir directory do
+          spec = Gem::Specification.load file
+          if spec then
+            spec.base_dir = base_dir
+
+            spec.extension_dir =
+              File.join base_dir, 'extensions', Gem::Platform.local.to_s,
+                Gem.extension_api_version, "#{name}-#{dir_shortref}"
+
+            spec.full_gem_path = File.dirname spec.loaded_from if spec
+          end
+          spec
+        end
+      end.compact
+    end
+  end
+
+  ##
+  # A hash for the git gem based on the git repository URI.
+
+  def uri_hash # :nodoc:
+    normalized =
+      if @repository =~ %r%^\w+://(\w+@)?% then
+        uri = URI(@repository).normalize.to_s.sub %r%/$%,''
+        uri.sub(/\A(\w+)/) { $1.downcase }
+      else
+        @repository
+      end
+
+    Digest::SHA1.hexdigest normalized
+  end
+
+end
+
diff --git a/jni/ruby/lib/rubygems/source/installed.rb b/jni/ruby/lib/rubygems/source/installed.rb
new file mode 100644
index 0000000..bd05c75
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/installed.rb
@@ -0,0 +1,40 @@
+##
+# Represents an installed gem.  This is used for dependency resolution.
+
+class Gem::Source::Installed < Gem::Source
+
+  def initialize # :nodoc:
+    @uri = nil
+  end
+
+  ##
+  # Installed sources sort before all other sources
+
+  def <=> other
+    case other
+    when Gem::Source::Git,
+         Gem::Source::Lock,
+         Gem::Source::Vendor then
+      -1
+    when Gem::Source::Installed then
+      0
+    when Gem::Source then
+      1
+    else
+      nil
+    end
+  end
+
+  ##
+  # We don't need to download an installed gem
+
+  def download spec, path
+    nil
+  end
+
+  def pretty_print q # :nodoc:
+    q.text '[Installed]'
+  end
+
+end
+
diff --git a/jni/ruby/lib/rubygems/source/local.rb b/jni/ruby/lib/rubygems/source/local.rb
new file mode 100644
index 0000000..8057921
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/local.rb
@@ -0,0 +1,129 @@
+##
+# The local source finds gems in the current directory for fulfilling
+# dependencies.
+
+class Gem::Source::Local < Gem::Source
+
+  def initialize # :nodoc:
+    @specs   = nil
+    @api_uri = nil
+    @uri     = nil
+  end
+
+  ##
+  # Local sorts before Gem::Source and after Gem::Source::Installed
+
+  def <=> other
+    case other
+    when Gem::Source::Installed,
+         Gem::Source::Lock then
+      -1
+    when Gem::Source::Local then
+      0
+    when Gem::Source then
+      1
+    else
+      nil
+    end
+  end
+
+  def inspect # :nodoc:
+    keys = @specs ? @specs.keys.sort : 'NOT LOADED'
+    "#<%s specs: %p>" % [self.class, keys]
+  end
+
+  def load_specs type # :nodoc:
+    names = []
+
+    @specs = {}
+
+    Dir["*.gem"].each do |file|
+      begin
+        pkg = Gem::Package.new(file)
+      rescue SystemCallError, Gem::Package::FormatError
+        # ignore
+      else
+        tup = pkg.spec.name_tuple
+        @specs[tup] = [File.expand_path(file), pkg]
+
+        case type
+        when :released
+          unless pkg.spec.version.prerelease?
+            names << pkg.spec.name_tuple
+          end
+        when :prerelease
+          if pkg.spec.version.prerelease?
+            names << pkg.spec.name_tuple
+          end
+        when :latest
+          tup = pkg.spec.name_tuple
+
+          cur = names.find { |x| x.name == tup.name }
+          if !cur
+            names << tup
+          elsif cur.version < tup.version
+            names.delete cur
+            names << tup
+          end
+        else
+          names << pkg.spec.name_tuple
+        end
+      end
+    end
+
+    names
+  end
+
+  def find_gem gem_name, version = Gem::Requirement.default, # :nodoc:
+               prerelease = false
+    load_specs :complete
+
+    found = []
+
+    @specs.each do |n, data|
+      if n.name == gem_name
+        s = data[1].spec
+
+        if version.satisfied_by?(s.version)
+          if prerelease
+            found << s
+          elsif !s.version.prerelease?
+            found << s
+          end
+        end
+      end
+    end
+
+    found.max_by { |s| s.version }
+  end
+
+  def fetch_spec name # :nodoc:
+    load_specs :complete
+
+    if data = @specs[name]
+      data.last.spec
+    else
+      raise Gem::Exception, "Unable to find spec for #{name.inspect}"
+    end
+  end
+
+  def download spec, cache_dir = nil # :nodoc:
+    load_specs :complete
+
+    @specs.each do |name, data|
+      return data[0] if data[1].spec == spec
+    end
+
+    raise Gem::Exception, "Unable to find file for '#{spec.full_name}'"
+  end
+
+  def pretty_print q # :nodoc:
+    q.group 2, '[Local gems:', ']' do
+      q.breakable
+      q.seplist @specs.keys do |v|
+        q.text v.full_name
+      end
+    end
+  end
+
+end
diff --git a/jni/ruby/lib/rubygems/source/lock.rb b/jni/ruby/lib/rubygems/source/lock.rb
new file mode 100644
index 0000000..2ba7702
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/lock.rb
@@ -0,0 +1,48 @@
+##
+# A Lock source wraps an installed gem's source and sorts before other sources
+# during dependency resolution.  This allows RubyGems to prefer gems from
+# dependency lock files.
+
+class Gem::Source::Lock < Gem::Source
+
+  ##
+  # The wrapped Gem::Source
+
+  attr_reader :wrapped
+
+  ##
+  # Creates a new Lock source that wraps +source+ and moves it earlier in the
+  # sort list.
+
+  def initialize source
+    @wrapped = source
+  end
+
+  def <=> other # :nodoc:
+    case other
+    when Gem::Source::Lock then
+      @wrapped <=> other.wrapped
+    when Gem::Source then
+      1
+    else
+      nil
+    end
+  end
+
+  def == other # :nodoc:
+    0 == (self <=> other)
+  end
+
+  ##
+  # Delegates to the wrapped source's fetch_spec method.
+
+  def fetch_spec name_tuple
+    @wrapped.fetch_spec name_tuple
+  end
+
+  def uri # :nodoc:
+    @wrapped.uri
+  end
+
+end
+
diff --git a/jni/ruby/lib/rubygems/source/specific_file.rb b/jni/ruby/lib/rubygems/source/specific_file.rb
new file mode 100644
index 0000000..250a839
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/specific_file.rb
@@ -0,0 +1,72 @@
+##
+# A source representing a single .gem file.  This is used for installation of
+# local gems.
+
+class Gem::Source::SpecificFile < Gem::Source
+
+  ##
+  # The path to the gem for this specific file.
+
+  attr_reader :path
+
+  ##
+  # Creates a new SpecificFile for the gem in +file+
+
+  def initialize(file)
+    @uri = nil
+    @path = ::File.expand_path(file)
+
+    @package = Gem::Package.new @path
+    @spec = @package.spec
+    @name = @spec.name_tuple
+  end
+
+  ##
+  # The Gem::Specification extracted from this .gem.
+
+  attr_reader :spec
+
+  def load_specs *a # :nodoc:
+    [@name]
+  end
+
+  def fetch_spec name # :nodoc:
+    return @spec if name == @name
+    raise Gem::Exception, "Unable to find '#{name}'"
+    @spec
+  end
+
+  def download spec, dir = nil # :nodoc:
+    return @path if spec == @spec
+    raise Gem::Exception, "Unable to download '#{spec.full_name}'"
+  end
+
+  def pretty_print q # :nodoc:
+    q.group 2, '[SpecificFile:', ']' do
+      q.breakable
+      q.text @path
+    end
+  end
+
+  ##
+  # Orders this source against +other+.
+  #
+  # If +other+ is a SpecificFile from a different gem name +nil+ is returned.
+  #
+  # If +other+ is a SpecificFile from the same gem name the versions are
+  # compared using Gem::Version#<=>
+  #
+  # Otherwise Gem::Source#<=> is used.
+
+  def <=> other
+    case other
+    when Gem::Source::SpecificFile then
+      return nil if @spec.name != other.spec.name
+
+      @spec.version <=> other.spec.version
+    else
+      super
+    end
+  end
+
+end
diff --git a/jni/ruby/lib/rubygems/source/vendor.rb b/jni/ruby/lib/rubygems/source/vendor.rb
new file mode 100644
index 0000000..2d93623
--- /dev/null
+++ b/jni/ruby/lib/rubygems/source/vendor.rb
@@ -0,0 +1,27 @@
+##
+# This represents a vendored source that is similar to an installed gem.
+
+class Gem::Source::Vendor < Gem::Source::Installed
+
+  ##
+  # Creates a new Vendor source for a gem that was unpacked at +path+.
+
+  def initialize path
+    @uri = path
+  end
+
+  def <=> other
+    case other
+    when Gem::Source::Lock then
+      -1
+    when Gem::Source::Vendor then
+      0
+    when Gem::Source then
+      1
+    else
+      nil
+    end
+  end
+
+end
+
-- 
cgit v1.2.3-70-g09d2