bowline-bundler 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +291 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/bin/bowline-bundle +59 -0
- data/lib/bowline/bundler/bundle.rb +323 -0
- data/lib/bowline/bundler/cli.rb +87 -0
- data/lib/bowline/bundler/dependency.rb +62 -0
- data/lib/bowline/bundler/dsl.rb +182 -0
- data/lib/bowline/bundler/environment.rb +87 -0
- data/lib/bowline/bundler/finder.rb +51 -0
- data/lib/bowline/bundler/gem_bundle.rb +11 -0
- data/lib/bowline/bundler/gem_ext.rb +34 -0
- data/lib/bowline/bundler/remote_specification.rb +53 -0
- data/lib/bowline/bundler/resolver.rb +250 -0
- data/lib/bowline/bundler/runtime.rb +2 -0
- data/lib/bowline/bundler/source.rb +361 -0
- data/lib/bowline/bundler/templates/app_script.erb +3 -0
- data/lib/bowline/bundler/templates/environment.erb +156 -0
- data/lib/bowline/bundler/templates/environment_picker.erb +4 -0
- data/lib/bowline/bundler.rb +35 -0
- data/spec/bundler/cli_spec.rb +558 -0
- data/spec/bundler/directory_spec.rb +255 -0
- data/spec/bundler/dsl_spec.rb +126 -0
- data/spec/bundler/fetcher_spec.rb +138 -0
- data/spec/bundler/git_spec.rb +266 -0
- data/spec/bundler/installer_spec.rb +155 -0
- data/spec/bundler/manifest_file_spec.rb +105 -0
- data/spec/bundler/manifest_spec.rb +257 -0
- data/spec/bundler/runtime_spec.rb +141 -0
- data/spec/bundler/system_gems_spec.rb +42 -0
- data/spec/quality_spec.rb +57 -0
- data/spec/resolver/engine_spec.rb +112 -0
- data/spec/resolver/error_spec.rb +50 -0
- data/spec/resolver/fake_source_index_spec.rb +43 -0
- data/spec/resolver/prerelease_spec.rb +113 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/builders.rb +257 -0
- data/spec/support/core_ext.rb +18 -0
- data/spec/support/helpers.rb +126 -0
- data/spec/support/matchers.rb +201 -0
- data/spec/support/path_utils.rb +63 -0
- metadata +126 -0
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,291 @@
|
|
1
|
+
## bowline-bundler
|
2
|
+
|
3
|
+
This is a version of Bundler for Bowline apps.
|
4
|
+
|
5
|
+
Below is the original Bundler README.
|
6
|
+
|
7
|
+
|
8
|
+
## Bundler : A gem to bundle gems
|
9
|
+
|
10
|
+
Github: http://github.com/wycats/bundler
|
11
|
+
Mailing list: http://groups.google.com/group/ruby-bundler
|
12
|
+
IRC: #carlhuda on freenode
|
13
|
+
|
14
|
+
## Intro
|
15
|
+
|
16
|
+
Bundler is a tool that manages gem dependencies for your ruby application. It
|
17
|
+
takes a gem manifest file and is able to fetch, download, and install the gems
|
18
|
+
and all child dependencies specified in this manifest. It can manage any update
|
19
|
+
to the gem manifest file and update the bundled gems accordingly. It also lets
|
20
|
+
you run any ruby code in context of the bundled gem environment.
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Bundler has no dependencies. Just clone the git repository and install the gem
|
25
|
+
with the following rake task:
|
26
|
+
|
27
|
+
rake install
|
28
|
+
|
29
|
+
You can also install the gem with
|
30
|
+
|
31
|
+
gem install bundler
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Bundler requires a gem manifest file to be created. This should be a file named
|
36
|
+
`Gemfile` located in the root directory of your application. After the manifest
|
37
|
+
has been created, in your shell, cd into your application's directory and run
|
38
|
+
`gem bundle`. This will start the bundling process.
|
39
|
+
|
40
|
+
### Manifest file
|
41
|
+
|
42
|
+
This is where you specify all of your application's dependencies. By default
|
43
|
+
this should be in a file named `Gemfile` located in your application's root
|
44
|
+
directory. The following is an example of a potential `Gemfile`. For more
|
45
|
+
information, please refer to Bundler::ManifestBuilder.
|
46
|
+
|
47
|
+
# Specify a dependency on rails. When the bundler downloads gems,
|
48
|
+
# it will download rails as well as all of rails' dependencies (such as
|
49
|
+
# activerecord, actionpack, etc...)
|
50
|
+
#
|
51
|
+
# At least one dependency must be specified
|
52
|
+
gem "rails"
|
53
|
+
|
54
|
+
# Specify a dependency on rack v.1.0.0. The version is optional. If present,
|
55
|
+
# it can be specified the same way as with rubygems' #gem method.
|
56
|
+
gem "rack", "1.0.0"
|
57
|
+
|
58
|
+
# Specify a dependency rspec, but only require that gem in the "testing"
|
59
|
+
# environment. :except is also a valid option to specify environment
|
60
|
+
# restrictions.
|
61
|
+
gem "rspec", :only => :testing
|
62
|
+
|
63
|
+
# Specify a dependency, but specify that it is already present and expanded
|
64
|
+
# at vendor/rspec. Bundler will treat rspec as though it was the rspec gem
|
65
|
+
# for the purpose of gem resolution: if another gem depends on a version
|
66
|
+
# of rspec satisfied by "1.1.6", it will be used.
|
67
|
+
#
|
68
|
+
# If a gemspec is found in the directory, it will be used to specify load
|
69
|
+
# paths and supply additional dependencies.
|
70
|
+
#
|
71
|
+
# Bundler will also recursively search for *.gemspec, and assume that
|
72
|
+
# gemspecs it finds represent gems that are rooted in the same directory
|
73
|
+
# the gemspec is found in.
|
74
|
+
gem "rspec", "1.1.6", :vendored_at => "vendor/rspec"
|
75
|
+
|
76
|
+
# You can also control what will happen when you run Bundler.require_env
|
77
|
+
# by using the :require_as option, as per the next two examples.
|
78
|
+
|
79
|
+
# Don't auto-require this gem.
|
80
|
+
gem "rspec-rails", "1.2.9", :require_as => nil
|
81
|
+
|
82
|
+
# Require something other than the default.
|
83
|
+
gem "yajl-ruby", "0.6.7", :require_as => "yajl/json_gem"
|
84
|
+
|
85
|
+
# Works exactly like :vendored_at, but first downloads the repo from
|
86
|
+
# git and handles stashing the files for you. As with :vendored_at,
|
87
|
+
# Bundler will automatically use *.gemspec files in the root or anywhere
|
88
|
+
# in the repository.
|
89
|
+
gem "rails", "3.0.pre", :git => "git://github.com/rails/rails.git"
|
90
|
+
|
91
|
+
# Add http://gems.github.com as a source that the bundler will use
|
92
|
+
# to find gems listed in the manifest. By default,
|
93
|
+
# http://gems.rubyforge.org is already added to the list.
|
94
|
+
#
|
95
|
+
# This is an optional setting.
|
96
|
+
source "http://gems.github.com"
|
97
|
+
|
98
|
+
# Specify where the bundled gems should be stashed. This directory will
|
99
|
+
# be a gem repository where all gems are downloaded to and installed to.
|
100
|
+
#
|
101
|
+
# This is an optional setting.
|
102
|
+
# The default is: vendor/gems
|
103
|
+
bundle_path "my/bundled/gems"
|
104
|
+
|
105
|
+
# Specify where gem executables should be copied to.
|
106
|
+
#
|
107
|
+
# This is an optional setting.
|
108
|
+
# The default is: bin
|
109
|
+
bin_path "my/executables"
|
110
|
+
|
111
|
+
# Specify that rubygems should be completely disabled. This means that it
|
112
|
+
# will be impossible to require it and that available gems will be
|
113
|
+
# limited exclusively to gems that have been bundled.
|
114
|
+
#
|
115
|
+
# The default is to automatically require rubygems. There is also a
|
116
|
+
# `disable_system_gems` option that will limit available rubygems to
|
117
|
+
# the ones that have been bundled.
|
118
|
+
disable_rubygems
|
119
|
+
|
120
|
+
### Gem Resolution
|
121
|
+
|
122
|
+
One of the most important things that the bundler does is do a
|
123
|
+
dependency resolution on the full list of gems that you specify, all
|
124
|
+
at once. This differs from the one-at-a-time dependency resolution that
|
125
|
+
Rubygems does, which can result in the following problem:
|
126
|
+
|
127
|
+
# On my system:
|
128
|
+
# activesupport 3.0.pre
|
129
|
+
# activesupport 2.3.4
|
130
|
+
# activemerchant 1.4.2
|
131
|
+
# rails 2.3.4
|
132
|
+
#
|
133
|
+
# activemerchant 1.4.2 depends on activesupport >= 2.3.2
|
134
|
+
|
135
|
+
gem "activemerchant", "1.4.2"
|
136
|
+
# results in activating activemerchant, as well as
|
137
|
+
# activesupport 3.0.pre, since it is >= 2.3.2
|
138
|
+
|
139
|
+
gem "rails", "2.3.4"
|
140
|
+
# results in:
|
141
|
+
# can't activate activesupport (= 2.3.4, runtime)
|
142
|
+
# for ["rails-2.3.4"], already activated
|
143
|
+
# activesupport-3.0.pre for ["activemerchant-1.4.2"]
|
144
|
+
|
145
|
+
This is because activemerchant has a broader dependency, which results
|
146
|
+
in the activation of a version of activesupport that does not satisfy
|
147
|
+
a more narrow dependency.
|
148
|
+
|
149
|
+
Bundler solves this problem by evaluating all dependencies at once,
|
150
|
+
so it can detect that all gems *together* require activesupport "2.3.4".
|
151
|
+
|
152
|
+
### Running Bundler
|
153
|
+
|
154
|
+
Once a manifest file has been created, the only thing that needs to be done
|
155
|
+
is to run the `gem bundle` command anywhere in your application. The script
|
156
|
+
will load the manifest file, resolve all the dependencies, download all
|
157
|
+
needed gems, and install them into the specified directory.
|
158
|
+
|
159
|
+
Every time an update is made to the manifest file, run `gem bundle` again to
|
160
|
+
get the changes installed. This will only check the remote sources if your
|
161
|
+
currently installed gems do not satisfy the `Gemfile`. If you want to force
|
162
|
+
checking for updates on the remote sources, use the `--update` option.
|
163
|
+
|
164
|
+
### Remote deploys
|
165
|
+
|
166
|
+
When you run `gem bundle`, the following steps occur:
|
167
|
+
|
168
|
+
1. Gemfile is read in
|
169
|
+
2. The gems specified in the Gemfile are resolved against the gems
|
170
|
+
already in your bundle. If the dependencies resolve, skip to step 5.
|
171
|
+
3. If the dependencies in your Gemfile cannot be fully resolved
|
172
|
+
against the gems already in the bundle, the metadata for each
|
173
|
+
source is fetched.
|
174
|
+
4. The gems in the Gemfile are resolved against the full list of
|
175
|
+
available gems in all sources, and the resulting gems are downloaded
|
176
|
+
5. Each gem that has been downloaded but not yet expanded is expanded
|
177
|
+
into the local directory. This expansion process also installs
|
178
|
+
native gems.
|
179
|
+
|
180
|
+
As you can see, if you run gem bundle twice in a row, it will do nothing the
|
181
|
+
second time, since the gems obviously resolve against the installed gems,
|
182
|
+
and they are all expanded.
|
183
|
+
|
184
|
+
This also means that if you run `gem bundle`, and .gitignore the expanded
|
185
|
+
copies, leaving only the cached `.gem` files, you can run `gem bundle` again
|
186
|
+
on the remote system, and it will only expand out the gems (but not
|
187
|
+
resolve or download `.gem` files). This also means that native gems
|
188
|
+
will be compiled for the target platform without requiring that the
|
189
|
+
`.gem` file itself be downloaded from a remote gem server.
|
190
|
+
|
191
|
+
Assuming a Rails app with Bundler's standard setup, add something like
|
192
|
+
this to your top-level `.gitignore` to only keep the cache:
|
193
|
+
|
194
|
+
bin/*
|
195
|
+
vendor/gems/*
|
196
|
+
!vendor/gems/cache/
|
197
|
+
|
198
|
+
Make sure that you explicitly `git add vendor/gems/cache` before you commit.
|
199
|
+
|
200
|
+
### Gems with compile-time options
|
201
|
+
|
202
|
+
Some gems require you to pass compile-time options to the gem install command.
|
203
|
+
For instance, to install mysql, you might do:
|
204
|
+
|
205
|
+
gem install mysql -- --with-mysql-config=/usr/local/lib/mysql
|
206
|
+
|
207
|
+
You can pass these options to the bundler by creating a YAML file containing
|
208
|
+
the options in question:
|
209
|
+
|
210
|
+
mysql:
|
211
|
+
mysql-config: /usr/local/lib/mysql
|
212
|
+
|
213
|
+
You can then point the bundler at the file:
|
214
|
+
|
215
|
+
gem bundle --build-options build_options.yml
|
216
|
+
|
217
|
+
In general, you will want to keep the build options YAML out of version control,
|
218
|
+
and provide the appropriate options for the system in question.
|
219
|
+
|
220
|
+
### Running your application
|
221
|
+
|
222
|
+
The easiest way to run your application is to start it with an executable
|
223
|
+
copied to the specified bin directory (by default, simply bin). For example,
|
224
|
+
if the application in question is a rack app, start it with `bin/rackup`.
|
225
|
+
This will automatically set the gem environment correctly.
|
226
|
+
|
227
|
+
Another way to run arbitrary ruby code in context of the bundled gems is to
|
228
|
+
run it with the `gem exec` command. For example:
|
229
|
+
|
230
|
+
gem exec ruby my_ruby_script.rb
|
231
|
+
|
232
|
+
You can use `gem exec bash` to enter a shell that will run all binaries in
|
233
|
+
the current context.
|
234
|
+
|
235
|
+
Yet another way is to manually require the environment file first. This is
|
236
|
+
located in `[bundle_path]/gems/environment.rb`. For example:
|
237
|
+
|
238
|
+
ruby -r vendor/gems/environment.rb my_ruby_script.rb
|
239
|
+
|
240
|
+
### Using Bundler with Rails today
|
241
|
+
|
242
|
+
It should be possible to use Bundler with Rails today. Here are the steps
|
243
|
+
to follow.
|
244
|
+
|
245
|
+
* In your rails app, create a Gemfile and specify the gems that your
|
246
|
+
application depends on. Make sure to specify rails as well:
|
247
|
+
|
248
|
+
gem "rails", "2.1.2"
|
249
|
+
gem "will_paginate"
|
250
|
+
|
251
|
+
# Optionally, you can disable system gems all together and only
|
252
|
+
# use bundled gems.
|
253
|
+
disable_system_gems
|
254
|
+
|
255
|
+
* Run `gem bundle`
|
256
|
+
|
257
|
+
* You can now use rails if you prepend `gem exec` to every call to `script/*`
|
258
|
+
but that isn't fun.
|
259
|
+
|
260
|
+
* At the top of `config/preinitializer.rb`, add the following line:
|
261
|
+
|
262
|
+
require "#{RAILS_ROOT}/vendor/gems/environment"
|
263
|
+
|
264
|
+
In theory, this should be enough to get going.
|
265
|
+
|
266
|
+
## To require rubygems or not
|
267
|
+
|
268
|
+
Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides
|
269
|
+
enough features so that this isn't necessary. However, there are a number of gems
|
270
|
+
that require specific rubygems features.
|
271
|
+
|
272
|
+
If the `disable_rubygems` option is used, Bundler will stub out the most common
|
273
|
+
of these features, but it is possible that things will not go as intended quite
|
274
|
+
yet. So, if you are brave, try your code without rubygems at runtime.
|
275
|
+
|
276
|
+
This is different from the `disable_system_gems` option, which uses the rubygems
|
277
|
+
library, but prevents system gems from being loaded; only gems that are bundled
|
278
|
+
will be available to your application. This option guarantees that dependencies
|
279
|
+
of your application will be available to a remote system.
|
280
|
+
|
281
|
+
## Known Issues
|
282
|
+
|
283
|
+
* When a gem points to a git repository, the git repository will be cloned
|
284
|
+
every time Bundler does a gem dependency resolve.
|
285
|
+
|
286
|
+
## Reporting bugs
|
287
|
+
|
288
|
+
Please report all bugs on the github issue tracker for the project located
|
289
|
+
at:
|
290
|
+
|
291
|
+
http://github.com/wycats/bundler/issues/
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'bowline/bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "bowline-bundler"
|
8
|
+
gemspec.summary = "An easy way to vendor gem dependencies for Bowline apps"
|
9
|
+
gemspec.email = "alex@leadthinking.com"
|
10
|
+
gemspec.homepage = "http://github.com/maccman/bowline-bundler"
|
11
|
+
gemspec.authors = ["Alex MacCaw"]
|
12
|
+
gemspec.required_rubygems_version = ">= 1.3.5"
|
13
|
+
gemspec.files = FileList["[A-Z]*", "{bin,generators,lib,spec}/**/*"]
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :spec
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
rescue LoadError
|
24
|
+
task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
|
25
|
+
else
|
26
|
+
desc "Run specs"
|
27
|
+
Spec::Rake::SpecTask.new do |t|
|
28
|
+
t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb']
|
29
|
+
t.spec_opts = %w(-fs --color)
|
30
|
+
t.warning = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
namespace :spec do
|
35
|
+
file "tmp/rg_deps" do
|
36
|
+
repo = File.dirname(__FILE__) + '/tmp/rg_deps'
|
37
|
+
FileUtils.mkdir_p(repo)
|
38
|
+
p repo
|
39
|
+
ENV['GEM_HOME'], ENV['GEM_PATH'] = repo, repo
|
40
|
+
system "gem install builder --no-rdoc --no-ri"
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Do all setup needed to run the specs"
|
44
|
+
task :setup => "tmp/rg_deps"
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/bowline-bundle
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib bowline bundler])
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
|
10
|
+
options[:manifest] = manifest
|
11
|
+
end
|
12
|
+
|
13
|
+
opts.on('-u', '--update', "Force a remote check for newer gems") do
|
14
|
+
options[:update] = true
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on('--cached', "Only use cached gems when expanding the bundle") do
|
18
|
+
options[:cached] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('--cache GEM', "Specify a path to a .gem file to add to the bundled gem cache") do |gem, options|
|
22
|
+
options[:cache] = gem
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('--prune-cache', "Removes all .gem files that are not a part of the bundle from the cache") do
|
26
|
+
options[:prune] = true
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on('--list', "List all gems that are part of the active bundle") do
|
30
|
+
options[:list] = true
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on('--list-outdated', "List all outdated gems that are part of the active bundle") do
|
34
|
+
options[:list_outdated] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('-b', '--build-options OPTION_FILE', "Specify a path to a yml file with build options for binary gems") do |option_file, options|
|
38
|
+
if File.exist?(option_file)
|
39
|
+
options[:build_options] = YAML.load_file(option_file)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on('--only ENV', "Only expand the given environment. To specify multiple environments, use --only multiple times.") do |env, options|
|
44
|
+
options[:only] ||= []
|
45
|
+
options[:only] << env
|
46
|
+
end
|
47
|
+
end.parse!
|
48
|
+
|
49
|
+
if options[:cache]
|
50
|
+
Bundler::CLI.run(:cache, options)
|
51
|
+
elsif options[:prune]
|
52
|
+
Bundler::CLI.run(:prune, options)
|
53
|
+
elsif options[:list]
|
54
|
+
Bundler::CLI.run(:list, options)
|
55
|
+
elsif options[:list_outdated]
|
56
|
+
Bundler::CLI.run(:list_outdated, options)
|
57
|
+
else
|
58
|
+
Bundler::CLI.run(:bundle, options)
|
59
|
+
end
|