Object
# File lib/bundler/definition.rb, line 9 9: def self.build(gemfile, lockfile, unlock) 10: unlock ||= {} 11: gemfile = Pathname.new(gemfile).expand_path 12: 13: unless gemfile.file? 14: raise GemfileNotFound, "#{gemfile} not found" 15: end 16: 17: # TODO: move this back into DSL 18: builder = Dsl.new 19: builder.instance_eval(Bundler.read_file(gemfile.to_s), gemfile.to_s, 1) 20: builder.to_definition(lockfile, unlock) 21: end
# File lib/bundler/definition.rb, line 35 35: def initialize(lockfile, dependencies, sources, unlock) 36: @dependencies, @sources, @unlock = dependencies, sources, unlock 37: @remote = false 38: @specs = nil 39: @lockfile_contents = "" 40: 41: if lockfile && File.exists?(lockfile) 42: @lockfile_contents = Bundler.read_file(lockfile) 43: locked = LockfileParser.new(@lockfile_contents) 44: @platforms = locked.platforms 45: 46: if unlock != true 47: @locked_deps = locked.dependencies 48: @locked_specs = SpecSet.new(locked.specs) 49: @locked_sources = locked.sources 50: else 51: @unlock = {} 52: @locked_deps = [] 53: @locked_specs = SpecSet.new([]) 54: @locked_sources = [] 55: end 56: else 57: @unlock = {} 58: @platforms = [] 59: @locked_deps = [] 60: @locked_specs = SpecSet.new([]) 61: @locked_sources = [] 62: end 63: 64: @unlock[:gems] ||= [] 65: @unlock[:sources] ||= [] 66: 67: current_platform = Gem.platforms.map { |p| generic(p) }.compact.last 68: @new_platform = !@platforms.include?(current_platform) 69: @platforms |= [current_platform] 70: 71: eager_unlock = expand_dependencies(@unlock[:gems]) 72: @unlock[:gems] = @locked_specs.for(eager_unlock).map { |s| s.name } 73: 74: converge_sources 75: converge_dependencies 76: end
# File lib/bundler/definition.rb, line 130 130: def current_dependencies 131: dependencies.reject { |d| !d.should_include? } 132: end
# File lib/bundler/definition.rb, line 230 230: def ensure_equivalent_gemfile_and_lockfile 231: changes = false 232: 233: msg = "You have modified your Gemfile in development but did not check\n" "the resulting snapshot (Gemfile.lock) into version control" 234: 235: added = [] 236: deleted = [] 237: changed = [] 238: 239: if @locked_sources != @sources 240: new_sources = @sources - @locked_sources 241: deleted_sources = @locked_sources - @sources 242: 243: if new_sources.any? 244: added.concat new_sources.map { |source| "* source: #{source}" } 245: end 246: 247: if deleted_sources.any? 248: deleted.concat deleted_sources.map { |source| "* source: #{source}" } 249: end 250: 251: changes = true 252: end 253: 254: both_sources = Hash.new { |h,k| h[k] = ["no specified source", "no specified source"] } 255: @dependencies.each { |d| both_sources[d.name][0] = d.source if d.source } 256: @locked_deps.each { |d| both_sources[d.name][1] = d.source if d.source } 257: both_sources.delete_if { |k,v| v[0] == v[1] } 258: 259: if @dependencies != @locked_deps 260: new_deps = @dependencies - @locked_deps 261: deleted_deps = @locked_deps - @dependencies 262: 263: if new_deps.any? 264: added.concat new_deps.map { |d| "* #{pretty_dep(d)}" } 265: end 266: 267: if deleted_deps.any? 268: deleted.concat deleted_deps.map { |d| "* #{pretty_dep(d)}" } 269: end 270: 271: both_sources.each do |name, sources| 272: changed << "* #{name} from `#{sources[0]}` to `#{sources[1]}`" 273: end 274: 275: changes = true 276: end 277: 278: msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? 279: msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any? 280: msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any? 281: 282: raise ProductionError, msg if added.any? || deleted.any? || changed.any? 283: end
# File lib/bundler/definition.rb, line 170 170: def groups 171: dependencies.map { |d| d.groups }.flatten.uniq 172: end
# File lib/bundler/definition.rb, line 158 158: def index 159: @index ||= Index.build do |idx| 160: @sources.each do |s| 161: idx.use s.specs 162: end 163: end 164: end
# File lib/bundler/definition.rb, line 174 174: def lock(file) 175: contents = to_lock 176: 177: return if @lockfile_contents == contents 178: 179: if Bundler.settings[:frozen] 180: # TODO: Warn here if we got here. 181: return 182: end 183: 184: File.open(file, 'wb') do |f| 185: f.puts contents 186: end 187: end
# File lib/bundler/definition.rb, line 116 116: def missing_specs 117: missing = [] 118: resolve.materialize(requested_dependencies, missing) 119: missing 120: end
# File lib/bundler/definition.rb, line 112 112: def new_platform? 113: @new_platform 114: end
# File lib/bundler/definition.rb, line 104 104: def new_specs 105: specs - @locked_specs 106: end
# File lib/bundler/definition.rb, line 166 166: def no_sources? 167: @sources.length == 1 && @sources.first.remotes.empty? 168: end
# File lib/bundler/definition.rb, line 108 108: def removed_specs 109: @locked_specs - specs 110: end
# File lib/bundler/definition.rb, line 122 122: def requested_specs 123: @requested_specs ||= begin 124: groups = self.groups - Bundler.settings.without 125: groups.map! { |g| g.to_sym } 126: specs_for(groups) 127: end 128: end
# File lib/bundler/definition.rb, line 140 140: def resolve 141: @resolve ||= begin 142: if Bundler.settings[:frozen] 143: @locked_specs 144: else 145: last_resolve = converge_locked_specs 146: source_requirements = {} 147: dependencies.each do |dep| 148: next unless dep.source 149: source_requirements[dep.name] = dep.source.specs 150: end 151: 152: # Run a resolve against the locally available gems 153: last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve) 154: end 155: end 156: end
# File lib/bundler/definition.rb, line 84 84: def resolve_remotely! 85: raise "Specs already loaded" if @specs 86: @remote = true 87: @sources.each { |s| s.remote! } 88: specs 89: end
# File lib/bundler/definition.rb, line 78 78: def resolve_with_cache! 79: raise "Specs already loaded" if @specs 80: @sources.each { |s| s.cached! } 81: specs 82: end
# File lib/bundler/definition.rb, line 91 91: def specs 92: @specs ||= begin 93: specs = resolve.materialize(requested_dependencies) 94: 95: unless specs["bundler"].any? 96: bundler = index.search(Gem::Dependency.new('bundler', VERSION)).last 97: specs["bundler"] = bundler if bundler 98: end 99: 100: specs 101: end 102: end
# File lib/bundler/definition.rb, line 134 134: def specs_for(groups) 135: deps = dependencies.select { |d| (d.groups & groups).any? } 136: deps.delete_if { |d| !d.should_include? } 137: specs.for(expand_dependencies(deps)) 138: end
# File lib/bundler/definition.rb, line 189 189: def to_lock 190: out = "" 191: 192: sorted_sources.each do |source| 193: # Add the source header 194: out << source.to_lock 195: # Find all specs for this source 196: resolve. 197: select { |s| s.source == source }. 198: # This needs to be sorted by full name so that 199: # gems with the same name, but different platform 200: # are ordered consistantly 201: sort_by { |s| s.full_name }. 202: each do |spec| 203: next if spec.name == 'bundler' 204: out << spec.to_lock 205: end 206: out << "\n" 207: end 208: 209: out << "PLATFORMS\n" 210: 211: platforms.map { |p| p.to_s }.sort.each do |p| 212: out << " #{p}\n" 213: end 214: 215: out << "\n" 216: out << "DEPENDENCIES\n" 217: 218: handled = [] 219: dependencies. 220: sort_by { |d| d.name }. 221: each do |dep| 222: next if handled.include?(dep.name) 223: out << dep.to_lock 224: handled << dep.name 225: end 226: 227: out 228: end
# File lib/bundler/definition.rb, line 312 312: def converge_dependencies 313: (@dependencies + @locked_deps).each do |dep| 314: if dep.source 315: dep.source = @sources.find { |s| dep.source == s } 316: end 317: end 318: end
Remove elements from the locked specs that are expired. This will most commonly happen if the Gemfile has changed since the lockfile was last generated
# File lib/bundler/definition.rb, line 323 323: def converge_locked_specs 324: deps = [] 325: 326: # Build a list of dependencies that are the same in the Gemfile 327: # and Gemfile.lock. If the Gemfile modified a dependency, but 328: # the gem in the Gemfile.lock still satisfies it, this is fine 329: # too. 330: @dependencies.each do |dep| 331: locked_dep = @locked_deps.find { |d| dep == d } 332: 333: if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep) 334: deps << dep 335: elsif dep.source.is_a?(Source::Path) && (!locked_dep || dep.source != locked_dep.source) 336: @locked_specs.each do |s| 337: @unlock[:gems] << s.name if s.source == dep.source 338: end 339: 340: dep.source.unlock! if dep.source.respond_to?(:unlock!) 341: dep.source.specs.each { |s| @unlock[:gems] << s.name } 342: end 343: end 344: 345: converged = [] 346: @locked_specs.each do |s| 347: s.source = @sources.find { |src| s.source == src } 348: 349: # Don't add a spec to the list if its source is expired. For example, 350: # if you change a Git gem to Rubygems. 351: next if s.source.nil? || @unlock[:sources].include?(s.name) 352: # If the spec is from a path source and it doesn't exist anymore 353: # then we just unlock it. 354: 355: # Path sources have special logic 356: if s.source.instance_of?(Source::Path) 357: other = s.source.specs[s].first 358: 359: # If the spec is no longer in the path source, unlock it. This 360: # commonly happens if the version changed in the gemspec 361: next unless other 362: # If the dependencies of the path source have changed, unlock it 363: next unless s.dependencies.sort == other.dependencies.sort 364: end 365: 366: converged << s 367: end 368: 369: resolve = SpecSet.new(converged) 370: resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems]) 371: diff = @locked_specs.to_a - resolve.to_a 372: 373: # Now, we unlock any sources that do not have anymore gems pinned to it 374: @sources.each do |source| 375: next unless source.respond_to?(:unlock!) 376: 377: unless resolve.any? { |s| s.source == source } 378: source.unlock! if diff.any? { |s| s.source == source } 379: end 380: end 381: 382: resolve 383: end
# File lib/bundler/definition.rb, line 295 295: def converge_sources 296: locked_gem = @locked_sources.find { |s| Source::Rubygems === s } 297: actual_gem = @sources.find { |s| Source::Rubygems === s } 298: 299: if locked_gem && actual_gem 300: locked_gem.merge_remotes actual_gem 301: end 302: 303: @sources.map! do |source| 304: @locked_sources.find { |s| s == source } || source 305: end 306: 307: @sources.each do |source| 308: source.unlock! if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name) 309: end 310: end
# File lib/bundler/definition.rb, line 397 397: def expand_dependencies(dependencies, remote = false) 398: deps = [] 399: dependencies.each do |dep| 400: dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name) 401: dep.gem_platforms(@platforms).each do |p| 402: deps << DepProxy.new(dep, p) if remote || p == generic(Gem::Platform.local) 403: end 404: end 405: deps 406: end
# File lib/bundler/definition.rb, line 393 393: def expanded_dependencies 394: @expanded_dependencies ||= expand_dependencies(dependencies, @remote) 395: end
# File lib/bundler/definition.rb, line 385 385: def in_locked_deps?(dep, d) 386: d && dep.source == d.source 387: end
# File lib/bundler/definition.rb, line 288 288: def pretty_dep(dep, source = false) 289: msg = "#{dep.name}" 290: msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default 291: msg << " from the `#{dep.source}` source" if source && dep.source 292: msg 293: end
# File lib/bundler/definition.rb, line 415 415: def requested_dependencies 416: groups = self.groups - Bundler.settings.without 417: groups.map! { |g| g.to_sym } 418: dependencies.reject { |d| !d.should_include? || (d.groups & groups).empty? } 419: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.