aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bundler/source.rb
diff options
context:
space:
mode:
authorAndre Arko <andre@arko.net>2012-11-13 10:38:48 -0800
committerAndre Arko <andre@arko.net>2012-11-13 10:40:34 -0800
commit4b4916c03b75674f06a15e1180334756b96dfca8 (patch)
tree3befedf739c742be25e8ee02d8c9882e477d4cdf /lib/bundler/source.rb
parent405edfe8995955a8161dc2cc815337c512901c78 (diff)
downloadbundler-4b4916c03b75674f06a15e1180334756b96dfca8.tar.gz
extract classes in bundler/source for autoloading
Diffstat (limited to 'lib/bundler/source.rb')
-rw-r--r--lib/bundler/source.rb889
1 files changed, 3 insertions, 886 deletions
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 004a3342..c75599f4 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -1,890 +1,7 @@
-require "uri"
-require 'rubygems/user_interaction'
-require "rubygems/installer"
-require "rubygems/spec_fetcher"
-require "rubygems/format"
-require "digest/sha1"
-require "fileutils"
-
module Bundler
module Source
- # TODO: Refactor this class
- class Rubygems
- FORCE_MODERN_INDEX_LIMIT = 100 # threshold for switching back to the modern index instead of fetching every spec
-
- attr_reader :remotes, :caches
- attr_accessor :dependency_names
-
- def initialize(options = {})
- @options = options
- @remotes = (options["remotes"] || []).map { |r| normalize_uri(r) }
- @fetchers = {}
- @allow_remote = false
- @allow_cached = false
-
- @caches = [ Bundler.app_cache ] +
- Bundler.rubygems.gem_path.map{|p| File.expand_path("#{p}/cache") }
- end
-
- def remote!
- @allow_remote = true
- end
-
- def cached!
- @allow_cached = true
- end
-
- def hash
- Rubygems.hash
- end
-
- def eql?(o)
- Rubygems === o
- end
-
- alias == eql?
-
- def options
- { "remotes" => @remotes.map { |r| r.to_s } }
- end
-
- def self.from_lock(options)
- s = new(options)
- Array(options["remote"]).each { |r| s.add_remote(r) }
- s
- end
-
- def to_lock
- out = "GEM\n"
- out << remotes.map {|r| " remote: #{r}\n" }.join
- out << " specs:\n"
- end
-
- def to_s
- remote_names = self.remotes.map { |r| r.to_s }.join(', ')
- "rubygems repository #{remote_names}"
- end
- alias_method :name, :to_s
-
- def specs
- @specs ||= fetch_specs
- end
-
- def install(spec)
- if installed_specs[spec].any?
- Bundler.ui.info "Using #{spec.name} (#{spec.version}) "
- return
- end
-
- Bundler.ui.info "Installing #{spec.name} (#{spec.version}) "
- path = cached_gem(spec)
- if Bundler.requires_sudo?
- install_path = Bundler.tmp
- bin_path = install_path.join("bin")
- else
- install_path = Bundler.rubygems.gem_dir
- bin_path = Bundler.system_bindir
- end
-
- Bundler.rubygems.preserve_paths do
- Bundler::GemInstaller.new(path,
- :install_dir => install_path.to_s,
- :bin_dir => bin_path.to_s,
- :ignore_dependencies => true,
- :wrappers => true,
- :env_shebang => true
- ).install
- end
-
- if spec.post_install_message
- Installer.post_install_messages[spec.name] = spec.post_install_message
- end
-
- # SUDO HAX
- if Bundler.requires_sudo?
- Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/gems"
- Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/specifications"
- Bundler.sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Bundler.rubygems.gem_dir}/gems/"
- Bundler.sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Bundler.rubygems.gem_dir}/specifications/"
- spec.executables.each do |exe|
- Bundler.mkdir_p Bundler.system_bindir
- Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.system_bindir}"
- end
- end
-
- spec.loaded_from = "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
- end
-
- def cache(spec)
- cached_path = cached_gem(spec)
- raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
- return if File.dirname(cached_path) == Bundler.app_cache.to_s
- Bundler.ui.info " * #{File.basename(cached_path)}"
- FileUtils.cp(cached_path, Bundler.app_cache)
- end
-
- def add_remote(source)
- @remotes << normalize_uri(source)
- end
-
- def replace_remotes(source)
- return false if source.remotes == @remotes
-
- @remotes = []
- source.remotes.each do |r|
- add_remote r.to_s
- end
-
- true
- end
-
- private
-
- def cached_gem(spec)
- possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" }
- cached_gem = possibilities.find { |p| File.exist?(p) }
- unless cached_gem
- raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
- end
- cached_gem
- end
-
- def normalize_uri(uri)
- uri = uri.to_s
- uri = "#{uri}/" unless uri =~ %r'/$'
- uri = URI(uri)
- raise ArgumentError, "The source must be an absolute URI" unless uri.absolute?
- uri
- end
-
- def fetch_specs
- # remote_specs usually generates a way larger Index than the other
- # sources, and large_idx.use small_idx is way faster than
- # small_idx.use large_idx.
- if @allow_remote
- idx = remote_specs.dup
- else
- idx = Index.new
- end
- idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
- idx.use(installed_specs, :override_dupes)
- idx
- end
-
- def installed_specs
- @installed_specs ||= begin
- idx = Index.new
- have_bundler = false
- Bundler.rubygems.all_specs.reverse.each do |spec|
- next if spec.name == 'bundler' && spec.version.to_s != VERSION
- have_bundler = true if spec.name == 'bundler'
- spec.source = self
- idx << spec
- end
-
- # Always have bundler locally
- unless have_bundler
- # We're running bundler directly from the source
- # so, let's create a fake gemspec for it (it's a path)
- # gemspec
- bundler = Gem::Specification.new do |s|
- s.name = 'bundler'
- s.version = VERSION
- s.platform = Gem::Platform::RUBY
- s.source = self
- s.authors = ["bundler team"]
- s.loaded_from = File.expand_path("..", __FILE__)
- end
- idx << bundler
- end
- idx
- end
- end
-
- def cached_specs
- @cached_specs ||= begin
- idx = installed_specs.dup
-
- path = Bundler.app_cache
- Dir["#{path}/*.gem"].each do |gemfile|
- next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
-
- begin
- s ||= Bundler.rubygems.spec_from_gem(gemfile)
- rescue Gem::Package::FormatError
- raise GemspecError, "Could not read gem at #{gemfile}. It may be corrupted."
- end
-
- s.source = self
- idx << s
- end
- end
-
- idx
- end
-
- def remote_specs
- @remote_specs ||= begin
- idx = Index.new
- old = Bundler.rubygems.sources
-
- sources = {}
- remotes.each do |uri|
- fetcher = Bundler::Fetcher.new(uri)
- specs = fetcher.specs(dependency_names, self)
- sources[fetcher] = specs.size
-
- idx.use specs
- end
-
- # don't need to fetch all specifications for every gem/version on
- # the rubygems repo if there's no api endpoints to search over
- # or it has too many specs to fetch
- fetchers = sources.keys
- api_fetchers = fetchers.select {|fetcher| fetcher.has_api }
- modern_index_fetchers = fetchers - api_fetchers
- if api_fetchers.any? && modern_index_fetchers.all? {|fetcher| sources[fetcher] < FORCE_MODERN_INDEX_LIMIT }
- # this will fetch all the specifications on the rubygems repo
- unmet_dependency_names = idx.unmet_dependency_names
- unmet_dependency_names -= ['bundler'] # bundler will always be unmet
-
- Bundler.ui.debug "Unmet Dependencies: #{unmet_dependency_names}"
- if unmet_dependency_names.any?
- api_fetchers.each do |fetcher|
- idx.use fetcher.specs(unmet_dependency_names, self)
- end
- end
- else
- Bundler::Fetcher.disable_endpoint = true
- api_fetchers.each {|fetcher| idx.use fetcher.specs([], self) }
- end
-
- idx
- ensure
- Bundler.rubygems.sources = old
- end
- end
- end
-
-
- class Path
- class Installer < Bundler::GemInstaller
- def initialize(spec, options = {})
- @spec = spec
- @bin_dir = Bundler.requires_sudo? ? "#{Bundler.tmp}/bin" : "#{Bundler.rubygems.gem_dir}/bin"
- @gem_dir = Bundler.rubygems.path(spec.full_gem_path)
- @wrappers = options[:wrappers] || true
- @env_shebang = options[:env_shebang] || true
- @format_executable = options[:format_executable] || false
- end
-
- def generate_bin
- return if spec.executables.nil? || spec.executables.empty?
-
- if Bundler.requires_sudo?
- FileUtils.mkdir_p("#{Bundler.tmp}/bin") unless File.exist?("#{Bundler.tmp}/bin")
- end
- super
- if Bundler.requires_sudo?
- Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/bin"
- spec.executables.each do |exe|
- Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.rubygems.gem_dir}/bin/"
- end
- end
- end
- end
-
- attr_reader :path, :options
- attr_writer :name
- attr_accessor :version
-
- DEFAULT_GLOB = "{,*,*/*}.gemspec"
-
- def initialize(options)
- @options = options
- @glob = options["glob"] || DEFAULT_GLOB
-
- @allow_cached = false
- @allow_remote = false
-
- if options["path"]
- @path = Pathname.new(options["path"])
- @path = @path.expand_path(Bundler.root) unless @path.relative?
- end
-
- @name = options["name"]
- @version = options["version"]
-
- # Stores the original path. If at any point we move to the
- # cached directory, we still have the original path to copy from.
- @original_path = @path
- end
-
- def remote!
- @allow_remote = true
- end
-
- def cached!
- @allow_cached = true
- end
-
- def self.from_lock(options)
- new(options.merge("path" => options.delete("remote")))
- end
-
- def to_lock
- out = "PATH\n"
- out << " remote: #{relative_path}\n"
- out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
- out << " specs:\n"
- end
-
- def to_s
- "source at #{@path}"
- end
-
- def hash
- self.class.hash
- end
-
- def eql?(o)
- o.instance_of?(Path) &&
- path.expand_path(Bundler.root) == o.path.expand_path(Bundler.root) &&
- version == o.version
- end
-
- alias == eql?
-
- def name
- File.basename(path.expand_path(Bundler.root).to_s)
- end
-
- def install(spec)
- Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
- # Let's be honest, when we're working from a path, we can't
- # really expect native extensions to work because the whole point
- # is to just be able to modify what's in that path and go. So, let's
- # not put ourselves through the pain of actually trying to generate
- # the full gem.
- Installer.new(spec).generate_bin
- end
-
- def cache(spec)
- return unless Bundler.settings[:cache_all]
- return if @original_path.expand_path(Bundler.root).to_s.index(Bundler.root.to_s) == 0
- FileUtils.rm_rf(app_cache_path)
- FileUtils.cp_r("#{@original_path}/.", app_cache_path)
- FileUtils.touch(app_cache_path.join(".bundlecache"))
- end
-
- def local_specs(*)
- @local_specs ||= load_spec_files
- end
-
- def specs
- if has_app_cache?
- @path = app_cache_path
- end
- local_specs
- end
-
- def app_cache_dirname
- name
- end
-
- private
-
- def app_cache_path
- @app_cache_path ||= Bundler.app_cache.join(app_cache_dirname)
- end
-
- def has_app_cache?
- SharedHelpers.in_bundle? && app_cache_path.exist?
- end
-
- def load_spec_files
- index = Index.new
- expanded_path = path.expand_path(Bundler.root)
-
- if File.directory?(expanded_path)
- Dir["#{expanded_path}/#{@glob}"].each do |file|
- spec = Bundler.load_gemspec(file)
- if spec
- spec.loaded_from = file.to_s
- spec.source = self
- index << spec
- end
- end
-
- if index.empty? && @name && @version
- index << Gem::Specification.new do |s|
- s.name = @name
- s.source = self
- s.version = Gem::Version.new(@version)
- s.platform = Gem::Platform::RUBY
- s.summary = "Fake gemspec for #{@name}"
- s.relative_loaded_from = "#{@name}.gemspec"
- s.authors = ["no one"]
- if expanded_path.join("bin").exist?
- executables = expanded_path.join("bin").children
- executables.reject!{|p| File.directory?(p) }
- s.executables = executables.map{|c| c.basename.to_s }
- end
- end
- end
- else
- raise PathError, "The path `#{expanded_path}` does not exist."
- end
-
- index
- end
-
- def relative_path
- if path.to_s.match(%r{^#{Regexp.escape Bundler.root.to_s}})
- return path.relative_path_from(Bundler.root)
- end
- path
- end
-
- def generate_bin(spec)
- gem_dir = Pathname.new(spec.full_gem_path)
-
- # Some gem authors put absolute paths in their gemspec
- # and we have to save them from themselves
- spec.files = spec.files.map do |p|
- next if File.directory?(p)
- begin
- Pathname.new(p).relative_path_from(gem_dir).to_s
- rescue ArgumentError
- p
- end
- end.compact
-
- gem_file = Dir.chdir(gem_dir){ Gem::Builder.new(spec).build }
-
- installer = Path::Installer.new(spec, :env_shebang => false)
- run_hooks(:pre_install, installer)
- installer.build_extensions
- run_hooks(:post_build, installer)
- installer.generate_bin
- run_hooks(:post_install, installer)
- rescue Gem::InvalidSpecificationException => e
- Bundler.ui.warn "\n#{spec.name} at #{spec.full_gem_path} did not have a valid gemspec.\n" \
- "This prevents bundler from installing bins or native extensions, but " \
- "that may not affect its functionality."
-
- if !spec.extensions.empty? && !spec.email.empty?
- Bundler.ui.warn "If you need to use this package without installing it from a gem " \
- "repository, please contact #{spec.email} and ask them " \
- "to modify their .gemspec so it can work with `gem build`."
- end
-
- Bundler.ui.warn "The validation message from Rubygems was:\n #{e.message}"
- ensure
- Dir.chdir(gem_dir){ FileUtils.rm_rf(gem_file) if gem_file && File.exist?(gem_file) }
- end
-
- def run_hooks(type, installer)
- hooks_meth = "#{type}_hooks"
- return unless Gem.respond_to?(hooks_meth)
- Gem.send(hooks_meth).each do |hook|
- result = hook.call(installer)
- if result == false
- location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
- message = "#{type} hook#{location} failed for #{installer.spec.full_name}"
- raise InstallHookError, message
- end
- end
- end
- end
-
- class Git < Path
- # The GitProxy is responsible to iteract with git repositories.
- # All actions required by the Git source is encapsualted in this
- # object.
- class GitProxy
- attr_accessor :path, :uri, :ref
- attr_writer :revision
-
- def initialize(path, uri, ref, revision=nil, &allow)
- @path = path
- @uri = uri
- @ref = ref
- @revision = revision
- @allow = allow || Proc.new { true }
- end
-
- def revision
- @revision ||= allowed_in_path { git("rev-parse #{ref}").strip }
- end
-
- def branch
- @branch ||= allowed_in_path do
- git("branch") =~ /^\* (.*)$/ && $1.strip
- end
- end
-
- def contains?(commit)
- allowed_in_path do
- result = git_null("branch --contains #{commit}")
- $? == 0 && result =~ /^\* (.*)$/
- end
- end
-
- def checkout
- if path.exist?
- return if has_revision_cached?
- Bundler.ui.info "Updating #{uri}"
- in_path do
- git %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"|
- end
- else
- Bundler.ui.info "Fetching #{uri}"
- FileUtils.mkdir_p(path.dirname)
- git %|clone #{uri_escaped} "#{path}" --bare --no-hardlinks|
- end
- end
-
- def copy_to(destination, submodules=false)
- unless File.exist?(destination.join(".git"))
- FileUtils.mkdir_p(destination.dirname)
- FileUtils.rm_rf(destination)
- git %|clone --no-checkout "#{path}" "#{destination}"|
- File.chmod((0777 & ~File.umask), destination)
- end
-
- Dir.chdir(destination) do
- git %|fetch --force --quiet --tags "#{path}"|
- git "reset --hard #{@revision}"
-
- if submodules
- git "submodule update --init --recursive"
- end
- end
- end
-
- private
-
- # TODO: Do not rely on /dev/null.
- # Given that open3 is not cross platform until Ruby 1.9.3,
- # the best solution is to pipe to /dev/null if it exists.
- # If it doesn't, everything will work fine, but the user
- # will get the $stderr messages as well.
- def git_null(command)
- if !Bundler::WINDOWS && File.exist?("/dev/null")
- git("#{command} 2>/dev/null", false)
- else
- git(command, false)
- end
- end
-
- def git(command, check_errors=true)
- if allow?
- out = %x{git #{command}}
-
- if check_errors && $?.exitstatus != 0
- msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed."
- msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
- raise GitError, msg
- end
- out
- else
- raise GitError, "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " \
- "this error message could probably be more useful. Please submit a ticket at http://github.com/carlhuda/bundler/issues " \
- "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
- end
- end
-
- def has_revision_cached?
- return unless @revision
- in_path { git("cat-file -e #{@revision}") }
- true
- rescue GitError
- false
- end
-
- # Escape the URI for git commands
- def uri_escaped
- if Bundler::WINDOWS
- # Windows quoting requires double quotes only, with double quotes
- # inside the string escaped by being doubled.
- '"' + uri.gsub('"') {|s| '""'} + '"'
- else
- # Bash requires single quoted strings, with the single quotes escaped
- # by ending the string, escaping the quote, and restarting the string.
- "'" + uri.gsub("'") {|s| "'\\''"} + "'"
- end
- end
-
- def allow?
- @allow.call
- end
-
- def in_path(&blk)
- checkout unless path.exist?
- Dir.chdir(path, &blk)
- end
-
- def allowed_in_path
- if allow?
- in_path { yield }
- else
- raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"
- end
- end
- end
-
- 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"]
-
- @update = false
- @installed = nil
- @local = false
- end
-
- def self.from_lock(options)
- new(options.merge("uri" => options.delete("remote")))
- end
-
- def to_lock
- out = "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 eql?(o)
- Git === o &&
- uri == o.uri &&
- ref == o.ref &&
- branch == o.branch &&
- name == o.name &&
- version == o.version &&
- submodules == o.submodules
- end
-
- alias == eql?
-
- def to_s
- at = if local?
- path
- elsif options["ref"]
- shortref_for_display(options["ref"])
- else
- ref
- end
- "#{uri} (at #{at})"
- 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)}"
-
- if Bundler.requires_sudo?
- Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
- else
- Bundler.install_path.join(git_scope)
- end
- end
- end
-
- alias :path :install_path
-
- def unlock!
- git_proxy.revision = nil
- 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 && !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
-
- # TODO: actually cache git specs
- def specs(*)
- if has_app_cache? && !local?
- set_local!(app_cache_path)
- end
-
- if requires_checkout? && !@update
- git_proxy.checkout
- git_proxy.copy_to(install_path, submodules)
- @update = true
- end
-
- local_specs
- end
-
- def install(spec)
- Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
- if requires_checkout? && !@installed
- Bundler.ui.debug " * Checking out revision: #{ref}"
- git_proxy.copy_to(install_path, submodules)
- @installed = true
- end
- generate_bin(spec)
- end
-
- def cache(spec)
- 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)
- FileUtils.rm_rf(app_cache_path.join(".git"))
- FileUtils.touch(app_cache_path.join(".bundlecache"))
- end
-
- def load_spec_files
- super
- rescue PathError, GitError
- raise GitError, "#{to_s} is not checked out. Please run `bundle install`"
- 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
-
- private
-
- 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 allow_git_ops?
- @allow_remote || @allow_cached
- end
-
- def cached_revision
- options["revision"]
- end
-
- def revision
- git_proxy.revision
- end
-
- def cached?
- cache_path.exist?
- end
-
- def git_proxy
- @git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision){ allow_git_ops? }
- end
- end
+ autoload :Rubygems, 'bundler/source/rubygems'
+ autoload :Path, 'bundler/source/path'
+ autoload :Git, 'bundler/source/git'
end
end