bundler 0.9.26 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

@@ -1,5 +1,3 @@
1
- require 'erb'
2
-
3
1
  module Bundler
4
2
  class Environment
5
3
  attr_reader :root
@@ -9,130 +7,36 @@ module Bundler
9
7
  @definition = definition
10
8
  end
11
9
 
10
+ # TODO: Remove this method. It's used in cli.rb still
12
11
  def index
13
- @index ||= Index.build do |idx|
14
- idx.use runtime_gems
15
- idx.use Index.cached_gems
16
- end
12
+ @definition.index
17
13
  end
18
14
 
19
15
  def requested_specs
20
- @requested_specs ||= begin
21
- groups = @definition.groups - Bundler.settings.without
22
- groups.map! { |g| g.to_sym }
23
- groups.any? ? specs_for(groups) : []
24
- end
16
+ @definition.requested_specs
25
17
  end
26
18
 
27
19
  def specs
28
- @specs ||= resolve_locally || resolve_remotely
20
+ @definition.specs
29
21
  end
30
22
 
31
- private
32
-
33
- def sources
34
- @definition.sources
23
+ def dependencies
24
+ @definition.dependencies
35
25
  end
36
26
 
37
- def runtime_gems
38
- @runtime_gems ||= Index.build do |i|
39
- sources.each do |s|
40
- i.use s.local_specs if s.respond_to?(:local_specs)
41
- end
42
-
43
- i.use Index.installed_gems
44
- end
27
+ def current_dependencies
28
+ @definition.current_dependencies
45
29
  end
46
30
 
47
- def resolve(type, index)
48
- source_requirements = {}
49
- actual_dependencies.each do |dep|
50
- next unless dep.source && dep.source.respond_to?(type)
51
- source_requirements[dep.name] = dep.source.send(type)
31
+ def lock
32
+ File.open(root.join('Gemfile.lock'), 'w') do |f|
33
+ f.puts @definition.to_lock
52
34
  end
53
-
54
- # Run a resolve against the locally available gems
55
- Resolver.resolve(actual_dependencies, index, source_requirements)
56
35
  end
57
36
 
58
- def resolve_locally
59
- resolve(:local_specs, index)
37
+ def update(*gems)
38
+ # Nothing
60
39
  end
61
40
 
62
- def resolve_remotely
63
- raise NotImplementedError
64
- end
65
-
66
- def specs_for(groups)
67
- deps = dependencies.select { |d| (d.groups & groups).any? }
68
- # deps.any? ? specs.for(deps) : specs
69
- specs.for(deps)
70
- end
71
-
72
- # ==== Locking
73
-
74
- def locked?
75
- File.exist?("#{root}/Gemfile.lock")
76
- end
77
-
78
- def write_rb_lock
79
- shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__))
80
- template = File.read(File.expand_path("../templates/environment.erb", __FILE__))
81
- erb = ERB.new(template, nil, '-')
82
- Bundler.env_file.dirname.mkpath
83
- File.open(Bundler.env_file, 'w') do |f|
84
- f.puts erb.result(binding)
85
- end
86
- end
87
-
88
- def gemfile_fingerprint
89
- Digest::SHA1.hexdigest(File.read("#{root}/Gemfile"))
90
- end
91
-
92
- def specs_for_lock_file
93
- requested_specs.map do |s|
94
- hash = {
95
- :name => s.name,
96
- :load_paths => s.load_paths
97
- }
98
- if s.respond_to?(:relative_loaded_from) && s.relative_loaded_from
99
- hash[:virtual_spec] = s.to_ruby
100
- end
101
- hash[:loaded_from] = s.loaded_from.to_s
102
- hash
103
- end
104
- end
105
-
106
- def autorequires_for_groups(*groups)
107
- groups.map! { |g| g.to_sym }
108
- autorequires = Hash.new { |h,k| h[k] = [] }
109
-
110
- ordered_deps = []
111
- specs = groups.any? ? specs_for(groups) : requested_specs
112
- specs.each do |g|
113
- dep = @definition.dependencies.find{|d| d.name == g.name }
114
- ordered_deps << dep if dep && !ordered_deps.include?(dep)
115
- end
116
-
117
- ordered_deps.each do |dep|
118
- dep.groups.each do |group|
119
- # If there is no autorequire, then rescue from
120
- # autorequiring the gems name
121
- if dep.autorequire
122
- dep.autorequire.each do |file|
123
- autorequires[group] << [file, true]
124
- end
125
- else
126
- autorequires[group] << [dep.name, false]
127
- end
128
- end
129
- end
130
-
131
- if groups.empty?
132
- autorequires
133
- else
134
- groups.inject({}) { |h,g| h[g] = autorequires[g]; h }
135
- end
136
- end
137
41
  end
138
42
  end
@@ -0,0 +1,130 @@
1
+ module Bundler
2
+ class Graph
3
+
4
+ USER_OPTIONS = {:style => 'filled, bold', :fillcolor => '#cccccc'}.freeze
5
+
6
+ def initialize(env)
7
+ @env = env
8
+ end
9
+
10
+ def nodes
11
+ populate
12
+ @nodes
13
+ end
14
+
15
+ def groups
16
+ populate
17
+ @groups
18
+ end
19
+
20
+ def viz(output_file, show_gem_versions = false, show_dependency_requirements = false)
21
+ require 'graphviz'
22
+ populate
23
+
24
+ graph_viz = GraphViz::new('Gemfile', {:concentrate => true, :dpi => 65 } )
25
+ graph_viz.edge[:fontname] = graph_viz.node[:fontname] = 'Arial, Helvetica, SansSerif'
26
+ graph_viz.edge[:fontsize] = 12
27
+
28
+ viz_nodes = {}
29
+
30
+ # populate all of the nodes
31
+ nodes.each do |name, node|
32
+ label = name.dup
33
+ label << "\n#{node.version}" if show_gem_versions
34
+ options = { :label => label }
35
+ options.merge!( USER_OPTIONS ) if node.is_user
36
+ viz_nodes[name] = graph_viz.add_node( name, options )
37
+ end
38
+
39
+ group_nodes = {}
40
+ @groups.each do |name, dependencies|
41
+ group_nodes[name] = graph_viz.add_node(name.to_s, { :shape => 'folder', :fontsize => 16 }.merge(USER_OPTIONS))
42
+ dependencies.each do |dependency|
43
+ options = { :weight => 2 }
44
+ if show_dependency_requirements && (dependency.requirement.to_s != ">= 0")
45
+ options[:label] = dependency.requirement.to_s
46
+ end
47
+ graph_viz.add_edge( group_nodes[name], viz_nodes[dependency.name], options )
48
+ end
49
+ end
50
+
51
+ @groups.keys.select { |group| group != :default }.each do |group|
52
+ graph_viz.add_edge( group_nodes[group], group_nodes[:default], { :weight => 2 } )
53
+ end
54
+
55
+ viz_nodes.each do |name, node|
56
+ nodes[name].dependencies.each do |dependency|
57
+ options = { }
58
+ if nodes[dependency.name].is_user
59
+ options[:constraint] = false
60
+ end
61
+ if show_dependency_requirements && (dependency.requirement.to_s != ">= 0")
62
+ options[:label] = dependency.requirement.to_s
63
+ end
64
+
65
+ graph_viz.add_edge( node, viz_nodes[dependency.name], options )
66
+ end
67
+ end
68
+
69
+ graph_viz.output( :png => output_file )
70
+ end
71
+
72
+ private
73
+
74
+ def populate
75
+ return if @populated
76
+
77
+ # hash of name => GraphNode
78
+ @nodes = {}
79
+ @groups = {}
80
+
81
+ # Populate @nodes
82
+ @env.specs.each { |spec| @nodes[spec.name] = GraphNode.new(spec.name, spec.version) }
83
+
84
+ # For gems in Gemfile, add details
85
+ @env.current_dependencies.each do |dependency|
86
+ node = @nodes[dependency.name]
87
+ node.is_user = true
88
+
89
+ dependency.groups.each do |group|
90
+ if @groups.has_key? group
91
+ group = @groups[group]
92
+ else
93
+ group = @groups[group] = []
94
+ end
95
+ group << dependency
96
+ end
97
+ end
98
+
99
+ # walk though a final time and add edges
100
+ @env.specs.each do |spec|
101
+
102
+ from = @nodes[spec.name]
103
+ spec.runtime_dependencies.each do |dependency|
104
+ from.dependencies << dependency
105
+ end
106
+
107
+ end
108
+
109
+ @nodes.freeze
110
+ @groups.freeze
111
+ @populated = true
112
+ end
113
+
114
+ end
115
+
116
+ # Add version info
117
+ class GraphNode
118
+
119
+ def initialize(name, version)
120
+ @name = name
121
+ @version = version
122
+ @is_user = false
123
+ @dependencies = []
124
+ end
125
+
126
+ attr_reader :name, :dependencies, :version
127
+ attr_accessor :is_user
128
+
129
+ end
130
+ end
@@ -6,43 +6,6 @@ module Bundler
6
6
  i
7
7
  end
8
8
 
9
- def self.installed_gems
10
- build do |idx|
11
- idx.use bundler_gems
12
- idx.use system_gems
13
- end
14
- end
15
-
16
- def self.bundler_gems
17
- Source::BundlerGems.new.specs
18
- end
19
-
20
- def self.system_gems
21
- Source::SystemGems.new.specs
22
- end
23
-
24
- def self.cached_gems
25
- build do |idx|
26
- idx.use application_cached_gems
27
- idx.use system_cached_gems
28
- end
29
- end
30
-
31
- def self.application_cached_gems
32
- path = "#{Bundler.root}/vendor/cache"
33
- if File.directory?(path)
34
- from_cached_specs(path)
35
- end
36
- end
37
-
38
- def self.system_cached_gems
39
- from_cached_specs("#{Bundler.bundle_path}/cache")
40
- end
41
-
42
- def self.from_cached_specs(path)
43
- Source::GemCache.new("path" => path).specs
44
- end
45
-
46
9
  def initialize
47
10
  @cache = {}
48
11
  @specs = Hash.new { |h,k| h[k] = [] }
@@ -62,12 +25,26 @@ module Bundler
62
25
 
63
26
  def search(query)
64
27
  case query
65
- when Gem::Specification, RemoteSpecification then search_by_spec(query)
28
+ when Gem::Specification, RemoteSpecification, LazySpecification then search_by_spec(query)
66
29
  when String then @specs[query]
67
30
  else search_by_dependency(query)
68
31
  end
69
32
  end
70
33
 
34
+ def search_for_all_platforms(dependency)
35
+ specs = @specs[dependency.name]
36
+
37
+ wants_prerelease = dependency.requirement.prerelease?
38
+ only_prerelease = specs.all? {|spec| spec.version.prerelease? }
39
+ found = specs.select { |spec| dependency =~ spec }
40
+
41
+ unless wants_prerelease || only_prerelease
42
+ found.reject! { |spec| spec.version.prerelease? }
43
+ end
44
+
45
+ found.sort_by {|s| [s.version, s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s] }
46
+ end
47
+
71
48
  def sources
72
49
  @specs.values.map do |specs|
73
50
  specs.map{|s| s.source.class }
@@ -105,7 +82,9 @@ module Bundler
105
82
  private
106
83
 
107
84
  def search_by_spec(spec)
108
- @specs[spec.name].select { |s| s.version == spec.version && s.platform == spec.platform }
85
+ @specs[spec.name].select do |s|
86
+ s.version == spec.version && Gem::Platform.new(s.platform) == Gem::Platform.new(spec.platform)
87
+ end
109
88
  end
110
89
 
111
90
  def search_by_dependency(dependency)
@@ -114,7 +93,7 @@ module Bundler
114
93
 
115
94
  wants_prerelease = dependency.requirement.prerelease?
116
95
  only_prerelease = specs.all? {|spec| spec.version.prerelease? }
117
- found = specs.select { |spec| dependency =~ spec }
96
+ found = specs.select { |spec| dependency =~ spec && Gem::Platform.match(spec.platform) }
118
97
 
119
98
  unless wants_prerelease || only_prerelease
120
99
  found.reject! { |spec| spec.version.prerelease? }
@@ -123,6 +102,5 @@ module Bundler
123
102
  found.sort_by {|s| [s.version, s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s] }
124
103
  end
125
104
  end
126
-
127
105
  end
128
106
  end
@@ -2,16 +2,22 @@ require 'rubygems/dependency_installer'
2
2
 
3
3
  module Bundler
4
4
  class Installer < Environment
5
- def self.install(root, definition, options)
6
- new(root, definition).run(options)
5
+ def self.install(root, definition, options = {})
6
+ installer = new(root, definition)
7
+ installer.run(options)
8
+ installer
7
9
  end
8
10
 
9
11
  def run(options)
10
- if actual_dependencies.empty?
12
+ if dependencies.empty?
11
13
  Bundler.ui.warn "The Gemfile specifies no dependencies"
12
14
  return
13
15
  end
14
16
 
17
+ # Since we are installing, we can resolve the definition
18
+ # using remote specs
19
+ @definition.resolve_remotely!
20
+
15
21
  # Ensure that BUNDLE_PATH exists
16
22
  FileUtils.mkdir_p(Bundler.bundle_path)
17
23
 
@@ -21,72 +27,30 @@ module Bundler
21
27
  specs.each do |spec|
22
28
  spec.source.fetch(spec) if spec.source.respond_to?(:fetch)
23
29
 
24
- unless requested_specs.include?(spec)
25
- Bundler.ui.debug " * Not in requested group; skipping."
26
- next
27
- end
30
+ # unless requested_specs.include?(spec)
31
+ # Bundler.ui.debug " * Not in requested group; skipping."
32
+ # next
33
+ # end
28
34
 
29
- if [Source::Rubygems, Source::GemCache].include?(spec.source.class)
30
- Bundler.ui.info "Installing #{spec.name} (#{spec.version}) from #{spec.source} "
31
- else
32
- Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{spec.source} "
33
- end
34
35
  spec.source.install(spec)
35
36
  Bundler.ui.info ""
37
+ generate_bundler_executable_stubs(spec)
38
+ FileUtils.rm_rf(Bundler.tmp)
36
39
  end
37
40
 
38
- if locked?
39
- write_rb_lock
40
- end
41
- end
42
-
43
- def dependencies
44
- @definition.dependencies
45
- end
46
-
47
- def actual_dependencies
48
- @definition.actual_dependencies
41
+ lock
49
42
  end
50
43
 
51
44
  private
52
45
 
53
- def resolve_locally
54
- # Return unless all the dependencies have = version requirements
55
- return if actual_dependencies.any? { |d| ambiguous?(d) }
56
-
57
- specs = super
58
-
59
- # Simple logic for now. Can improve later.
60
- specs.length == actual_dependencies.length && specs
61
- rescue GemNotFound, PathError => e
62
- nil
63
- end
64
-
65
- def resolve_remotely
66
- resolve(:specs, remote_index)
67
- end
68
-
69
- def ambiguous?(dep)
70
- dep.requirement.requirements.any? { |op,_| op != '=' }
71
- end
72
-
73
- def remote_index
74
- @remote_index ||= Index.build do |idx|
75
- rubygems, other = sources.partition { |s| Source::Rubygems === s }
76
-
77
- other.each do |source|
78
- Bundler.ui.debug "Source: Processing index"
79
- idx.use source.specs
80
- end
81
-
82
- idx.use Index.installed_gems
83
- idx.use Index.cached_gems
84
-
85
- rubygems.each do |source|
86
- Bundler.ui.debug "Source: Processing index"
87
- idx.use source.specs
46
+ def generate_bundler_executable_stubs(spec)
47
+ spec.executables.each do |executable|
48
+ next if executable == "bundle"
49
+ File.open "#{Bundler.bin_path}/#{executable}", 'w', 0755 do |f|
50
+ f.puts File.read(File.expand_path('../templates/Executable', __FILE__))
88
51
  end
89
52
  end
90
53
  end
54
+
91
55
  end
92
56
  end