Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 243 lines (199 sloc) 6.919 kb
d19c577 Jeremy Kemper Locked environment checks for Gemfile changes
jeremy authored
1 require "digest/sha1"
8835be6 Print an error if the Gemfile changed after the lock
Yehuda Katz authored
2
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
3 module Bundler
4 class Runtime < Environment
f7bfdde Actually disable system gems in .bundle/environment.rb
Carlhuda authored
5 include SharedHelpers
6
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
7 def setup(*groups)
8 # Has to happen first
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
9 clean_load_path
10
11 specs = specs_for(*groups)
12
6d36909 Cripple rubygems with a smarter #gem
Carl Lerche authored
13 cripple_rubygems(specs)
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
14
15 # Activate the specs
6d36909 Cripple rubygems with a smarter #gem
Carl Lerche authored
16 specs.each do |spec|
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
17 Gem.loaded_specs[spec.name] = spec
18 $LOAD_PATH.unshift(*spec.load_paths)
19 end
20 self
21 end
22
23 def require(*groups)
ca6cc3b Jeremy Kemper Merge branch 'master' of git://github.com/carlhuda/bundler into carlhuda
jeremy authored
24 groups = [:default] if groups.empty?
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
25 autorequires = autorequires_for_groups(*groups)
26 groups.each do |group|
27 (autorequires[group] || []).each do |path|
28 Kernel.require(path)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
29 end
30 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
31 end
32
33 def dependencies
6c5a67d Andy Delcambre Dump full details into Gemfile.lock
adelcambre authored
34 @definition.dependencies
35 end
36
37 def actual_dependencies
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
38 @definition.actual_dependencies
39 end
40
4ebd4da Fix a bug with git repos and bundle lock breaking the install
Carl Lerche authored
41 def lock
42 Bundler.ui.info("The bundle is already locked, relocking.") if locked?
43 sources.each { |s| s.lock if s.respond_to?(:lock) }
44 FileUtils.mkdir_p("#{root}/.bundle")
45 write_yml_lock
46 write_rb_lock
47 Bundler.ui.info("The bundle is now locked. Use `bundle show` to list the gems in the environment.")
48 end
49
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
50 def locked?
89994a0 Jeremy Kemper Locked checks should always include both Gemfile.lock and the environmen...
jeremy authored
51 File.exist?("#{root}/Gemfile.lock") || File.exist?("#{root}/.bundle/environment.rb")
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
52 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
53
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
54 def dependencies_for(*groups)
55 if groups.empty?
56 dependencies
57 else
58 dependencies.select { |d| (groups & d.groups).any? }
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
59 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
60 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
61
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
62 def specs_for(*groups)
63 if groups.empty?
64 specs
65 else
66 Resolver.resolve(dependencies_for(*groups), index)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
67 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
68 end
69
70 def specs
71 @specs ||= begin
72 source_requirements = {}
6c5a67d Andy Delcambre Dump full details into Gemfile.lock
adelcambre authored
73 actual_dependencies.each do |dep|
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
74 next unless dep.source && dep.source.respond_to?(:local_specs)
75 source_requirements[dep.name] = dep.source.local_specs
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
76 end
77
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
78 Resolver.resolve(@definition.actual_dependencies, index, source_requirements)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
79 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
80 end
81
82 alias gems specs
83
84 def index
85 @definition.local_index
86 end
87
88 def pack
89 pack_path = "#{root}/vendor/cache/"
90 FileUtils.mkdir_p(pack_path)
91
92 Bundler.ui.info "Copying .gem files into vendor/cache"
93 specs.each do |spec|
94 next unless spec.source.is_a?(Source::SystemGems) || spec.source.is_a?(Source::Rubygems)
95 possibilities = Gem.path.map { |p| "#{p}/cache/#{spec.full_name}.gem" }
96 cached_path = possibilities.find { |p| File.exist? p }
97 Bundler.ui.info " * #{File.basename(cached_path)}"
98 next if File.expand_path(File.dirname(cached_path)) == File.expand_path(pack_path)
99 FileUtils.cp(cached_path, pack_path)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
100 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
101 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
102
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
103 private
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
104
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
105 def sources
106 @definition.sources
107 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
108
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
109 def load_paths
110 specs.map { |s| s.load_paths }.flatten
111 end
112
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
113 def write_rb_lock
f7bfdde Actually disable system gems in .bundle/environment.rb
Carlhuda authored
114 shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__))
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
115 template = File.read(File.expand_path("../templates/environment.erb", __FILE__))
116 erb = ERB.new(template, nil, '-')
117 File.open("#{root}/.bundle/environment.rb", 'w') do |f|
118 f.puts erb.result(binding)
119 end
120 end
121
122 def write_yml_lock
123 yml = details.to_yaml
124 File.open("#{root}/Gemfile.lock", 'w') do |f|
125 f.puts yml
126 end
127 end
128
129 def details
130 details = {}
131 details["hash"] = gemfile_fingerprint
132 details["sources"] = sources.map { |s| { s.class.name.split("::").last => s.options} }
133
134 details["specs"] = specs.map do |s|
135 options = {"version" => s.version.to_s}
136 options["source"] = sources.index(s.source) if sources.include?(s.source)
137 { s.name => options }
138 end
139
6c5a67d Andy Delcambre Dump full details into Gemfile.lock
adelcambre authored
140 details["dependencies"] = @definition.dependencies.inject({}) do |h,d|
141 h.merge!({d.name => {"version" => d.version_requirements.to_s,
142 "group" => d.groups,
143 "require" => d.autorequire}})
144 end
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
145 details
146 end
147
148 def gemfile_fingerprint
149 Digest::SHA1.hexdigest(File.read("#{root}/Gemfile"))
150 end
151
152 def autorequires_for_groups(*groups)
153 autorequires = Hash.new { |h,k| h[k] = [] }
154 @definition.dependencies.each do |dep|
155 dep.groups.each do |group|
156 autorequires[group].concat dep.autorequire
157 end
158 end
159
160 if groups.empty?
161 autorequires
162 else
163 groups.inject({}) { |h,g| h[g] = autorequires[g]; h }
164 end
165 end
166
167 def clean_load_path
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
168 # handle 1.9 where system gems are always on the load path
169 if defined?(::Gem)
170 me = File.expand_path("../../", __FILE__)
171 $LOAD_PATH.reject! do |p|
172 p != File.dirname(__FILE__) &&
173 Gem.path.any? { |gp| p.include?(gp) }
174 end
175 $LOAD_PATH.unshift me
176 $LOAD_PATH.uniq!
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
177 end
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
178 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
179
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
180 def cripple_rubygems(specs)
181 reverse_rubygems_kernel_mixin
182
183 executables = specs.map { |s| s.executables }.flatten
6d36909 Cripple rubygems with a smarter #gem
Carl Lerche authored
184
185 ::Kernel.send(:define_method, :gem) do |dep, *reqs|
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
186 if executables.include? File.basename(caller.first.split(':').first)
187 return
188 end
6d36909 Cripple rubygems with a smarter #gem
Carl Lerche authored
189 opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
190
191 unless dep.respond_to?(:name) && dep.respond_to?(:version_requirements)
192 dep = Gem::Dependency.new(dep, reqs)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
193 end
6d36909 Cripple rubygems with a smarter #gem
Carl Lerche authored
194
195 spec = specs.find { |s| s.name == dep.name }
196
197 if spec.nil?
198 e = Gem::LoadError.new "#{dep} is not part of the bundle. Add it to Gemfile."
199 e.name = dep.name
200 e.version_requirement = dep.version_requirements
201 raise e
202 elsif dep !~ spec
203 e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
204 "Make sure all dependencies are added to Gemfile."
205 e.name = dep.name
206 e.version_requirement = dep.version_requirements
207 raise e
208 end
209
210 true
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
211 end
212
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
213 # === Following hacks are to improve on the generated bin wrappers ===
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
214
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
215 # Yeah, talk about a hack
216 source_index_class = (class << Gem::SourceIndex ; self ; end)
217 source_index_class.send(:define_method, :from_gems_in) do |*args|
218 source_index = Gem::SourceIndex.new
219 source_index.add_specs *specs
220 source_index
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
221 end
222
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
223 # OMG more hacks
224 gem_class = (class << Gem ; self ; end)
225 gem_class.send(:define_method, :bin_path) do |name, *args|
226 exec_name, *reqs = args
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
227
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
228 spec = nil
d19c577 Jeremy Kemper Locked environment checks for Gemfile changes
jeremy authored
229
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
230 if exec_name
231 spec = specs.find { |s| s.executables.include?(exec_name) }
232 spec or raise Gem::Exception, "can't find executable #{exec_name}"
233 else
234 spec = specs.find { |s| s.name == name }
235 exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
ca6cc3b Jeremy Kemper Merge branch 'master' of git://github.com/carlhuda/bundler into carlhuda
jeremy authored
236 end
237
2d05242 Handle rubygems executable wrappers better
Carl Lerche authored
238 File.join(spec.full_gem_path, spec.bindir, exec_name)
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
239 end
e993e6f Persist spec groups to the lockfile
Carl Lerche authored
240 end
c0f8641 Persist spec groups to the lockfile
Carl Lerche authored
241 end
ca6cc3b Jeremy Kemper Merge branch 'master' of git://github.com/carlhuda/bundler into carlhuda
jeremy authored
242 end
Something went wrong with that request. Please try again.