mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Merge bundler to standard libraries.
rubygems 2.7.x depends bundler-1.15.x. This is preparation for rubygems and bundler migration. * lib/bundler.rb, lib/bundler/*: files of bundler-1.15.4 * spec/bundler/*: rspec examples of bundler-1.15.4. I applied patches. * https://github.com/bundler/bundler/pull/6007 * Exclude not working examples on ruby repository. * Fake ruby interpriter instead of installed ruby. * Makefile.in: Added test task named `test-bundler`. This task is only working macOS/linux yet. I'm going to support Windows environment later. * tool/sync_default_gems.rb: Added sync task for bundler. [Feature #12733][ruby-core:77172] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59779 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f2e04b77aa
commit
8598f8c2dc
409 changed files with 60699 additions and 1 deletions
324
lib/bundler/source/git.rb
Normal file
324
lib/bundler/source/git.rb
Normal file
|
@ -0,0 +1,324 @@
|
|||
# frozen_string_literal: true
|
||||
require "fileutils"
|
||||
require "uri"
|
||||
require "digest/sha1"
|
||||
|
||||
module Bundler
|
||||
class Source
|
||||
class Git < Path
|
||||
autoload :GitProxy, "bundler/source/git/git_proxy"
|
||||
|
||||
attr_reader :uri, :ref, :branch, :options, :submodules
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
@glob = options["glob"] || DEFAULT_GLOB
|
||||
|
||||
@allow_cached = false
|
||||
@allow_remote = false
|
||||
|
||||
# Stringify options that could be set as symbols
|
||||
%w(ref branch tag revision).each {|k| options[k] = options[k].to_s if options[k] }
|
||||
|
||||
@uri = options["uri"] || ""
|
||||
@branch = options["branch"]
|
||||
@ref = options["ref"] || options["branch"] || options["tag"] || "master"
|
||||
@submodules = options["submodules"]
|
||||
@name = options["name"]
|
||||
@version = options["version"].to_s.strip.gsub("-", ".pre.")
|
||||
|
||||
@copied = false
|
||||
@local = false
|
||||
end
|
||||
|
||||
def self.from_lock(options)
|
||||
new(options.merge("uri" => options.delete("remote")))
|
||||
end
|
||||
|
||||
def to_lock
|
||||
out = String.new("GIT\n")
|
||||
out << " remote: #{@uri}\n"
|
||||
out << " revision: #{revision}\n"
|
||||
%w(ref branch tag submodules).each do |opt|
|
||||
out << " #{opt}: #{options[opt]}\n" if options[opt]
|
||||
end
|
||||
out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
|
||||
out << " specs:\n"
|
||||
end
|
||||
|
||||
def hash
|
||||
[self.class, uri, ref, branch, name, version, submodules].hash
|
||||
end
|
||||
|
||||
def eql?(other)
|
||||
other.is_a?(Git) && uri == other.uri && ref == other.ref &&
|
||||
branch == other.branch && name == other.name &&
|
||||
version == other.version && submodules == other.submodules
|
||||
end
|
||||
|
||||
alias_method :==, :eql?
|
||||
|
||||
def to_s
|
||||
at = if local?
|
||||
path
|
||||
elsif user_ref = options["ref"]
|
||||
if ref =~ /\A[a-z0-9]{4,}\z/i
|
||||
shortref_for_display(user_ref)
|
||||
else
|
||||
user_ref
|
||||
end
|
||||
else
|
||||
ref
|
||||
end
|
||||
|
||||
rev = begin
|
||||
"@#{shortref_for_display(revision)}"
|
||||
rescue GitError
|
||||
nil
|
||||
end
|
||||
|
||||
"#{uri} (at #{at}#{rev})"
|
||||
end
|
||||
|
||||
def name
|
||||
File.basename(@uri, ".git")
|
||||
end
|
||||
|
||||
# This is the path which is going to contain a specific
|
||||
# checkout of the git repository. When using local git
|
||||
# repos, this is set to the local repo.
|
||||
def install_path
|
||||
@install_path ||= begin
|
||||
git_scope = "#{base_name}-#{shortref_for_path(revision)}"
|
||||
|
||||
path = Bundler.install_path.join(git_scope)
|
||||
|
||||
if !path.exist? && Bundler.requires_sudo?
|
||||
Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias_method :path, :install_path
|
||||
|
||||
def extension_dir_name
|
||||
"#{base_name}-#{shortref_for_path(revision)}"
|
||||
end
|
||||
|
||||
def unlock!
|
||||
git_proxy.revision = nil
|
||||
options["revision"] = nil
|
||||
|
||||
@unlocked = true
|
||||
end
|
||||
|
||||
def local_override!(path)
|
||||
return false if local?
|
||||
|
||||
path = Pathname.new(path)
|
||||
path = path.expand_path(Bundler.root) unless path.relative?
|
||||
|
||||
unless options["branch"] || Bundler.settings[:disable_local_branch_check]
|
||||
raise GitError, "Cannot use local override for #{name} at #{path} because " \
|
||||
":branch is not specified in Gemfile. Specify a branch or use " \
|
||||
"`bundle config --delete` to remove the local override"
|
||||
end
|
||||
|
||||
unless path.exist?
|
||||
raise GitError, "Cannot use local override for #{name} because #{path} " \
|
||||
"does not exist. Check `bundle config --delete` to remove the local override"
|
||||
end
|
||||
|
||||
set_local!(path)
|
||||
|
||||
# Create a new git proxy without the cached revision
|
||||
# so the Gemfile.lock always picks up the new revision.
|
||||
@git_proxy = GitProxy.new(path, uri, ref)
|
||||
|
||||
if git_proxy.branch != options["branch"] && !Bundler.settings[:disable_local_branch_check]
|
||||
raise GitError, "Local override for #{name} at #{path} is using branch " \
|
||||
"#{git_proxy.branch} but Gemfile specifies #{options["branch"]}"
|
||||
end
|
||||
|
||||
changed = cached_revision && cached_revision != git_proxy.revision
|
||||
|
||||
if changed && !@unlocked && !git_proxy.contains?(cached_revision)
|
||||
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
|
||||
"but the current branch in your local override for #{name} does not contain such commit. " \
|
||||
"Please make sure your branch is up to date."
|
||||
end
|
||||
|
||||
changed
|
||||
end
|
||||
|
||||
def specs(*)
|
||||
set_local!(app_cache_path) if has_app_cache? && !local?
|
||||
|
||||
if requires_checkout? && !@copied
|
||||
fetch
|
||||
git_proxy.copy_to(install_path, submodules)
|
||||
serialize_gemspecs_in(install_path)
|
||||
@copied = true
|
||||
end
|
||||
|
||||
local_specs
|
||||
end
|
||||
|
||||
def install(spec, options = {})
|
||||
force = options[:force]
|
||||
|
||||
Bundler.ui.info "Using #{version_message(spec)} from #{self}"
|
||||
|
||||
if requires_checkout? && !@copied && !force
|
||||
Bundler.ui.debug " * Checking out revision: #{ref}"
|
||||
git_proxy.copy_to(install_path, submodules)
|
||||
serialize_gemspecs_in(install_path)
|
||||
@copied = true
|
||||
elsif force
|
||||
git_proxy.copy_to(install_path, submodules)
|
||||
end
|
||||
|
||||
generate_bin_options = { :disable_extensions => !Bundler.rubygems.spec_missing_extensions?(spec), :build_args => options[:build_args] }
|
||||
generate_bin(spec, generate_bin_options)
|
||||
|
||||
requires_checkout? ? spec.post_install_message : nil
|
||||
end
|
||||
|
||||
def cache(spec, custom_path = nil)
|
||||
app_cache_path = app_cache_path(custom_path)
|
||||
return unless Bundler.settings[:cache_all]
|
||||
return if path == app_cache_path
|
||||
cached!
|
||||
FileUtils.rm_rf(app_cache_path)
|
||||
git_proxy.checkout if requires_checkout?
|
||||
git_proxy.copy_to(app_cache_path, @submodules)
|
||||
serialize_gemspecs_in(app_cache_path)
|
||||
end
|
||||
|
||||
def load_spec_files
|
||||
super
|
||||
rescue PathError => e
|
||||
Bundler.ui.trace e
|
||||
raise GitError, "#{self} is not yet checked out. Run `bundle install` first."
|
||||
end
|
||||
|
||||
# This is the path which is going to contain a cache
|
||||
# of the git repository. When using the same git repository
|
||||
# across different projects, this cache will be shared.
|
||||
# When using local git repos, this is set to the local repo.
|
||||
def cache_path
|
||||
@cache_path ||= begin
|
||||
git_scope = "#{base_name}-#{uri_hash}"
|
||||
|
||||
if Bundler.requires_sudo?
|
||||
Bundler.user_bundle_path.join("cache/git", git_scope)
|
||||
else
|
||||
Bundler.cache.join("git", git_scope)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def app_cache_dirname
|
||||
"#{base_name}-#{shortref_for_path(cached_revision || revision)}"
|
||||
end
|
||||
|
||||
def revision
|
||||
git_proxy.revision
|
||||
end
|
||||
|
||||
def allow_git_ops?
|
||||
@allow_remote || @allow_cached
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize_gemspecs_in(destination)
|
||||
destination = destination.expand_path(Bundler.root) if destination.relative?
|
||||
Dir["#{destination}/#{@glob}"].each do |spec_path|
|
||||
# Evaluate gemspecs and cache the result. Gemspecs
|
||||
# in git might require git or other dependencies.
|
||||
# The gemspecs we cache should already be evaluated.
|
||||
spec = Bundler.load_gemspec(spec_path)
|
||||
next unless spec
|
||||
Bundler.rubygems.set_installed_by_version(spec)
|
||||
Bundler.rubygems.validate(spec)
|
||||
File.open(spec_path, "wb") {|file| file.write(spec.to_ruby) }
|
||||
end
|
||||
end
|
||||
|
||||
def set_local!(path)
|
||||
@local = true
|
||||
@local_specs = @git_proxy = nil
|
||||
@cache_path = @install_path = path
|
||||
end
|
||||
|
||||
def has_app_cache?
|
||||
cached_revision && super
|
||||
end
|
||||
|
||||
def local?
|
||||
@local
|
||||
end
|
||||
|
||||
def requires_checkout?
|
||||
allow_git_ops? && !local?
|
||||
end
|
||||
|
||||
def base_name
|
||||
File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*}, ""), ".git")
|
||||
end
|
||||
|
||||
def shortref_for_display(ref)
|
||||
ref[0..6]
|
||||
end
|
||||
|
||||
def shortref_for_path(ref)
|
||||
ref[0..11]
|
||||
end
|
||||
|
||||
def uri_hash
|
||||
if uri =~ %r{^\w+://(\w+@)?}
|
||||
# Downcase the domain component of the URI
|
||||
# and strip off a trailing slash, if one is present
|
||||
input = URI.parse(uri).normalize.to_s.sub(%r{/$}, "")
|
||||
else
|
||||
# If there is no URI scheme, assume it is an ssh/git URI
|
||||
input = uri
|
||||
end
|
||||
Digest::SHA1.hexdigest(input)
|
||||
end
|
||||
|
||||
def cached_revision
|
||||
options["revision"]
|
||||
end
|
||||
|
||||
def cached?
|
||||
cache_path.exist?
|
||||
end
|
||||
|
||||
def git_proxy
|
||||
@git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision, self)
|
||||
end
|
||||
|
||||
def fetch
|
||||
git_proxy.checkout
|
||||
rescue GitError
|
||||
raise unless Bundler.feature_flag.allow_offline_install?
|
||||
Bundler.ui.warn "Using cached git data because of network errors"
|
||||
end
|
||||
|
||||
# no-op, since we validate when re-serializing the gemspec
|
||||
def validate_spec(_spec); end
|
||||
|
||||
if Bundler.rubygems.stubs_provide_full_functionality?
|
||||
def load_gemspec(file)
|
||||
stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent)
|
||||
stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s.untaint
|
||||
StubSpecification.from_stub(stub)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue