bundler08 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Engine Yard
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,284 @@
1
+ ## Bundler : A gem to bundle gems
2
+
3
+ Github: http://github.com/wycats/bundler
4
+ Mailing list: http://groups.google.com/group/ruby-bundler
5
+ IRC: #carlhuda on freenode
6
+
7
+ ## Intro
8
+
9
+ Bundler is a tool that manages gem dependencies for your ruby application. It
10
+ takes a gem manifest file and is able to fetch, download, and install the gems
11
+ and all child dependencies specified in this manifest. It can manage any update
12
+ to the gem manifest file and update the bundled gems accordingly. It also lets
13
+ you run any ruby code in context of the bundled gem environment.
14
+
15
+ ## Installation
16
+
17
+ Bundler has no dependencies. Just clone the git repository and install the gem
18
+ with the following rake task:
19
+
20
+ rake install
21
+
22
+ You can also install the gem with
23
+
24
+ gem install bundler
25
+
26
+ ## Usage
27
+
28
+ Bundler requires a gem manifest file to be created. This should be a file named
29
+ `Gemfile` located in the root directory of your application. After the manifest
30
+ has been created, in your shell, cd into your application's directory and run
31
+ `gem bundle`. This will start the bundling process.
32
+
33
+ ### Manifest file
34
+
35
+ This is where you specify all of your application's dependencies. By default
36
+ this should be in a file named `Gemfile` located in your application's root
37
+ directory. The following is an example of a potential `Gemfile`. For more
38
+ information, please refer to Bundler::ManifestBuilder.
39
+
40
+ # Specify a dependency on rails. When the bundler downloads gems,
41
+ # it will download rails as well as all of rails' dependencies (such as
42
+ # activerecord, actionpack, etc...)
43
+ #
44
+ # At least one dependency must be specified
45
+ gem "rails"
46
+
47
+ # Specify a dependency on rack v.1.0.0. The version is optional. If present,
48
+ # it can be specified the same way as with rubygems' #gem method.
49
+ gem "rack", "1.0.0"
50
+
51
+ # Specify a dependency rspec, but only require that gem in the "testing"
52
+ # environment. :except is also a valid option to specify environment
53
+ # restrictions.
54
+ gem "rspec", :only => :testing
55
+
56
+ # Specify a dependency, but specify that it is already present and expanded
57
+ # at vendor/rspec. Bundler will treat rspec as though it was the rspec gem
58
+ # for the purpose of gem resolution: if another gem depends on a version
59
+ # of rspec satisfied by "1.1.6", it will be used.
60
+ #
61
+ # If a gemspec is found in the directory, it will be used to specify load
62
+ # paths and supply additional dependencies.
63
+ #
64
+ # Bundler will also recursively search for *.gemspec, and assume that
65
+ # gemspecs it finds represent gems that are rooted in the same directory
66
+ # the gemspec is found in.
67
+ gem "rspec", "1.1.6", :vendored_at => "vendor/rspec"
68
+
69
+ # You can also control what will happen when you run Bundler.require_env
70
+ # by using the :require_as option, as per the next two examples.
71
+
72
+ # Don't auto-require this gem.
73
+ gem "rspec-rails", "1.2.9", :require_as => nil
74
+
75
+ # Require something other than the default.
76
+ gem "yajl-ruby", "0.6.7", :require_as => "yajl/json_gem"
77
+
78
+ # Works exactly like :vendored_at, but first downloads the repo from
79
+ # git and handles stashing the files for you. As with :vendored_at,
80
+ # Bundler will automatically use *.gemspec files in the root or anywhere
81
+ # in the repository.
82
+ gem "rails", "3.0.pre", :git => "git://github.com/rails/rails.git"
83
+
84
+ # Add http://gems.github.com as a source that the bundler will use
85
+ # to find gems listed in the manifest. By default,
86
+ # http://gems.rubyforge.org is already added to the list.
87
+ #
88
+ # This is an optional setting.
89
+ source "http://gems.github.com"
90
+
91
+ # Specify where the bundled gems should be stashed. This directory will
92
+ # be a gem repository where all gems are downloaded to and installed to.
93
+ #
94
+ # This is an optional setting.
95
+ # The default is: vendor/gems
96
+ bundle_path "my/bundled/gems"
97
+
98
+ # Specify where gem executables should be copied to.
99
+ #
100
+ # This is an optional setting.
101
+ # The default is: bin
102
+ bin_path "my/executables"
103
+
104
+ # Specify that rubygems should be completely disabled. This means that it
105
+ # will be impossible to require it and that available gems will be
106
+ # limited exclusively to gems that have been bundled.
107
+ #
108
+ # The default is to automatically require rubygems. There is also a
109
+ # `disable_system_gems` option that will limit available rubygems to
110
+ # the ones that have been bundled.
111
+ disable_rubygems
112
+
113
+ ### Gem Resolution
114
+
115
+ One of the most important things that the bundler does is do a
116
+ dependency resolution on the full list of gems that you specify, all
117
+ at once. This differs from the one-at-a-time dependency resolution that
118
+ Rubygems does, which can result in the following problem:
119
+
120
+ # On my system:
121
+ # activesupport 3.0.pre
122
+ # activesupport 2.3.4
123
+ # activemerchant 1.4.2
124
+ # rails 2.3.4
125
+ #
126
+ # activemerchant 1.4.2 depends on activesupport >= 2.3.2
127
+
128
+ gem "activemerchant", "1.4.2"
129
+ # results in activating activemerchant, as well as
130
+ # activesupport 3.0.pre, since it is >= 2.3.2
131
+
132
+ gem "rails", "2.3.4"
133
+ # results in:
134
+ # can't activate activesupport (= 2.3.4, runtime)
135
+ # for ["rails-2.3.4"], already activated
136
+ # activesupport-3.0.pre for ["activemerchant-1.4.2"]
137
+
138
+ This is because activemerchant has a broader dependency, which results
139
+ in the activation of a version of activesupport that does not satisfy
140
+ a more narrow dependency.
141
+
142
+ Bundler solves this problem by evaluating all dependencies at once,
143
+ so it can detect that all gems *together* require activesupport "2.3.4".
144
+
145
+ ### Running Bundler
146
+
147
+ Once a manifest file has been created, the only thing that needs to be done
148
+ is to run the `gem bundle` command anywhere in your application. The script
149
+ will load the manifest file, resolve all the dependencies, download all
150
+ needed gems, and install them into the specified directory.
151
+
152
+ Every time an update is made to the manifest file, run `gem bundle` again to
153
+ get the changes installed. This will only check the remote sources if your
154
+ currently installed gems do not satisfy the `Gemfile`. If you want to force
155
+ checking for updates on the remote sources, use the `--update` option.
156
+
157
+ ### Remote deploys
158
+
159
+ When you run `gem bundle`, the following steps occur:
160
+
161
+ 1. Gemfile is read in
162
+ 2. The gems specified in the Gemfile are resolved against the gems
163
+ already in your bundle. If the dependencies resolve, skip to step 5.
164
+ 3. If the dependencies in your Gemfile cannot be fully resolved
165
+ against the gems already in the bundle, the metadata for each
166
+ source is fetched.
167
+ 4. The gems in the Gemfile are resolved against the full list of
168
+ available gems in all sources, and the resulting gems are downloaded
169
+ 5. Each gem that has been downloaded but not yet expanded is expanded
170
+ into the local directory. This expansion process also installs
171
+ native gems.
172
+
173
+ As you can see, if you run gem bundle twice in a row, it will do nothing the
174
+ second time, since the gems obviously resolve against the installed gems,
175
+ and they are all expanded.
176
+
177
+ This also means that if you run `gem bundle`, and .gitignore the expanded
178
+ copies, leaving only the cached `.gem` files, you can run `gem bundle` again
179
+ on the remote system, and it will only expand out the gems (but not
180
+ resolve or download `.gem` files). This also means that native gems
181
+ will be compiled for the target platform without requiring that the
182
+ `.gem` file itself be downloaded from a remote gem server.
183
+
184
+ Assuming a Rails app with Bundler's standard setup, add something like
185
+ this to your top-level `.gitignore` to only keep the cache:
186
+
187
+ bin/*
188
+ vendor/gems/*
189
+ !vendor/gems/cache/
190
+
191
+ Make sure that you explicitly `git add vendor/gems/cache` before you commit.
192
+
193
+ ### Gems with compile-time options
194
+
195
+ Some gems require you to pass compile-time options to the gem install command.
196
+ For instance, to install mysql, you might do:
197
+
198
+ gem install mysql -- --with-mysql-config=/usr/local/lib/mysql
199
+
200
+ You can pass these options to the bundler by creating a YAML file containing
201
+ the options in question:
202
+
203
+ mysql:
204
+ mysql-config: /usr/local/lib/mysql
205
+
206
+ You can then point the bundler at the file:
207
+
208
+ gem bundle --build-options build_options.yml
209
+
210
+ In general, you will want to keep the build options YAML out of version control,
211
+ and provide the appropriate options for the system in question.
212
+
213
+ ### Running your application
214
+
215
+ The easiest way to run your application is to start it with an executable
216
+ copied to the specified bin directory (by default, simply bin). For example,
217
+ if the application in question is a rack app, start it with `bin/rackup`.
218
+ This will automatically set the gem environment correctly.
219
+
220
+ Another way to run arbitrary ruby code in context of the bundled gems is to
221
+ run it with the `gem exec` command. For example:
222
+
223
+ gem exec ruby my_ruby_script.rb
224
+
225
+ You can use `gem exec bash` to enter a shell that will run all binaries in
226
+ the current context.
227
+
228
+ Yet another way is to manually require the environment file first. This is
229
+ located in `[bundle_path]/gems/environment.rb`. For example:
230
+
231
+ ruby -r vendor/gems/environment.rb my_ruby_script.rb
232
+
233
+ ### Using Bundler with Rails today
234
+
235
+ It should be possible to use Bundler with Rails today. Here are the steps
236
+ to follow.
237
+
238
+ * In your rails app, create a Gemfile and specify the gems that your
239
+ application depends on. Make sure to specify rails as well:
240
+
241
+ gem "rails", "2.1.2"
242
+ gem "will_paginate"
243
+
244
+ # Optionally, you can disable system gems all together and only
245
+ # use bundled gems.
246
+ disable_system_gems
247
+
248
+ * Run `gem bundle`
249
+
250
+ * You can now use rails if you prepend `gem exec` to every call to `script/*`
251
+ but that isn't fun.
252
+
253
+ * At the top of `config/preinitializer.rb`, add the following line:
254
+
255
+ require "#{RAILS_ROOT}/vendor/gems/environment"
256
+
257
+ In theory, this should be enough to get going.
258
+
259
+ ## To require rubygems or not
260
+
261
+ Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides
262
+ enough features so that this isn't necessary. However, there are a number of gems
263
+ that require specific rubygems features.
264
+
265
+ If the `disable_rubygems` option is used, Bundler will stub out the most common
266
+ of these features, but it is possible that things will not go as intended quite
267
+ yet. So, if you are brave, try your code without rubygems at runtime.
268
+
269
+ This is different from the `disable_system_gems` option, which uses the rubygems
270
+ library, but prevents system gems from being loaded; only gems that are bundled
271
+ will be available to your application. This option guarantees that dependencies
272
+ of your application will be available to a remote system.
273
+
274
+ ## Known Issues
275
+
276
+ * When a gem points to a git repository, the git repository will be cloned
277
+ every time Bundler does a gem dependency resolve.
278
+
279
+ ## Reporting bugs
280
+
281
+ Please report all bugs on the github issue tracker for the project located
282
+ at:
283
+
284
+ http://github.com/wycats/bundler/issues/
data/Rakefile ADDED
@@ -0,0 +1,81 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
3
+ require 'rubygems/specification'
4
+ require 'bundler08'
5
+ require 'date'
6
+
7
+ spec = Gem::Specification.new do |s|
8
+ s.name = "bundler08"
9
+ s.version = Bundler::VERSION
10
+ s.authors = ["Yehuda Katz", "Carl Lerche"]
11
+ s.email = ["wycats@gmail.com", "clerche@engineyard.com"]
12
+ s.homepage = "http://github.com/wycats/bundler"
13
+ s.description = s.summary = "An easy way to vendor gem dependencies"
14
+
15
+ s.platform = Gem::Platform::RUBY
16
+ s.has_rdoc = true
17
+ s.extra_rdoc_files = ["README.markdown", "LICENSE"]
18
+
19
+ s.required_rubygems_version = ">= 1.3.5"
20
+
21
+ s.require_path = 'lib'
22
+ s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("lib/**/*")
23
+ end
24
+
25
+ task :default => :spec
26
+
27
+ begin
28
+ require 'spec/rake/spectask'
29
+ rescue LoadError
30
+ task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
31
+ else
32
+ desc "Run specs"
33
+ Spec::Rake::SpecTask.new do |t|
34
+ t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb']
35
+ t.spec_opts = %w(-fs --color)
36
+ t.warning = true
37
+ end
38
+ end
39
+
40
+ namespace :spec do
41
+ file "tmp/rg_deps" do
42
+ repo = File.dirname(__FILE__) + '/tmp/rg_deps'
43
+ FileUtils.mkdir_p(repo)
44
+ p repo
45
+ ENV['GEM_HOME'], ENV['GEM_PATH'] = repo, repo
46
+ system "gem install builder --no-rdoc --no-ri"
47
+ end
48
+
49
+ desc "Do all setup needed to run the specs"
50
+ task :setup => "tmp/rg_deps"
51
+
52
+ desc "Mount a ramdisk at ./tmp for faster specs"
53
+ task :ramdisk do
54
+ sh 'diskutil erasevolume HFS+ "tmpbundler" `hdiutil attach -nomount ram://116543`'
55
+ File.symlink "/Volumes/tmpbundler", File.expand_path('../tmp', __FILE__)
56
+ end
57
+ end
58
+
59
+ spec_file = "#{spec.name}.gemspec"
60
+ desc "Create #{spec_file}"
61
+ file spec_file => "Rakefile" do
62
+ File.open(spec_file, "w") do |file|
63
+ file.puts spec.to_ruby
64
+ end
65
+ end
66
+
67
+ begin
68
+ require 'rake/gempackagetask'
69
+ rescue LoadError
70
+ task(:gem) { $stderr.puts '`gem install rake` to package gems' }
71
+ else
72
+ Rake::GemPackageTask.new(spec) do |pkg|
73
+ pkg.gem_spec = spec
74
+ end
75
+ task :gem => spec_file
76
+ end
77
+
78
+ desc "install the gem locally"
79
+ task :install => :package do
80
+ sh %{gem install pkg/#{spec.name}-#{spec.version}}
81
+ end
data/lib/bundler08.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'pathname'
2
+ require 'logger'
3
+ require 'set'
4
+ require 'erb'
5
+ # Required elements of rubygems
6
+ require "rubygems/remote_fetcher"
7
+ require "rubygems/installer"
8
+
9
+ require "bundler08/gem_bundle"
10
+ require "bundler08/source"
11
+ require "bundler08/finder"
12
+ require "bundler08/gem_ext"
13
+ require "bundler08/resolver"
14
+ require "bundler08/environment"
15
+ require "bundler08/dsl"
16
+ require "bundler08/cli"
17
+ require "bundler08/bundle"
18
+ require "bundler08/dependency"
19
+ require "bundler08/remote_specification"
20
+
21
+ module Bundler
22
+ VERSION = "0.8.2"
23
+
24
+ class << self
25
+ attr_writer :logger, :mode
26
+
27
+ def logger
28
+ @logger ||= begin
29
+ logger = Logger.new(STDOUT, Logger::INFO)
30
+ logger.formatter = proc {|_,_,_,msg| "#{msg}\n" }
31
+ logger
32
+ end
33
+ end
34
+
35
+ def local?
36
+ @mode == :local
37
+ end
38
+
39
+ def writable?
40
+ @mode != :readonly
41
+ end
42
+
43
+ def remote?
44
+ @mode == :readwrite
45
+ end
46
+ end
47
+
48
+ self.mode = :readonly
49
+ end
@@ -0,0 +1,314 @@
1
+ module Bundler
2
+ class InvalidRepository < StandardError ; end
3
+
4
+ class Bundle
5
+ attr_reader :gemfile, :environment
6
+
7
+ def self.load(gemfile = nil)
8
+ gemfile = Pathname.new(gemfile || default_gemfile).expand_path
9
+
10
+ unless gemfile.file?
11
+ raise ManifestFileNotFound, "Manifest file not found: #{gemfile.to_s.inspect}"
12
+ end
13
+
14
+ new(gemfile)
15
+ end
16
+
17
+ def self.default_gemfile
18
+ current = Pathname.new(Dir.pwd)
19
+
20
+ until current.root?
21
+ filename = current.join("Gemfile")
22
+ return filename if filename.exist?
23
+ current = current.parent
24
+ end
25
+
26
+ raise DefaultManifestNotFound
27
+ end
28
+
29
+ # TODO: passing in the filename is not good
30
+ def initialize(gemfile)
31
+ @gemfile = gemfile
32
+ @environment = Environment.new(self)
33
+ Dsl.evaluate(gemfile, self, @environment)
34
+
35
+ # path = env.gem_path
36
+
37
+ FileUtils.mkdir_p(gem_path)
38
+
39
+ @cache_path = gem_path.join('cache')
40
+ @cache = GemDirectorySource.new(self, :location => @cache_path)
41
+
42
+ @specs_path = gem_path.join('specifications')
43
+ @gems_path = gem_path.join('gems')
44
+ end
45
+
46
+ def root
47
+ gemfile.parent
48
+ end
49
+
50
+ def path
51
+ @path ||= root.join("vendor/gems")
52
+ end
53
+
54
+ def path=(path)
55
+ @path = (path.relative? ? root.join(path) : path).expand_path
56
+ end
57
+
58
+ def gem_path
59
+ path.join("#{Gem.ruby_engine}/#{Gem::ConfigMap[:ruby_version]}")
60
+ end
61
+
62
+ def bindir
63
+ @bindir ||= root.join("bin")
64
+ end
65
+
66
+ def bindir=(path)
67
+ @bindir = (path.relative? ? root.join(path) : path).expand_path
68
+ end
69
+
70
+ def install(options = {})
71
+ dependencies = @environment.dependencies
72
+ sources = @environment.sources
73
+
74
+ # ========== from env
75
+ if only_envs = options[:only]
76
+ dependencies.reject! { |d| !only_envs.any? {|env| d.in?(env) } }
77
+ end
78
+ # ==========
79
+
80
+ # Check to see whether the existing cache meets all the requirements
81
+ begin
82
+ valid = nil
83
+ # valid = Resolver.resolve(dependencies, [source_index], source_requirements)
84
+ rescue Bundler::GemNotFound
85
+ end
86
+
87
+ sources = only_local(sources) if options[:cached]
88
+
89
+ # Check the remote sources if the existing cache does not meet the requirements
90
+ # or the user passed --update
91
+ if options[:update] || !valid
92
+ Bundler.logger.info "Calculating dependencies..."
93
+ bundle = Resolver.resolve(dependencies, [@cache] + sources)
94
+ download(bundle, options)
95
+ do_install(bundle, options)
96
+ valid = bundle
97
+ end
98
+
99
+ generate_bins(valid, options)
100
+ cleanup(valid, options)
101
+ configure(valid, options)
102
+
103
+ Bundler.logger.info "Done."
104
+ end
105
+
106
+ def cache(*gemfiles)
107
+ FileUtils.mkdir_p(@cache_path)
108
+ gemfiles.each do |gemfile|
109
+ Bundler.logger.info "Caching: #{File.basename(gemfile)}"
110
+ FileUtils.cp(gemfile, @cache_path)
111
+ end
112
+ end
113
+
114
+ def list_outdated(options={})
115
+ outdated_gems = source_index.outdated.sort
116
+
117
+ if outdated_gems.empty?
118
+ Bundler.logger.info "All gems are up to date."
119
+ else
120
+ Bundler.logger.info "Outdated gems:"
121
+ outdated_gems.each do |name|
122
+ Bundler.logger.info " * #{name}"
123
+ end
124
+ end
125
+ end
126
+
127
+ def prune(options = {})
128
+ dependencies, sources = @environment.dependencies, @environment.sources
129
+
130
+ sources = only_local(sources)
131
+ bundle = Resolver.resolve(dependencies, [@cache] + sources)
132
+ @cache.gems.each do |name, specs|
133
+ specs.each do |spec|
134
+ unless bundle.any? { |s| s.name == spec.name && s.version == spec.version }
135
+ Bundler.logger.info "Pruning #{spec.name} (#{spec.version}) from the cache"
136
+ FileUtils.rm @cache_path.join("#{spec.full_name}.gem")
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def list(options = {})
143
+ Bundler.logger.info "Currently bundled gems:"
144
+ gems.each do |spec|
145
+ Bundler.logger.info " * #{spec.name} (#{spec.version})"
146
+ end
147
+ end
148
+
149
+ def gems
150
+ source_index.gems.values
151
+ end
152
+
153
+ def source_index
154
+ index = Gem::SourceIndex.from_gems_in(@specs_path)
155
+ index.each { |n, spec| spec.loaded_from = @specs_path.join("#{spec.full_name}.gemspec") }
156
+ index
157
+ end
158
+
159
+ def download_path_for(type)
160
+ @repos[type].download_path_for
161
+ end
162
+
163
+ def setup_environment
164
+ unless @environment.system_gems
165
+ ENV["GEM_HOME"] = gem_path
166
+ ENV["GEM_PATH"] = gem_path
167
+ end
168
+ ENV["PATH"] = "#{bindir}:#{ENV["PATH"]}"
169
+ ENV["RUBYOPT"] = "-r#{gem_path}/environment #{ENV["RUBYOPT"]}"
170
+ end
171
+
172
+ private
173
+
174
+ def only_local(sources)
175
+ sources.select { |s| s.local? }
176
+ end
177
+
178
+ def download(bundle, options)
179
+ bundle.sort_by {|s| s.full_name.downcase }.each do |spec|
180
+ next if spec.no_bundle?
181
+ spec.source.download(spec)
182
+ end
183
+ end
184
+
185
+ def do_install(bundle, options)
186
+ bundle.each do |spec|
187
+ next if spec.no_bundle?
188
+ spec.loaded_from = @specs_path.join("#{spec.full_name}.gemspec")
189
+ # Do nothing if the gem is already expanded
190
+ next if @gems_path.join(spec.full_name).directory?
191
+
192
+ case spec.source
193
+ when GemSource, GemDirectorySource, SystemGemSource
194
+ expand_gemfile(spec, options)
195
+ else
196
+ expand_vendored_gem(spec, options)
197
+ end
198
+ end
199
+ end
200
+
201
+ def generate_bins(bundle, options)
202
+ bundle.each do |spec|
203
+ next if spec.no_bundle?
204
+ # HAX -- Generate the bin
205
+ bin_dir = bindir
206
+ path = gem_path
207
+ gems_path = @gems_path
208
+ installer = Gem::Installer.allocate
209
+ installer.instance_eval do
210
+ @spec = spec
211
+ @bin_dir = bin_dir
212
+ @gem_dir = gems_path.join(spec.full_name)
213
+ @gem_home = path
214
+ @wrappers = true
215
+ @format_executable = false
216
+ @env_shebang = false
217
+ end
218
+ installer.generate_bin
219
+ end
220
+ end
221
+
222
+ def expand_gemfile(spec, options)
223
+ Bundler.logger.info "Installing #{spec.name} (#{spec.version})"
224
+
225
+ gemfile = @cache_path.join("#{spec.full_name}.gem").to_s
226
+
227
+ if build_args = options[:build_options] && options[:build_options][spec.name]
228
+ Gem::Command.build_args = build_args.map {|k,v| "--with-#{k}=#{v}"}
229
+ end
230
+
231
+ installer = Gem::Installer.new(gemfile, options.merge(
232
+ :install_dir => gem_path,
233
+ :ignore_dependencies => true,
234
+ :env_shebang => true,
235
+ :wrappers => true,
236
+ :bin_dir => bindir
237
+ ))
238
+ installer.install
239
+ rescue Gem::InstallError
240
+ cleanup_spec(spec)
241
+ raise
242
+ ensure
243
+ Gem::Command.build_args = []
244
+ end
245
+
246
+ def expand_vendored_gem(spec, options)
247
+ add_spec(spec)
248
+ FileUtils.mkdir_p(@gems_path)
249
+ File.symlink(spec.location, @gems_path.join(spec.full_name))
250
+ end
251
+
252
+ def add_spec(spec)
253
+ destination = @specs_path
254
+ destination.mkdir unless destination.exist?
255
+
256
+ File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f|
257
+ f.puts spec.to_ruby
258
+ end
259
+ end
260
+
261
+ def cleanup(valid, options)
262
+ to_delete = gems
263
+ to_delete.delete_if do |spec|
264
+ valid.any? { |other| spec.name == other.name && spec.version == other.version }
265
+ end
266
+
267
+ valid_executables = valid.map { |s| s.executables }.flatten.compact
268
+
269
+ to_delete.each do |spec|
270
+ Bundler.logger.info "Deleting gem: #{spec.name} (#{spec.version})"
271
+ cleanup_spec(spec)
272
+ # Cleanup the bin directory
273
+ spec.executables.each do |bin|
274
+ next if valid_executables.include?(bin)
275
+ Bundler.logger.info "Deleting bin file: #{bin}"
276
+ FileUtils.rm_rf(bindir.join(bin))
277
+ end
278
+ end
279
+ end
280
+
281
+ def cleanup_spec(spec)
282
+ FileUtils.rm_rf(@specs_path.join("#{spec.full_name}.gemspec"))
283
+ FileUtils.rm_rf(@gems_path.join(spec.full_name))
284
+ end
285
+
286
+ def expand(options)
287
+ each_repo do |repo|
288
+ repo.expand(options)
289
+ end
290
+ end
291
+
292
+ def configure(specs, options)
293
+ FileUtils.mkdir_p(gem_path)
294
+
295
+ File.open(gem_path.join("environment.rb"), "w") do |file|
296
+ file.puts @environment.environment_rb(specs, options)
297
+ end
298
+
299
+ generate_environment_picker
300
+ end
301
+
302
+ def generate_environment_picker
303
+ FileUtils.cp("#{File.dirname(__FILE__)}/templates/environment_picker.erb", path.join("environment.rb"))
304
+ end
305
+
306
+ def require_code(file, dep)
307
+ constraint = case
308
+ when dep.only then %{ if #{dep.only.inspect}.include?(env)}
309
+ when dep.except then %{ unless #{dep.except.inspect}.include?(env)}
310
+ end
311
+ "require #{file.inspect}#{constraint}"
312
+ end
313
+ end
314
+ end