lib/bundler/definition.rb in bundler-1.10.6 vs lib/bundler/definition.rb in bundler-1.11.0.pre.1
- old
+ new
@@ -17,18 +17,15 @@
# @return [Bundler::Definition]
def self.build(gemfile, lockfile, unlock)
unlock ||= {}
gemfile = Pathname.new(gemfile).expand_path
- unless gemfile.file?
- raise GemfileNotFound, "#{gemfile} not found"
- end
+ raise GemfileNotFound, "#{gemfile} not found" unless gemfile.file?
Dsl.evaluate(gemfile, lockfile, unlock)
end
-
#
# How does the new system work?
#
# * Load information from Gemfile and Lockfile
# * Invalidate stale locked specs
@@ -60,11 +57,11 @@
@locked_bundler_version = nil
if lockfile && File.exist?(lockfile)
@lockfile_contents = Bundler.read_file(lockfile)
locked = LockfileParser.new(@lockfile_contents)
- @platforms = locked.platforms
+ @platforms = locked.platforms
@locked_bundler_version = locked.bundler_version
if unlock != true
@locked_deps = locked.dependencies
@locked_specs = SpecSet.new(locked.specs)
@@ -84,17 +81,17 @@
end
@unlock[:gems] ||= []
@unlock[:sources] ||= []
- current_platform = Bundler.rubygems.platforms.map { |p| generic(p) }.compact.last
+ current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
@new_platform = !@platforms.include?(current_platform)
@platforms |= [current_platform]
@path_changes = converge_paths
eager_unlock = expand_dependencies(@unlock[:gems])
- @unlock[:gems] = @locked_specs.for(eager_unlock).map { |s| s.name }
+ @unlock[:gems] = @locked_specs.for(eager_unlock).map(&:name)
@source_changes = converge_sources
@dependency_changes = converge_dependencies
@local_changes = converge_locals
@@ -108,11 +105,11 @@
# add_development_dependency in a gemspec that's loaded with the gemspec
# directive, the lockfile dependencies and resolved dependencies end up
# with a mismatch on #type.
# Test coverage to catch a regression on this is in gemspec_spec.rb
@dependencies.each do |d|
- if ld = @locked_deps.find { |l| l.name == d.name }
+ if ld = @locked_deps.find {|l| l.name == d.name }
ld.instance_variable_set(:@type, d.type)
end
end
end
@@ -139,11 +136,11 @@
@specs ||= begin
specs = resolve.materialize(Bundler.settings[:cache_all_platforms] ? dependencies : requested_dependencies)
unless specs["bundler"].any?
local = Bundler.settings[:frozen] ? rubygems_index : index
- bundler = local.search(Gem::Dependency.new('bundler', VERSION)).last
+ bundler = local.search(Gem::Dependency.new("bundler", VERSION)).last
specs["bundler"] = bundler if bundler
end
specs
end
@@ -168,22 +165,22 @@
end
def requested_specs
@requested_specs ||= begin
groups = requested_groups
- groups.map! { |g| g.to_sym }
+ groups.map!(&:to_sym)
specs_for(groups)
end
end
def current_dependencies
- dependencies.reject { |d| !d.should_include? }
+ dependencies.reject {|d| !d.should_include? }
end
def specs_for(groups)
- deps = dependencies.select { |d| (d.groups & groups).any? }
- deps.delete_if { |d| !d.should_include? }
+ deps = dependencies.select {|d| (d.groups & groups).any? }
+ deps.delete_if {|d| !d.should_include? }
specs.for(expand_dependencies(deps))
end
# Resolve all the dependencies specified in Gemfile. It ensures that
# dependencies that have been already resolved via locked file and are fresh
@@ -195,18 +192,19 @@
last_resolve = converge_locked_specs
if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
last_resolve
else
# Run a resolve against the locally available gems
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve)
+ requested_ruby_version = ruby_version.version if ruby_version
+ last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, requested_ruby_version)
end
end
end
def index
@index ||= Index.build do |idx|
- dependency_names = @dependencies.map { |d| d.name }
+ dependency_names = @dependencies.map(&:name)
sources.all_sources.each do |source|
source.dependency_names = dependency_names.dup
idx.add_source source.specs
dependency_names -= pinned_spec_names(source.specs)
@@ -236,11 +234,11 @@
def spec_git_paths
sources.git_sources.map {|s| s.path.to_s }
end
def groups
- dependencies.map { |d| d.groups }.flatten.uniq
+ dependencies.map(&:groups).flatten.uniq
end
def lock(file, preserve_bundled_with = false)
contents = to_lock
@@ -264,16 +262,13 @@
if Bundler.settings[:frozen]
Bundler.ui.error "Cannot write a changed lockfile while frozen."
return
end
- File.open(file, 'wb'){|f| f.puts(contents) }
- rescue Errno::EACCES
- raise Bundler::InstallError,
- "There was an error while trying to write to Gemfile.lock. It is likely that \n" \
- "you need to allow write permissions for the file at path: \n" \
- "#{File.expand_path(file)}"
+ SharedHelpers.filesystem_access(file) do |p|
+ File.open(p, "wb") {|f| f.puts(contents) }
+ end
end
# Returns the version of Bundler that is creating or has created
# Gemfile.lock. Used in #to_lock.
def lock_version
@@ -290,38 +285,36 @@
sources.lock_sources.each do |source|
# Add the source header
out << source.to_lock
# Find all specs for this source
resolve.
- select { |s| source.can_lock?(s) }.
+ select {|s| source.can_lock?(s) }.
# This needs to be sorted by full name so that
# gems with the same name, but different platform
# are ordered consistently
- sort_by { |s| s.full_name }.
+ sort_by(&:full_name).
each do |spec|
- next if spec.name == 'bundler'
+ next if spec.name == "bundler"
out << spec.to_lock
end
out << "\n"
end
out << "PLATFORMS\n"
- platforms.map { |p| p.to_s }.sort.each do |p|
+ platforms.map(&:to_s).sort.each do |p|
out << " #{p}\n"
end
out << "\n"
out << "DEPENDENCIES\n"
handled = []
- dependencies.
- sort_by { |d| d.to_s }.
- each do |dep|
- next if handled.include?(dep.name)
- out << dep.to_lock
- handled << dep.name
+ dependencies.sort_by(&:to_s).each do |dep|
+ next if handled.include?(dep.name)
+ out << dep.to_lock
+ handled << dep.name
end
# Record the version of Bundler that was used to create the lockfile
out << "\nBUNDLED WITH\n"
out << " #{lock_version}\n"
@@ -330,14 +323,14 @@
end
def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
msg = "You are trying to install in deployment mode after changing\n" \
"your Gemfile. Run `bundle install` elsewhere and add the\n" \
- "updated Gemfile.lock to version control."
+ "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
unless explicit_flag
- msg += "\n\nIf this is a development machine, remove the Gemfile " \
+ msg += "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
"freeze \nby running `bundle install --no-deployment`."
end
added = []
deleted = []
@@ -347,44 +340,41 @@
if @locked_sources != gemfile_sources
new_sources = gemfile_sources - @locked_sources
deleted_sources = @locked_sources - gemfile_sources
if new_sources.any?
- added.concat new_sources.map { |source| "* source: #{source}" }
+ added.concat new_sources.map {|source| "* source: #{source}" }
end
if deleted_sources.any?
- deleted.concat deleted_sources.map { |source| "* source: #{source}" }
+ deleted.concat deleted_sources.map {|source| "* source: #{source}" }
end
end
new_deps = @dependencies - @locked_deps
deleted_deps = @locked_deps - @dependencies
- if new_deps.any?
- added.concat new_deps.map { |d| "* #{pretty_dep(d)}" }
- end
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
if deleted_deps.any?
- deleted.concat deleted_deps.map { |d| "* #{pretty_dep(d)}" }
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
end
- both_sources = Hash.new { |h,k| h[k] = [] }
- @dependencies.each { |d| both_sources[d.name][0] = d }
- @locked_deps.each { |d| both_sources[d.name][1] = d.source }
+ both_sources = Hash.new {|h, k| h[k] = [] }
+ @dependencies.each {|d| both_sources[d.name][0] = d }
+ @locked_deps.each {|d| both_sources[d.name][1] = d.source }
both_sources.each do |name, (dep, lock_source)|
- if (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
- gemfile_source_name = (dep && dep.source) || 'no specified source'
- lockfile_source_name = lock_source || 'no specified source'
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
- end
+ next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
+ gemfile_source_name = (dep && dep.source) || "no specified source"
+ lockfile_source_name = lock_source || "no specified source"
+ changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
end
- msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
+ msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
- msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
+ msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
msg << "\n"
raise ProductionError, msg if added.any? || deleted.any? || changed.any?
end
@@ -393,39 +383,39 @@
if diff = ruby_version.diff(Bundler.ruby_version)
problem, expected, actual = diff
msg = case problem
- when :engine
- "Your Ruby engine is #{actual}, but your Gemfile specified #{expected}"
- when :version
- "Your Ruby version is #{actual}, but your Gemfile specified #{expected}"
- when :engine_version
- "Your #{Bundler.ruby_version.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
- when :patchlevel
- if !expected.is_a?(String)
- "The Ruby patchlevel in your Gemfile must be a string"
- else
- "Your Ruby patchlevel is #{actual}, but your Gemfile specified #{expected}"
- end
+ when :engine
+ "Your Ruby engine is #{actual}, but your Gemfile specified #{expected}"
+ when :version
+ "Your Ruby version is #{actual}, but your Gemfile specified #{expected}"
+ when :engine_version
+ "Your #{Bundler.ruby_version.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
+ when :patchlevel
+ if !expected.is_a?(String)
+ "The Ruby patchlevel in your Gemfile must be a string"
+ else
+ "Your Ruby patchlevel is #{actual}, but your Gemfile specified #{expected}"
+ end
end
raise RubyVersionMismatch, msg
end
end
attr_reader :sources
- private :sources
+ private :sources
private
def nothing_changed?
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
end
def pretty_dep(dep, source = false)
- msg = "#{dep.name}"
+ msg = "#{dep.name}"
msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
msg << " from the `#{dep.source}` source" if source && dep.source
msg
end
@@ -444,33 +434,33 @@
!locked || unlocking || dependencies_for_source_changed?(locked) || source.specs != locked.specs
end
def dependencies_for_source_changed?(source)
- deps_for_source = @dependencies.select { |s| s.source == source }
- locked_deps_for_source = @locked_deps.select { |s| s.source == source }
+ deps_for_source = @dependencies.select {|s| s.source == source }
+ locked_deps_for_source = @locked_deps.select {|s| s.source == source }
deps_for_source != locked_deps_for_source
end
# Get all locals and override their matching sources.
# Return true if any of the locals changed (for example,
# they point to a new revision) or depend on new specs.
def converge_locals
locals = []
- Bundler.settings.local_overrides.map do |k,v|
- spec = @dependencies.find { |s| s.name == k }
+ Bundler.settings.local_overrides.map do |k, v|
+ spec = @dependencies.find {|s| s.name == k }
source = spec && spec.source
if source && source.respond_to?(:local_override!)
source.unlock! if @unlock[:gems].include?(spec.name)
- locals << [ source, source.local_override!(v) ]
+ locals << [source, source.local_override!(v)]
end
end
locals.any? do |source, changed|
- changed || specs_changed?(source) { |o| source.class == o.class && source.uri == o.uri }
+ changed || specs_changed?(source) {|o| source.class == o.class && source.uri == o.uri }
end
end
def converge_paths
sources.path_sources.any? do |source|
@@ -482,26 +472,26 @@
def converge_sources
changes = false
# Get the Rubygems sources from the Gemfile.lock
- locked_gem_sources = @locked_sources.select { |s| s.kind_of?(Source::Rubygems) }
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
# Get the Rubygems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
# If there is a Rubygems source in both
if !locked_gem_sources.empty? && !actual_remotes.empty?
locked_gem_sources.each do |locked_gem|
# Merge the remotes from the Gemfile into the Gemfile.lock
- changes = changes | locked_gem.replace_remotes(actual_remotes)
+ changes |= locked_gem.replace_remotes(actual_remotes)
end
end
# Replace the sources from the Gemfile with the sources from the Gemfile.lock,
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
# source in the Gemfile.lock, use the one from the Gemfile.
- changes = changes | sources.replace_sources!(@locked_sources)
+ changes |= sources.replace_sources!(@locked_sources)
sources.all_sources.each do |source|
# If the source is unlockable and the current command allows an unlock of
# the source (for example, you are doing a `bundle update <foo>` of a git-pinned
# gem), unlock it. For git sources, this means to unlock the revision, which
@@ -516,13 +506,11 @@
changes
end
def converge_dependencies
(@dependencies + @locked_deps).each do |dep|
- if dep.source
- dep.source = sources.get(dep.source)
- end
+ dep.source = sources.get(dep.source) if dep.source
end
Set.new(@dependencies) != Set.new(@locked_deps)
end
# Remove elements from the locked specs that are expired. This will most
@@ -533,11 +521,14 @@
# Build a list of dependencies that are the same in the Gemfile
# and Gemfile.lock. If the Gemfile modified a dependency, but
# the gem in the Gemfile.lock still satisfies it, this is fine
# too.
- locked_deps_hash = @locked_deps.inject({}) { |hsh, dep| hsh[dep] = dep; hsh }
+ locked_deps_hash = @locked_deps.inject({}) do |hsh, dep|
+ hsh[dep] = dep
+ hsh
+ end
@dependencies.each do |dep|
locked_dep = locked_deps_hash[dep]
if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
deps << dep
@@ -545,23 +536,28 @@
@locked_specs.each do |s|
@unlock[:gems] << s.name if s.source == dep.source
end
dep.source.unlock! if dep.source.respond_to?(:unlock!)
- dep.source.specs.each { |s| @unlock[:gems] << s.name }
+ dep.source.specs.each {|s| @unlock[:gems] << s.name }
end
end
converged = []
@locked_specs.each do |s|
# Replace the locked dependency's source with the equivalent source from the Gemfile
- dep = @dependencies.find { |d| s.satisfies?(d) }
+ dep = @dependencies.find {|d| s.satisfies?(d) }
s.source = (dep && dep.source) || sources.get(s.source)
# Don't add a spec to the list if its source is expired. For example,
# if you change a Git gem to Rubygems.
+ next if s.source.nil? || @unlock[:sources].include?(s.source.name)
+
+ # XXX This is a backwards-compatibility fix to preserve the ability to
+ # unlock a single gem by passing its name via `--source`. See issue #3759
next if s.source.nil? || @unlock[:sources].include?(s.name)
+
# If the spec is from a path source and it doesn't exist anymore
# then we just unlock it.
# Path sources have special logic
if s.source.instance_of?(Source::Path)
@@ -569,11 +565,11 @@
# If the spec is no longer in the path source, unlock it. This
# commonly happens if the version changed in the gemspec
next unless other
- deps2 = other.dependencies.select { |d| d.type != :development }
+ deps2 = other.dependencies.select {|d| d.type != :development }
# If the dependencies of the path source have changed, unlock it
next unless s.dependencies.sort == deps2.sort
end
converged << s
@@ -585,12 +581,12 @@
# Now, we unlock any sources that do not have anymore gems pinned to it
sources.all_sources.each do |source|
next unless source.respond_to?(:unlock!)
- unless resolve.any? { |s| s.source == source }
- source.unlock! if !diff.empty? && diff.any? { |s| s.source == source }
+ unless resolve.any? {|s| s.source == source }
+ source.unlock! if !diff.empty? && diff.any? {|s| s.source == source }
end
end
resolve
end
@@ -601,11 +597,11 @@
# that the Gemfile dep does.
locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
end
def satisfies_locked_spec?(dep)
- @locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
+ @locked_specs.any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
end
def expanded_dependencies
@expanded_dependencies ||= expand_dependencies(dependencies, @remote)
end
@@ -622,12 +618,12 @@
deps
end
def requested_dependencies
groups = requested_groups
- groups.map! { |g| g.to_sym }
- dependencies.reject { |d| !d.should_include? || (d.groups & groups).empty? }
+ groups.map!(&:to_sym)
+ dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? }
end
def source_requirements
# Load all specs from remote sources
index
@@ -644,11 +640,11 @@
end
def pinned_spec_names(specs)
names = []
specs.each do |s|
- # TODO when two sources without blocks is an error, we can change
+ # TODO: when two sources without blocks is an error, we can change
# this check to !s.source.is_a?(Source::LocalRubygems). For now,
# we need to ask every Rubygems for every gem name.
if s.source.is_a?(Source::Git) || s.source.is_a?(Source::Path)
names << s.name
end
@@ -656,19 +652,18 @@
names.uniq!
names
end
def requested_groups
- self.groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
+ groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
end
def lockfiles_equal?(current, proposed, preserve_bundled_with)
if preserve_bundled_with
pattern = /\n\n#{LockfileParser::BUNDLED}\n\s+#{Gem::Version::VERSION_PATTERN}\n/
current.sub(pattern, "\n") == proposed.sub(pattern, "\n")
else
current == proposed
end
end
-
end
end