lib/bundler/source.rb in bundler-1.1.pre.4 vs lib/bundler/source.rb in bundler-1.1.pre.5

- old
+ new

@@ -9,10 +9,11 @@ module Bundler module Source # TODO: Refactor this class class Rubygems attr_reader :remotes, :caches + attr_accessor :dependencies def initialize(options = {}) @options = options @remotes = (options["remotes"] || []).map { |r| normalize_uri(r) } @fetchers = {} @@ -63,55 +64,49 @@ remote_names = self.remotes.map { |r| r.to_s }.join(', ') "rubygems repository #{remote_names}" end alias_method :name, :to_s - def specs(dependencies = nil) - @specs ||= fetch_specs(dependencies) + def specs + @specs ||= fetch_specs end def fetch(spec) spec, uri = @spec_fetch_map[spec.full_name] if spec path = download_gem_from_uri(spec, uri) s = Bundler.rubygems.spec_from_gem(path) - spec.__swap__(s) + spec.__swap__(s) if spec.is_a?(RemoteSpecification) end end - def outdated(spec) - installed_spec = installed_specs[spec.name] - installed_spec = installed_spec.first - - if installed_spec && spec.version == installed_spec.version - Bundler.ui.debug "Up to date: #{spec.name} (#{installed_spec.version}) " - return - end - - Bundler.ui.info "#{spec.name} (#{spec.version} > #{installed_spec.version}) " - end - def install(spec) - path = cached_gem(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) - install_path = Bundler.requires_sudo? ? Bundler.tmp : Bundler.rubygems.gem_dir - options = { :install_dir => install_path, - :ignore_dependencies => true, - :wrappers => true, - :env_shebang => true } - options.merge!(:bin_dir => "#{install_path}/bin") unless spec.executables.nil? || spec.executables.empty? + Bundler.rubygems.preserve_paths do - installer = Gem::Installer.new path, options - installer.install + install_path = Bundler.requires_sudo? ? Bundler.tmp : Bundler.rubygems.gem_dir + options = { :install_dir => install_path, + :ignore_dependencies => true, + :wrappers => true, + :env_shebang => true } + options.merge!(:bin_dir => "#{install_path}/bin") unless spec.executables.nil? || spec.executables.empty? + installer = Gem::Installer.new path, options + installer.install + end + + if spec.post_install_message + Installer.post_install_messages[spec.name] = spec.post_install_message + end + # SUDO HAX if Bundler.requires_sudo? sudo "mkdir -p #{Bundler.rubygems.gem_dir}/gems #{Bundler.rubygems.gem_dir}/specifications" sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Bundler.rubygems.gem_dir}/gems/" sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Bundler.rubygems.gem_dir}/specifications/" @@ -149,26 +144,30 @@ private def cached_gem(spec) possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" } - possibilities.find { |p| File.exist?(p) } + 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(dependencies = nil) + def fetch_specs Index.build do |idx| idx.use installed_specs idx.use cached_specs if @allow_cached || @allow_remote - idx.use remote_specs(dependencies) if @allow_remote + idx.use remote_specs if @allow_remote end end def installed_specs @installed_specs ||= begin @@ -204,11 +203,11 @@ @cached_specs ||= begin idx = installed_specs.dup path = Bundler.app_cache Dir["#{path}/*.gem"].each do |gemfile| - next if gemfile =~ /bundler\-[\d\.]+?\.gem/ + 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." @@ -220,32 +219,21 @@ end idx end - def remote_specs(dependencies = nil) + def remote_specs @remote_specs ||= begin idx = Index.new old = Bundler.rubygems.sources remotes.each do |uri| - Bundler.ui.info "Fetching source index for #{uri}" @fetchers[uri] = Bundler::Fetcher.new(uri) - gem_names = - if dependencies - dependencies.map {|d| d.name } - end - @fetchers[uri].fetch_remote_specs(gem_names) do |n,v| - v.each do |name, version, platform| - next if name == 'bundler' - spec = RemoteSpecification.new(name, version, platform, @fetchers[uri]) - spec.source = self - @spec_fetch_map[spec.full_name] = [spec, uri] - idx << spec - end - end + gem_names = dependencies && dependencies.map{|d| d.name } + + idx.use @fetchers[uri].specs(gem_names, self, @spec_fetch_map) end idx ensure Bundler.rubygems.sources = old end @@ -601,10 +589,23 @@ input = uri end Digest::SHA1.hexdigest(input) 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 cache_path @cache_path ||= begin git_scope = "#{base_name}-#{uri_hash}" if Bundler.requires_sudo? @@ -618,23 +619,24 @@ def cache if cached? return if has_revision_cached? Bundler.ui.info "Updating #{uri}" in_cache do - git %|fetch --force --quiet --tags "#{uri}" "refs/heads/*:refs/heads/*"| + git %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"| end else Bundler.ui.info "Fetching #{uri}" FileUtils.mkdir_p(cache_path.dirname) - git %|clone "#{uri}" "#{cache_path}" --bare --no-hardlinks| + git %|clone #{uri_escaped} "#{cache_path}" --bare --no-hardlinks| end end def checkout unless File.exist?(path.join(".git")) FileUtils.mkdir_p(path.dirname) FileUtils.rm_rf(path) git %|clone --no-checkout "#{cache_path}" "#{path}"| + File.chmod((0777 & ~File.umask), path) end Dir.chdir(path) do git %|fetch --force --quiet --tags "#{cache_path}"| git "reset --hard #{revision}"