lib/bundler/source.rb in bundler-0.9.7 vs lib/bundler/source.rb in bundler-0.9.8
- old
+ new
@@ -1,6 +1,7 @@
-require "rubygems/remote_fetcher"
+require "uri"
+require "rubygems/spec_fetcher"
require "rubygems/format"
require "digest/sha1"
require "open3"
module Bundler
@@ -8,11 +9,12 @@
class Rubygems
attr_reader :uri, :options
def initialize(options = {})
@options = options
- @uri = options["uri"]
+ @uri = options["uri"].to_s
+ @uri = "#{uri}/" unless @uri =~ %r'/$'
@uri = URI.parse(@uri) unless @uri.is_a?(URI)
raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute?
end
def to_s
@@ -21,17 +23,18 @@
def specs
@specs ||= fetch_specs
end
- def install(spec)
- destination = Gem.dir
-
+ def fetch(spec)
Bundler.ui.debug " * Downloading"
- gem_path = Gem::RemoteFetcher.fetcher.download(spec, uri, destination)
+ Gem::RemoteFetcher.fetcher.download(spec, uri, Gem.dir)
+ end
+
+ def install(spec)
Bundler.ui.debug " * Installing"
- installer = Gem::Installer.new gem_path,
+ installer = Gem::Installer.new gem_path(spec),
:install_dir => Gem.dir,
:ignore_dependencies => true,
:wrappers => true,
:env_shebang => true,
:bin_dir => "#{Gem.dir}/bin"
@@ -39,42 +42,45 @@
installer.install
end
private
+ def gem_path(spec)
+ "#{Gem.dir}/cache/#{spec.full_name}.gem"
+ end
+
def fetch_specs
index = Index.new
Bundler.ui.info "Fetching source index from #{uri}"
- (main_specs + prerelease_specs).each do |name, version, platform|
- next unless Gem::Platform.match(platform)
- spec = RemoteSpecification.new(name, version, platform, @uri)
- spec.source = self
- index << spec
+ old, Gem.sources = Gem.sources, ["#{uri}"]
+
+ fetch_all_specs do |n,v|
+ v.each do |name, version, platform|
+ next unless Gem::Platform.match(platform)
+ spec = RemoteSpecification.new(name, version, platform, @uri)
+ spec.source = self
+ index << spec
+ end
end
+
index.freeze
+ ensure
+ Gem.sources = old
end
- def main_specs
- Marshal.load(Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/specs.4.8.gz"))
- rescue Gem::RemoteFetcher::FetchError => e
- raise ArgumentError, "#{to_s} is not a valid source: #{e.message}"
+ def fetch_all_specs(&blk)
+ Gem::SpecFetcher.new.list(true, false).each(&blk)
+ Gem::SpecFetcher.new.list(false, true).each(&blk)
end
-
- def prerelease_specs
- Marshal.load(Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/prerelease_specs.4.8.gz"))
- rescue Gem::RemoteFetcher::FetchError
- Bundler.ui.warn "Source '#{uri}' does not support prerelease gems"
- []
- end
end
class SystemGems
def specs
@specs ||= begin
index = Index.new
- Gem::SourceIndex.from_installed_gems.each do |name, spec|
+ Gem::SourceIndex.from_installed_gems.reverse_each do |name, spec|
spec.source = self
index << spec
end
index
@@ -99,26 +105,20 @@
".gem files at #{@path}"
end
def specs
@specs ||= begin
- index = Index.new
-
- Dir["#{@path}/*.gem"].each do |gemfile|
- spec = Gem::Format.from_file_by_path(gemfile).spec
- spec.source = self
- index << spec
- end
-
- index.freeze
+ specs = Index.from_cached_specs(@path)
+ specs.each { |s| s.source = self }
+ specs
end
end
def install(spec)
destination = Gem.dir
- Bundler.ui.debug " * Installing from pack"
+ Bundler.ui.debug " * Installing from cache"
installer = Gem::Installer.new "#{@path}/#{spec.full_name}.gem",
:install_dir => Gem.dir,
:ignore_dependencies => true,
:wrappers => true,
:env_shebang => true,
@@ -127,92 +127,108 @@
installer.install
end
end
class Path
- attr_reader :path, :options
+ attr_reader :path, :options, :default_spec
def initialize(options)
@options = options
@glob = options["glob"] || "{,*/}*.gemspec"
- @path = options["path"]
- @default_spec = nil
+
+ if options["path"]
+ @path = Pathname.new(options["path"]).expand_path(Bundler.root)
+ end
+
+ if options["name"]
+ @default_spec = Specification.new do |s|
+ s.name = options["name"]
+ s.source = self
+ s.version = Gem::Version.new(options["version"])
+ s.summary = "Fake gemspec for #{options["name"]}"
+ s.relative_loaded_from = "#{options["name"]}.gemspec"
+ end
+ end
end
def to_s
"source code at #{@path}"
end
- def default_spec(*args)
- return @default_spec if args.empty?
- name, version = *args
- @default_spec = Specification.new do |s|
- s.name = name
- s.source = self
- s.version = Gem::Version.new(version)
- s.relative_loaded_from = "#{name}.gemspec"
- end
- end
+ def load_spec_files
+ index = Index.new
- def local_specs
- @local_specs ||= begin
- index = Index.new
-
- if File.directory?(path)
- Dir["#{path}/#{@glob}"].each do |file|
- file = Pathname.new(file)
- relative_path = file.relative_path_from(Pathname.new(path))
- # Do it in the root of the repo in case they do
- # assume being in the root
- if spec = Dir.chdir(path) { eval(File.read(relative_path)) }
- spec = Specification.from_gemspec(spec)
- spec.loaded_from = file
- spec.source = self
- index << spec
- end
+ if File.directory?(path)
+ Dir["#{path}/#{@glob}"].each do |file|
+ file = Pathname.new(file)
+ # Eval the gemspec from its parent directory
+ if spec = Dir.chdir(file.dirname) { eval(File.read(file.basename)) }
+ spec = Specification.from_gemspec(spec)
+ spec.loaded_from = file.to_s
+ spec.source = self
+ index << spec
end
-
- index << default_spec if default_spec && index.empty?
end
- index.freeze
+ index << default_spec if default_spec && index.empty?
end
+
+ index.freeze
end
+ def local_specs
+ @local_specs ||= load_spec_files
+ end
+
def install(spec)
Bundler.ui.debug " * Using path #{path}"
generate_bin(spec)
end
alias specs local_specs
private
def generate_bin(spec)
- # HAX -- Generate the bin
- bin_dir = "#{Gem.dir}/bin"
- gem_dir = spec.full_gem_path
- installer = Gem::Installer.allocate
- installer.instance_eval do
- @spec = spec
- @bin_dir = bin_dir
- @gem_dir = gem_dir
- @wrappers = true
- @env_shebang = false
- @format_executable = false
+ gem_dir = spec.full_gem_path
+ gem_file = nil # so we have access once after it's set in the block
+
+ Dir.chdir(gem_dir) do
+ gem_file = Gem::Builder.new(spec).build
end
+
+ installer = Gem::Installer.new File.join(gem_dir, gem_file),
+ :bin_dir => "#{Gem.dir}/bin",
+ :wrappers => true,
+ :env_shebang => false,
+ :format_executable => false
+
+ installer.instance_eval { @gem_dir = gem_dir }
+
+ installer.build_extensions
installer.generate_bin
+ 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.emails.empty?
+ Bundler.ui.warn "If you need to use this package without installing it from a gem " \
+ "repository, please contact #{spec.emails.join(", or ")} 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}"
end
end
class Git < Path
attr_reader :uri, :ref, :options
def initialize(options)
- @options = options
- @glob = options["glob"] || "{,*/}*.gemspec"
+ super
@uri = options["uri"]
@ref = options["ref"] || options["branch"] || 'master'
end
def to_s
@@ -223,36 +239,13 @@
def path
Bundler.install_path.join("#{base_name}-#{uri_hash}-#{ref}")
end
def specs
- @specs ||= begin
- index = Index.new
- # Start by making sure the git cache is up to date
- cache
- # Find all gemspecs in the repo
- in_cache do
- out = %x(git ls-tree -r #{revision}).strip
- lines = out.split("\n").select { |l| l =~ /\.gemspec$/ }
- # Loop over the lines and extract the relative path and the
- # git hash
- lines.each do |line|
- next unless line =~ %r{^(\d+) (blob|tree) ([a-f0-9]+)\t(.*)$}
- hash, file = $3, $4
- # Read the gemspec
- if spec = eval(%x(git cat-file blob #{$3}))
- spec = Specification.from_gemspec(spec)
- spec.relative_loaded_from = file
- spec.source = self
- index << spec
- end
- end
- end
-
- index << default_spec if default_spec && index.empty?
-
- index.freeze
- end
+ # Start by making sure the git cache is up to date
+ cache
+ checkout
+ @specs ||= load_spec_files
end
def install(spec)
Bundler.ui.debug " * Using git #{uri}"