bundler 0.5.0 → 0.6.0
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.
- data/README.markdown +106 -14
- data/Rakefile +6 -3
- data/lib/bundler.rb +2 -1
- data/lib/bundler/cli.rb +24 -6
- data/lib/bundler/commands/bundle_command.rb +25 -1
- data/lib/bundler/dsl.rb +1 -0
- data/lib/bundler/environment.rb +58 -17
- data/lib/bundler/gem_bundle.rb +2 -2
- data/lib/bundler/gem_ext.rb +9 -1
- data/lib/bundler/remote_specification.rb +50 -0
- data/lib/bundler/repository.rb +119 -57
- data/lib/bundler/resolver.rb +3 -3
- data/lib/bundler/source.rb +185 -39
- data/lib/bundler/templates/environment.erb +5 -3
- metadata +7 -5
- data/lib/bundler/repository/directory_repository.rb +0 -46
- data/lib/bundler/repository/gem_repository.rb +0 -108
data/README.markdown
CHANGED
@@ -12,12 +12,6 @@ and all child dependencies specified in this manifest. It can manage any update
|
|
12
12
|
to the gem manifest file and update the bundled gems accordingly. It also lets
|
13
13
|
you run any ruby code in context of the bundled gem environment.
|
14
14
|
|
15
|
-
## Disclaimer
|
16
|
-
|
17
|
-
This project is under rapid development. It is usable today, but there will be
|
18
|
-
many changes in the near future, including to the Gemfile DSL. We will bump up
|
19
|
-
versions with changes though. We greatly appreciate feedback.
|
20
|
-
|
21
15
|
## Installation
|
22
16
|
|
23
17
|
Bundler has no dependencies. Just clone the git repository and install the gem
|
@@ -25,6 +19,10 @@ with the following rake task:
|
|
25
19
|
|
26
20
|
rake install
|
27
21
|
|
22
|
+
You can also install the gem with
|
23
|
+
|
24
|
+
gem install bundler
|
25
|
+
|
28
26
|
## Usage
|
29
27
|
|
30
28
|
Bundler requires a gem manifest file to be created. This should be a file named
|
@@ -50,11 +48,30 @@ information, please refer to Bundler::ManifestBuilder.
|
|
50
48
|
# it can be specified the same way as with rubygems' #gem method.
|
51
49
|
gem "rack", "1.0.0"
|
52
50
|
|
53
|
-
# Specify a dependency rspec, but only
|
54
|
-
# environment
|
55
|
-
#
|
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.
|
56
54
|
gem "rspec", :only => :testing
|
57
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
|
+
# Works exactly like :vendored_at, but first downloads the repo from
|
70
|
+
# git and handles stashing the files for you. As with :vendored_at,
|
71
|
+
# Bundler will automatically use *.gemspec files in the root or anywhere
|
72
|
+
# in the repository.
|
73
|
+
gem "rails", "3.0.pre", :git => "git://github.com/rails/rails.git"
|
74
|
+
|
58
75
|
# Add http://gems.github.com as a source that the bundler will use
|
59
76
|
# to find gems listed in the manifest. By default,
|
60
77
|
# http://gems.rubyforge.org is already added to the list.
|
@@ -84,11 +101,43 @@ information, please refer to Bundler::ManifestBuilder.
|
|
84
101
|
# the ones that have been bundled.
|
85
102
|
disable_rubygems
|
86
103
|
|
104
|
+
### Gem Resolution
|
105
|
+
|
106
|
+
One of the most important things that the bundler does is do a
|
107
|
+
dependency resolution on the full list of gems that you specify, all
|
108
|
+
at once. This differs from the one-at-a-time dependency resolution that
|
109
|
+
Rubygems does, which can result in the following problem:
|
110
|
+
|
111
|
+
# On my system:
|
112
|
+
# activesupport 3.0.pre
|
113
|
+
# activesupport 2.3.4
|
114
|
+
# activemerchant 1.4.2
|
115
|
+
# rails 2.3.4
|
116
|
+
#
|
117
|
+
# activemerchant 1.4.2 depends on activesupport >= 2.3.2
|
118
|
+
|
119
|
+
gem "activemerchant", "1.4.2"
|
120
|
+
# results in activating activemerchant, as well as
|
121
|
+
# activesupport 3.0.pre, since it is >= 2.3.2
|
122
|
+
|
123
|
+
gem "rails", "2.3.4"
|
124
|
+
# results in:
|
125
|
+
# can't activate activesupport (= 2.3.4, runtime)
|
126
|
+
# for ["rails-2.3.4"], already activated
|
127
|
+
# activesupport-3.0.pre for ["activemerchant-1.4.2"]
|
128
|
+
|
129
|
+
This is because activemerchant has a broader dependency, which results
|
130
|
+
in the activation of a version of activesupport that does not satisfy
|
131
|
+
a more narrow dependency.
|
132
|
+
|
133
|
+
Bundler solves this problem by evaluating all dependencies at once,
|
134
|
+
so it can detect that all gems *together* require activesupport "2.3.4".
|
135
|
+
|
87
136
|
### Running Bundler
|
88
137
|
|
89
138
|
Once a manifest file has been created, the only thing that needs to be done
|
90
139
|
is to run the `gem bundle` command anywhere in your application. The script
|
91
|
-
will load the manifest file,
|
140
|
+
will load the manifest file, resolve all the dependencies, download all
|
92
141
|
needed gems, and install them into the specified directory.
|
93
142
|
|
94
143
|
Every time an update is made to the manifest file, run `gem bundle` again to
|
@@ -96,6 +145,41 @@ get the changes installed. This will only check the remote sources if your
|
|
96
145
|
currently installed gems do not satisfy the `Gemfile`. If you want to force
|
97
146
|
checking for updates on the remote sources, use the `--update` option.
|
98
147
|
|
148
|
+
### Remote deploys
|
149
|
+
|
150
|
+
When you run `gem bundle`, the following steps occur:
|
151
|
+
|
152
|
+
1. Gemfile is read in
|
153
|
+
2. The gems specified in the Gemfile are resolved against the gems
|
154
|
+
already in your bundle. If the dependencies resolve, skip to step 5.
|
155
|
+
3. If the dependencies in your Gemfile cannot be fully resolved
|
156
|
+
against the gems already in the bundle, the metadata for each
|
157
|
+
source is fetched.
|
158
|
+
4. The gems in the Gemfile are resolved against the full list of
|
159
|
+
available gems in all sources, and the resulting gems are downloaded
|
160
|
+
5. Each gem that has been downloaded but not yet expanded is expanded
|
161
|
+
into the local directory. This expansion process also installs
|
162
|
+
native gems.
|
163
|
+
|
164
|
+
As you can see, if you run gem bundle twice in a row, it will do nothing the
|
165
|
+
second time, since the gems obviously resolve against the installed gems,
|
166
|
+
and they are all expanded.
|
167
|
+
|
168
|
+
This also means that if you run `gem bundle`, and .gitignore the expanded
|
169
|
+
copies, leaving only the cached `.gem` files, you can run `gem bundle` again
|
170
|
+
on the remote system, and it will only expand out the gems (but not
|
171
|
+
resolve or download `.gem` files). This also means that native gems
|
172
|
+
will be compiled for the target platform without requiring that the
|
173
|
+
`.gem` file itself be downloaded from a remote gem server.
|
174
|
+
|
175
|
+
Assuming a Rails app with Bundler's standard setup, add something like
|
176
|
+
this to your top-level `.gitignore` to only keep the cache:
|
177
|
+
|
178
|
+
vendor/gems/
|
179
|
+
!vendor/gems/cache/
|
180
|
+
|
181
|
+
Make sure that you explicitly `git add vendor/gems/cache` before you commit.
|
182
|
+
|
99
183
|
### Running your application
|
100
184
|
|
101
185
|
The easiest way to run your application is to start it with an executable
|
@@ -108,6 +192,9 @@ run it with the `gem exec` command. For example:
|
|
108
192
|
|
109
193
|
gem exec ruby my_ruby_script.rb
|
110
194
|
|
195
|
+
You can use `gem exec bash` to enter a shell that will run all binaries in
|
196
|
+
the current context.
|
197
|
+
|
111
198
|
Yet another way is to manually require the environment file first. This is
|
112
199
|
located in `[bundle_path]/environments/default.rb`. For example:
|
113
200
|
|
@@ -133,9 +220,9 @@ to follow.
|
|
133
220
|
* You can now use rails if you prepend `gem exec` to every call to `script/*`
|
134
221
|
but that isn't fun.
|
135
222
|
|
136
|
-
* At the top of `config/
|
223
|
+
* At the top of `config/preinitializer.rb`, add the following line:
|
137
224
|
|
138
|
-
|
225
|
+
require "#{RAILS_ROOT}/vendor/gems/environment"
|
139
226
|
|
140
227
|
In theory, this should be enough to get going.
|
141
228
|
|
@@ -143,12 +230,17 @@ In theory, this should be enough to get going.
|
|
143
230
|
|
144
231
|
Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides
|
145
232
|
enough features so that this isn't necessary. However, there are a number of gems
|
146
|
-
that require specific
|
233
|
+
that require specific rubygems features.
|
147
234
|
|
148
235
|
If the `disable_rubygems` option is used, Bundler will stub out the most common
|
149
236
|
of these features, but it is possible that things will not go as intended quite
|
150
237
|
yet. So, if you are brave, try your code without rubygems at runtime.
|
151
238
|
|
239
|
+
This is different from the `disable_system_gems` option, which uses the rubygems
|
240
|
+
library, but prevents system gems from being loaded; only gems that are bundled
|
241
|
+
will be available to your application. This option guarantees that dependencies
|
242
|
+
of your application will be available to a remote system.
|
243
|
+
|
152
244
|
## Known Issues
|
153
245
|
|
154
246
|
* When a gem points to a git repository, the git repository will be cloned
|
@@ -159,4 +251,4 @@ yet. So, if you are brave, try your code without rubygems at runtime.
|
|
159
251
|
Please report all bugs on the github issue tracker for the project located
|
160
252
|
at:
|
161
253
|
|
162
|
-
http://github.com/wycats/bundler/issues/
|
254
|
+
http://github.com/wycats/bundler/issues/
|
data/Rakefile
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
1
2
|
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
2
3
|
require 'rubygems/specification'
|
4
|
+
require 'bundler'
|
3
5
|
require 'date'
|
4
6
|
|
5
7
|
spec = Gem::Specification.new do |s|
|
6
8
|
s.name = "bundler"
|
7
|
-
s.version =
|
8
|
-
s.
|
9
|
-
s.email = "wycats@gmail.com"
|
9
|
+
s.version = Bundler::VERSION
|
10
|
+
s.authors = ["Yehuda Katz", "Carl Lerche"]
|
11
|
+
s.email = ["wycats@gmail.com", "clerche@engineyard.com"]
|
10
12
|
s.homepage = "http://github.com/wycats/bundler"
|
11
13
|
s.description = s.summary = "An easy way to vendor gem dependencies"
|
12
14
|
|
@@ -31,6 +33,7 @@ else
|
|
31
33
|
Spec::Rake::SpecTask.new do |t|
|
32
34
|
t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb']
|
33
35
|
t.spec_opts = %w(-fs --color)
|
36
|
+
t.warning = true
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
data/lib/bundler.rb
CHANGED
@@ -16,9 +16,10 @@ require "bundler/dsl"
|
|
16
16
|
require "bundler/cli"
|
17
17
|
require "bundler/repository"
|
18
18
|
require "bundler/dependency"
|
19
|
+
require "bundler/remote_specification"
|
19
20
|
|
20
21
|
module Bundler
|
21
|
-
VERSION = "0.
|
22
|
+
VERSION = "0.6.0"
|
22
23
|
|
23
24
|
class << self
|
24
25
|
attr_writer :logger
|
data/lib/bundler/cli.rb
CHANGED
@@ -6,19 +6,25 @@ module Bundler
|
|
6
6
|
new(options).run(command)
|
7
7
|
rescue DefaultManifestNotFound => e
|
8
8
|
Bundler.logger.error "Could not find a Gemfile to use"
|
9
|
-
exit
|
9
|
+
exit 3
|
10
10
|
rescue InvalidEnvironmentName => e
|
11
11
|
Bundler.logger.error "Gemfile error: #{e.message}"
|
12
|
-
exit
|
12
|
+
exit 4
|
13
13
|
rescue InvalidRepository => e
|
14
14
|
Bundler.logger.error e.message
|
15
|
-
exit
|
15
|
+
exit 5
|
16
16
|
rescue VersionConflict => e
|
17
17
|
Bundler.logger.error e.message
|
18
|
-
exit
|
18
|
+
exit 6
|
19
19
|
rescue GemNotFound => e
|
20
20
|
Bundler.logger.error e.message
|
21
|
-
exit
|
21
|
+
exit 7
|
22
|
+
rescue InvalidCacheArgument => e
|
23
|
+
Bundler.logger.error e.message
|
24
|
+
exit 8
|
25
|
+
rescue SourceNotCached => e
|
26
|
+
Bundler.logger.error e.message
|
27
|
+
exit 9
|
22
28
|
end
|
23
29
|
|
24
30
|
def initialize(options)
|
@@ -27,7 +33,19 @@ module Bundler
|
|
27
33
|
end
|
28
34
|
|
29
35
|
def bundle
|
30
|
-
@manifest.install(@options
|
36
|
+
@manifest.install(@options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def cache
|
40
|
+
@manifest.cache(@options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def prune
|
44
|
+
@manifest.prune(@options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def list
|
48
|
+
@manifest.list(@options)
|
31
49
|
end
|
32
50
|
|
33
51
|
def exec
|
@@ -10,6 +10,22 @@ class Gem::Commands::BundleCommand < Gem::Command
|
|
10
10
|
add_option('-u', '--update', "Force a remote check for newer gems") do
|
11
11
|
options[:update] = true
|
12
12
|
end
|
13
|
+
|
14
|
+
add_option('--cached', "Only use cached gems when expanding the bundle") do
|
15
|
+
options[:cached] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
add_option('--cache GEM', "Specify a path to a .gem file to add to the bundled gem cache") do |gem, options|
|
19
|
+
options[:cache] = gem
|
20
|
+
end
|
21
|
+
|
22
|
+
add_option('--prune-cache', "Removes all .gem files from the bundle's cache") do
|
23
|
+
options[:prune] = true
|
24
|
+
end
|
25
|
+
|
26
|
+
add_option('--list', "List all gems that are part of the active bundle") do
|
27
|
+
options[:list] = true
|
28
|
+
end
|
13
29
|
end
|
14
30
|
|
15
31
|
def usage
|
@@ -25,7 +41,15 @@ Bundle stuff
|
|
25
41
|
def execute
|
26
42
|
# Prevent the bundler from getting required unless it is actually being used
|
27
43
|
require 'bundler'
|
28
|
-
|
44
|
+
if options[:cache]
|
45
|
+
Bundler::CLI.run(:cache, options)
|
46
|
+
elsif options[:prune]
|
47
|
+
Bundler::CLI.run(:prune, options)
|
48
|
+
elsif options[:list]
|
49
|
+
Bundler::CLI.run(:list, options)
|
50
|
+
else
|
51
|
+
Bundler::CLI.run(:bundle, options)
|
52
|
+
end
|
29
53
|
end
|
30
54
|
|
31
55
|
end
|
data/lib/bundler/dsl.rb
CHANGED
data/lib/bundler/environment.rb
CHANGED
@@ -2,13 +2,16 @@ require "rubygems/source_index"
|
|
2
2
|
|
3
3
|
module Bundler
|
4
4
|
class DefaultManifestNotFound < StandardError; end
|
5
|
+
class InvalidCacheArgument < StandardError; end
|
6
|
+
class SourceNotCached < StandardError; end
|
5
7
|
|
6
8
|
class Environment
|
7
9
|
attr_reader :filename, :dependencies
|
8
|
-
attr_accessor :rubygems, :system_gems
|
10
|
+
attr_accessor :rubygems, :system_gems
|
11
|
+
attr_writer :gem_path, :bindir
|
9
12
|
|
10
13
|
def self.load(gemfile = nil)
|
11
|
-
gemfile = gemfile ? Pathname.new(gemfile) : default_manifest_file
|
14
|
+
gemfile = gemfile ? Pathname.new(gemfile).expand_path : default_manifest_file
|
12
15
|
|
13
16
|
unless gemfile.file?
|
14
17
|
raise ManifestFileNotFound, "#{filename.inspect} does not exist"
|
@@ -31,7 +34,7 @@ module Bundler
|
|
31
34
|
|
32
35
|
def initialize(filename) #, sources, dependencies, bindir, path, rubygems, system_gems)
|
33
36
|
@filename = filename
|
34
|
-
@default_sources = [GemSource.new(:uri => "http://gems.rubyforge.org")]
|
37
|
+
@default_sources = [GemSource.new(:uri => "http://gems.rubyforge.org"), SystemGemSource.new({})]
|
35
38
|
@sources = []
|
36
39
|
@priority_sources = []
|
37
40
|
@dependencies = []
|
@@ -43,23 +46,61 @@ module Bundler
|
|
43
46
|
builder.instance_eval(File.read(filename))
|
44
47
|
end
|
45
48
|
|
46
|
-
def install(
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
ensure
|
58
|
-
FileUtils.rm_rf(tmp_path)
|
59
|
-
end
|
49
|
+
def install(options = {})
|
50
|
+
update = options[:update]
|
51
|
+
cached = options[:cached]
|
52
|
+
|
53
|
+
repository.install(gem_dependencies, sources,
|
54
|
+
:rubygems => rubygems,
|
55
|
+
:system_gems => system_gems,
|
56
|
+
:manifest => filename,
|
57
|
+
:update => update,
|
58
|
+
:cached => cached
|
59
|
+
)
|
60
60
|
Bundler.logger.info "Done."
|
61
61
|
end
|
62
62
|
|
63
|
+
def cache(options = {})
|
64
|
+
gemfile = options[:cache]
|
65
|
+
|
66
|
+
if File.extname(gemfile) == ".gem"
|
67
|
+
if !File.exist?(gemfile)
|
68
|
+
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
|
69
|
+
end
|
70
|
+
repository.cache(gemfile)
|
71
|
+
elsif File.directory?(gemfile) || gemfile.include?('/')
|
72
|
+
if !File.directory?(gemfile)
|
73
|
+
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
|
74
|
+
end
|
75
|
+
gemfiles = Dir["#{gemfile}/*.gem"]
|
76
|
+
if gemfiles.empty?
|
77
|
+
raise InvalidCacheArgument, "'#{gemfile}' contains no gemfiles"
|
78
|
+
end
|
79
|
+
repository.cache(*gemfiles)
|
80
|
+
else
|
81
|
+
local = Gem::SourceIndex.from_installed_gems.find_name(gemfile).last
|
82
|
+
|
83
|
+
if !local
|
84
|
+
raise InvalidCacheArgument, "w0t? '#{gemfile}' means nothing to me."
|
85
|
+
end
|
86
|
+
|
87
|
+
gemfile = Pathname.new(local.loaded_from)
|
88
|
+
gemfile = gemfile.dirname.join('..', 'cache', "#{local.full_name}.gem").expand_path
|
89
|
+
repository.cache(gemfile)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def prune(options = {})
|
94
|
+
repository.prune(gem_dependencies, sources)
|
95
|
+
end
|
96
|
+
|
97
|
+
def list(options = {})
|
98
|
+
Bundler.logger.info "Currently bundled gems:"
|
99
|
+
repository.gems.each do |spec|
|
100
|
+
Bundler.logger.info " * #{spec.name} (#{spec.version})"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
63
104
|
def setup_environment
|
64
105
|
unless system_gems
|
65
106
|
ENV["GEM_HOME"] = gem_path
|
data/lib/bundler/gem_bundle.rb
CHANGED
data/lib/bundler/gem_ext.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Gem
|
2
2
|
class Installer
|
3
|
+
remove_method(:app_script_text) if method_defined?(:app_script_text)
|
4
|
+
|
3
5
|
def app_script_text(bin_file_name)
|
4
6
|
path = @gem_home
|
5
7
|
template = File.read(File.join(File.dirname(__FILE__), "templates", "app_script.erb"))
|
@@ -12,6 +14,8 @@ module Gem
|
|
12
14
|
attr_accessor :source
|
13
15
|
attr_accessor :location
|
14
16
|
|
17
|
+
remove_method(:specification_version) if method_defined?(:specification_version)
|
18
|
+
|
15
19
|
# Hack to fix github's strange marshal file
|
16
20
|
def specification_version
|
17
21
|
@specification_version && @specification_version.to_i
|
@@ -19,7 +23,11 @@ module Gem
|
|
19
23
|
|
20
24
|
alias full_gem_path_without_location full_gem_path
|
21
25
|
def full_gem_path
|
22
|
-
@location
|
26
|
+
if defined?(@location) && @location
|
27
|
+
@location
|
28
|
+
else
|
29
|
+
full_gem_path_without_location
|
30
|
+
end
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Bundler
|
2
|
+
# Represents a lazily loaded gem specification, where the full specification
|
3
|
+
# is on the source server in rubygems' "quick" index. The proxy object is to
|
4
|
+
# be seeded with what we're given from the source's abbreviated index - the
|
5
|
+
# full specification will only be fetched when necesary.
|
6
|
+
class RemoteSpecification
|
7
|
+
attr_reader :name, :version, :platform
|
8
|
+
attr_accessor :source
|
9
|
+
|
10
|
+
def initialize(name, version, platform, source_uri)
|
11
|
+
@name = name
|
12
|
+
@version = version
|
13
|
+
@platform = platform
|
14
|
+
@source_uri = source_uri
|
15
|
+
end
|
16
|
+
|
17
|
+
def full_name
|
18
|
+
if platform == Gem::Platform::RUBY or platform.nil? then
|
19
|
+
"#{@name}-#{@version}"
|
20
|
+
else
|
21
|
+
"#{@name}-#{@version}-#{platform}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Because Rubyforge cannot be trusted to provide valid specifications
|
26
|
+
# once the remote gem is donwloaded, the backend specification will
|
27
|
+
# be swapped out.
|
28
|
+
def __swap__(spec)
|
29
|
+
@specification = spec
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def _remote_uri
|
35
|
+
"#{@source_uri}/quick/Marshal.4.8/#{@name}-#{@version}.gemspec.rz"
|
36
|
+
end
|
37
|
+
|
38
|
+
def _remote_specification
|
39
|
+
@specification ||= begin
|
40
|
+
deflated = Gem::RemoteFetcher.fetcher.fetch_path(_remote_uri)
|
41
|
+
inflated = Gem.inflate(deflated)
|
42
|
+
Marshal.load(inflated)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def method_missing(method, *args, &blk)
|
47
|
+
_remote_specification.send(method, *args, &blk)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/bundler/repository.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require "bundler/repository/gem_repository"
|
2
|
-
require "bundler/repository/directory_repository"
|
3
|
-
|
4
1
|
module Bundler
|
5
2
|
class InvalidRepository < StandardError ; end
|
6
3
|
|
@@ -13,51 +10,67 @@ module Bundler
|
|
13
10
|
@path = Pathname.new(path)
|
14
11
|
@bindir = Pathname.new(bindir)
|
15
12
|
|
16
|
-
@
|
17
|
-
:gem => Gems.new(@path, @bindir),
|
18
|
-
:directory => Directory.new(@path.join("dirs"), @bindir)
|
19
|
-
}
|
13
|
+
@cache = GemDirectorySource.new(:location => @path.join("cache"))
|
20
14
|
end
|
21
15
|
|
22
16
|
def install(dependencies, sources, options = {})
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# Remove any gems that are still around if the Gemfile changed without
|
28
|
-
# requiring new gems to be download (e.g. a line in the Gemfile was
|
29
|
-
# removed)
|
30
|
-
cleanup(Resolver.resolve(dependencies, [source_index]))
|
17
|
+
# TODO: clean this up
|
18
|
+
sources.each do |s|
|
19
|
+
s.repository = self
|
20
|
+
s.local = options[:cached]
|
31
21
|
end
|
32
|
-
configure(options)
|
33
|
-
sync
|
34
|
-
end
|
35
22
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
gems.concat repo.gems
|
23
|
+
begin
|
24
|
+
valid = Resolver.resolve(dependencies, [source_index])
|
25
|
+
rescue Bundler::GemNotFound
|
40
26
|
end
|
41
|
-
|
27
|
+
|
28
|
+
if options[:cached]
|
29
|
+
sources = sources.select { |s| s.can_be_local? }
|
30
|
+
end
|
31
|
+
|
32
|
+
if options[:update] || !valid
|
33
|
+
Bundler.logger.info "Calculating dependencies..."
|
34
|
+
bundle = Resolver.resolve(dependencies, [@cache] + sources)
|
35
|
+
do_install(bundle, options)
|
36
|
+
valid = bundle
|
37
|
+
end
|
38
|
+
cleanup(valid)
|
39
|
+
configure(valid, options)
|
42
40
|
end
|
43
41
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
42
|
+
def cache(*gemfiles)
|
43
|
+
FileUtils.mkdir_p(@path.join("cache"))
|
44
|
+
gemfiles.each do |gemfile|
|
45
|
+
Bundler.logger.info "Caching: #{File.basename(gemfile)}"
|
46
|
+
FileUtils.cp(gemfile, @path.join("cache"))
|
47
|
+
end
|
47
48
|
end
|
48
49
|
|
49
|
-
def
|
50
|
-
|
50
|
+
def prune(dependencies, sources)
|
51
|
+
sources.each do |s|
|
52
|
+
s.repository = self
|
53
|
+
s.local = true
|
54
|
+
end
|
51
55
|
|
52
|
-
|
53
|
-
|
56
|
+
sources = sources.select { |s| s.can_be_local? }
|
57
|
+
bundle = Resolver.resolve(dependencies, [@cache] + sources)
|
58
|
+
@cache.gems.each do |name, spec|
|
59
|
+
unless bundle.any? { |s| s.name == spec.name && s.version == spec.version }
|
60
|
+
Bundler.logger.info "Pruning #{spec.name} (#{spec.version}) from the cache"
|
61
|
+
FileUtils.rm @path.join("cache", "#{spec.full_name}.gem")
|
62
|
+
end
|
54
63
|
end
|
64
|
+
end
|
55
65
|
|
56
|
-
|
66
|
+
def gems
|
67
|
+
source_index.gems.values
|
57
68
|
end
|
58
69
|
|
59
|
-
def
|
60
|
-
@
|
70
|
+
def source_index
|
71
|
+
index = Gem::SourceIndex.from_gems_in(@path.join("specifications"))
|
72
|
+
index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") }
|
73
|
+
index
|
61
74
|
end
|
62
75
|
|
63
76
|
def download_path_for(type)
|
@@ -66,34 +79,84 @@ module Bundler
|
|
66
79
|
|
67
80
|
private
|
68
81
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
82
|
+
def do_install(bundle, options)
|
83
|
+
bundle.download
|
84
|
+
|
85
|
+
bundle.each do |spec|
|
86
|
+
spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec")
|
87
|
+
# Do nothing if the gem is already expanded
|
88
|
+
next if @path.join("gems", spec.full_name).directory?
|
89
|
+
|
90
|
+
case spec.source
|
91
|
+
when GemSource, GemDirectorySource, SystemGemSource
|
92
|
+
expand_gemfile(spec, options)
|
93
|
+
else
|
94
|
+
expand_vendored_gem(spec, options)
|
95
|
+
end
|
72
96
|
end
|
73
97
|
end
|
74
98
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
99
|
+
def expand_gemfile(spec, options)
|
100
|
+
Bundler.logger.info "Installing #{spec.name} (#{spec.version})"
|
101
|
+
|
102
|
+
gemfile = @path.join("cache", "#{spec.full_name}.gem").to_s
|
103
|
+
|
104
|
+
installer = Gem::Installer.new(gemfile, options.merge(
|
105
|
+
:install_dir => @path,
|
106
|
+
:ignore_dependencies => true,
|
107
|
+
:env_shebang => true,
|
108
|
+
:wrappers => true,
|
109
|
+
:bin_dir => @bindir
|
110
|
+
))
|
111
|
+
installer.install
|
112
|
+
end
|
113
|
+
|
114
|
+
def expand_vendored_gem(spec, options)
|
115
|
+
add_spec(spec)
|
116
|
+
FileUtils.mkdir_p(@path.join("gems"))
|
117
|
+
File.symlink(spec.location, @path.join("gems", spec.full_name))
|
118
|
+
|
119
|
+
# HAX -- Generate the bin
|
120
|
+
bin_dir = @bindir
|
121
|
+
path = @path
|
122
|
+
installer = Gem::Installer.allocate
|
123
|
+
installer.instance_eval do
|
124
|
+
@spec = spec
|
125
|
+
@bin_dir = bin_dir
|
126
|
+
@gem_dir = path.join("gems", "#{spec.full_name}")
|
127
|
+
@gem_home = path
|
128
|
+
@wrappers = true
|
78
129
|
end
|
130
|
+
installer.generate_bin
|
79
131
|
end
|
80
132
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
bundle.download(self)
|
133
|
+
def add_spec(spec)
|
134
|
+
destination = path.join('specifications')
|
135
|
+
destination.mkdir unless destination.exist?
|
136
|
+
|
137
|
+
File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f|
|
138
|
+
f.puts spec.to_ruby
|
139
|
+
end
|
89
140
|
end
|
90
141
|
|
91
|
-
def
|
92
|
-
|
142
|
+
def cleanup(valid)
|
143
|
+
to_delete = gems
|
144
|
+
to_delete.delete_if do |spec|
|
145
|
+
valid.any? { |other| spec.name == other.name && spec.version == other.version }
|
146
|
+
end
|
93
147
|
|
94
|
-
|
95
|
-
|
96
|
-
|
148
|
+
valid_executables = valid.map { |s| s.executables }.flatten.compact
|
149
|
+
|
150
|
+
to_delete.each do |spec|
|
151
|
+
Bundler.logger.info "Deleting gem: #{spec.name} (#{spec.version})"
|
152
|
+
FileUtils.rm_rf(@path.join("specifications", "#{spec.full_name}.gemspec"))
|
153
|
+
FileUtils.rm_rf(@path.join("gems", spec.full_name))
|
154
|
+
# Cleanup the bin directory
|
155
|
+
spec.executables.each do |bin|
|
156
|
+
next if valid_executables.include?(bin)
|
157
|
+
Bundler.logger.info "Deleting bin file: #{bin}"
|
158
|
+
FileUtils.rm_rf(@bindir.join(bin))
|
159
|
+
end
|
97
160
|
end
|
98
161
|
end
|
99
162
|
|
@@ -103,14 +166,13 @@ module Bundler
|
|
103
166
|
end
|
104
167
|
end
|
105
168
|
|
106
|
-
def configure(options)
|
107
|
-
generate_environment(options)
|
169
|
+
def configure(specs, options)
|
170
|
+
generate_environment(specs, options)
|
108
171
|
end
|
109
172
|
|
110
|
-
def generate_environment(options)
|
173
|
+
def generate_environment(specs, options)
|
111
174
|
FileUtils.mkdir_p(path)
|
112
175
|
|
113
|
-
specs = gems
|
114
176
|
load_paths = load_paths_for_specs(specs)
|
115
177
|
bindir = @bindir.relative_path_from(path).to_s
|
116
178
|
filename = options[:manifest].relative_path_from(path).to_s
|
@@ -148,4 +210,4 @@ module Bundler
|
|
148
210
|
"require #{file.inspect}#{constraint}"
|
149
211
|
end
|
150
212
|
end
|
151
|
-
end
|
213
|
+
end
|
data/lib/bundler/resolver.rb
CHANGED
@@ -37,8 +37,6 @@ module Bundler
|
|
37
37
|
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
|
38
38
|
# collection of gemspecs is returned. Otherwise, nil is returned.
|
39
39
|
def self.resolve(requirements, sources)
|
40
|
-
Bundler.logger.info "Calculating dependencies..."
|
41
|
-
|
42
40
|
resolver = new(sources)
|
43
41
|
result = catch(:success) do
|
44
42
|
resolver.resolve(requirements, {})
|
@@ -181,7 +179,9 @@ module Bundler
|
|
181
179
|
def search(dependency)
|
182
180
|
@cache[dependency.hash] ||= begin
|
183
181
|
@specs[dependency.name].values.select do |spec|
|
184
|
-
dependency =~ spec
|
182
|
+
match = dependency =~ spec
|
183
|
+
match &= dependency.version_requirements.prerelease? if spec.version.prerelease?
|
184
|
+
match
|
185
185
|
end.sort_by {|s| s.version }
|
186
186
|
end
|
187
187
|
end
|
data/lib/bundler/source.rb
CHANGED
@@ -2,7 +2,7 @@ module Bundler
|
|
2
2
|
# Represents a source of rubygems. Initially, this is only gem repositories, but
|
3
3
|
# eventually, this will be git, svn, HTTP
|
4
4
|
class Source
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :repository, :local
|
6
6
|
end
|
7
7
|
|
8
8
|
class GemSource < Source
|
@@ -14,6 +14,10 @@ module Bundler
|
|
14
14
|
raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute?
|
15
15
|
end
|
16
16
|
|
17
|
+
def can_be_local?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
17
21
|
def gems
|
18
22
|
@specs ||= fetch_specs
|
19
23
|
end
|
@@ -28,16 +32,22 @@ module Bundler
|
|
28
32
|
|
29
33
|
class RubygemsRetardation < StandardError; end
|
30
34
|
|
31
|
-
def download(spec
|
35
|
+
def download(spec)
|
32
36
|
Bundler.logger.info "Downloading #{spec.full_name}.gem"
|
33
37
|
|
34
|
-
destination = repository.
|
38
|
+
destination = repository.path
|
35
39
|
|
36
40
|
unless destination.writable?
|
37
41
|
raise RubygemsRetardation
|
38
42
|
end
|
39
43
|
|
40
|
-
|
44
|
+
# Download the gem
|
45
|
+
Gem::RemoteFetcher.fetcher.download(spec, uri, destination)
|
46
|
+
|
47
|
+
# Re-read the gemspec from the downloaded gem to correct
|
48
|
+
# any errors that were present in the Rubyforge specification.
|
49
|
+
new_spec = Gem::Format.from_file_by_path(destination.join('cache', "#{spec.full_name}.gem")).spec
|
50
|
+
spec.__swap__(new_spec)
|
41
51
|
end
|
42
52
|
|
43
53
|
private
|
@@ -45,17 +55,109 @@ module Bundler
|
|
45
55
|
def fetch_specs
|
46
56
|
Bundler.logger.info "Updating source: #{to_s}"
|
47
57
|
|
48
|
-
|
49
|
-
|
58
|
+
fetcher = Gem::RemoteFetcher.fetcher
|
59
|
+
main_index = fetcher.fetch_path("#{uri}/specs.4.8.gz")
|
60
|
+
begin
|
61
|
+
prerelease_index = fetcher.fetch_path("#{uri}/prerelease_specs.4.8.gz")
|
62
|
+
index = Marshal.load(main_index) + Marshal.load(prerelease_index)
|
63
|
+
rescue Gem::RemoteFetcher::FetchError
|
64
|
+
Bundler.logger.warn "Source '#{uri}' does not support prerelease gems"
|
65
|
+
index = Marshal.load(main_index)
|
66
|
+
end
|
50
67
|
|
51
|
-
|
52
|
-
index.
|
68
|
+
gems = {}
|
69
|
+
index.each do |name, version, platform|
|
70
|
+
spec = RemoteSpecification.new(name, version, platform, @uri)
|
71
|
+
gems[spec.full_name] = spec
|
72
|
+
end
|
73
|
+
gems
|
53
74
|
rescue Gem::RemoteFetcher::FetchError => e
|
54
75
|
raise ArgumentError, "#{to_s} is not a valid source: #{e.message}"
|
55
76
|
end
|
56
77
|
end
|
57
78
|
|
79
|
+
class SystemGemSource < Source
|
80
|
+
def initialize(options)
|
81
|
+
# Nothing to do
|
82
|
+
end
|
83
|
+
|
84
|
+
def can_be_local?
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
def gems
|
89
|
+
@specs ||= Gem::SourceIndex.from_installed_gems.gems
|
90
|
+
end
|
91
|
+
|
92
|
+
def ==(other)
|
93
|
+
other.is_a?(SystemGemSource)
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
"system"
|
98
|
+
end
|
99
|
+
|
100
|
+
def download(spec)
|
101
|
+
# gemfile = Pathname.new(local.loaded_from)
|
102
|
+
# gemfile = gemfile.dirname.join('..', 'cache', "#{local.full_name}.gem").expand_path
|
103
|
+
# repository.cache(File.join(Gem.dir, "cache", "#{local.full_name}.gem"))
|
104
|
+
gemfile = Pathname.new(spec.loaded_from)
|
105
|
+
gemfile = gemfile.dirname.join('..', 'cache', "#{spec.full_name}.gem")
|
106
|
+
repository.cache(gemfile)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def fetch_specs
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
class GemDirectorySource < Source
|
118
|
+
attr_reader :location
|
119
|
+
|
120
|
+
def initialize(options)
|
121
|
+
@location = options[:location]
|
122
|
+
end
|
123
|
+
|
124
|
+
def can_be_local?
|
125
|
+
true
|
126
|
+
end
|
127
|
+
|
128
|
+
def gems
|
129
|
+
@specs ||= fetch_specs
|
130
|
+
end
|
131
|
+
|
132
|
+
def ==(other)
|
133
|
+
location == other.location
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_s
|
137
|
+
location.to_s
|
138
|
+
end
|
139
|
+
|
140
|
+
def download(spec)
|
141
|
+
# raise NotImplementedError
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def fetch_specs
|
147
|
+
specs = {}
|
148
|
+
|
149
|
+
Dir["#{@location}/*.gem"].each do |gemfile|
|
150
|
+
spec = Gem::Format.from_file_by_path(gemfile).spec
|
151
|
+
specs[spec.full_name] = spec
|
152
|
+
end
|
153
|
+
|
154
|
+
specs
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
58
158
|
class DirectorySource < Source
|
159
|
+
attr_reader :location
|
160
|
+
|
59
161
|
def initialize(options)
|
60
162
|
@name = options[:name]
|
61
163
|
@version = options[:version]
|
@@ -63,32 +165,38 @@ module Bundler
|
|
63
165
|
@require_paths = options[:require_paths] || %w(lib)
|
64
166
|
end
|
65
167
|
|
168
|
+
def can_be_local?
|
169
|
+
true
|
170
|
+
end
|
171
|
+
|
66
172
|
def gems
|
67
173
|
@gems ||= begin
|
68
174
|
specs = {}
|
69
175
|
|
70
176
|
# Find any gemspec files in the directory and load those specs
|
71
|
-
Dir[
|
72
|
-
|
73
|
-
spec = eval(File.read(file))
|
74
|
-
|
75
|
-
|
177
|
+
Dir["#{location}/**/*.gemspec"].each do |file|
|
178
|
+
file = Pathname.new(file)
|
179
|
+
if spec = eval(File.read(file)) and validate_gemspec(file, spec)
|
180
|
+
spec.location = file.dirname.expand_path
|
181
|
+
specs[spec.full_name] = spec
|
182
|
+
end
|
76
183
|
end
|
77
184
|
|
78
185
|
# If a gemspec for the dependency was not found, add it to the list
|
79
186
|
if specs.keys.grep(/^#{Regexp.escape(@name)}/).empty?
|
80
187
|
case
|
81
188
|
when @version.nil?
|
82
|
-
raise ArgumentError, "If you use :at, you must specify the gem" \
|
189
|
+
raise ArgumentError, "If you use :at, you must specify the gem " \
|
83
190
|
"and version you wish to stand in for"
|
84
191
|
when !Gem::Version.correct?(@version)
|
85
|
-
raise ArgumentError, "If you use :at, you must specify a gem and" \
|
192
|
+
raise ArgumentError, "If you use :at, you must specify a gem and " \
|
86
193
|
"version. You specified #{@version} for the version"
|
87
194
|
end
|
88
195
|
|
89
196
|
default = Gem::Specification.new do |s|
|
90
|
-
s.name
|
91
|
-
s.version
|
197
|
+
s.name = @name
|
198
|
+
s.version = Gem::Version.new(@version) if @version
|
199
|
+
s.location = location
|
92
200
|
end
|
93
201
|
specs[default.full_name] = default
|
94
202
|
end
|
@@ -97,18 +205,52 @@ module Bundler
|
|
97
205
|
end
|
98
206
|
end
|
99
207
|
|
208
|
+
# Too aggressive apparently.
|
209
|
+
# ===
|
210
|
+
# def validate_gemspec(file, spec)
|
211
|
+
# file = Pathname.new(file)
|
212
|
+
# Dir.chdir(file.dirname) do
|
213
|
+
# spec.validate
|
214
|
+
# end
|
215
|
+
# rescue Gem::InvalidSpecificationException => e
|
216
|
+
# file = file.relative_path_from(repository.path)
|
217
|
+
# Bundler.logger.warn e.message
|
218
|
+
# Bundler.logger.warn "Gemspec #{spec.name} (#{spec.version}) found at '#{file}' is not valid"
|
219
|
+
# false
|
220
|
+
# end
|
221
|
+
def validate_gemspec(file, spec)
|
222
|
+
base = file.dirname
|
223
|
+
msg = "Gemspec for #{spec.name} (#{spec.version}) is invalid:"
|
224
|
+
# Check the require_paths
|
225
|
+
(spec.require_paths || []).each do |path|
|
226
|
+
unless base.join(path).directory?
|
227
|
+
Bundler.logger.warn "#{msg} Missing require path: '#{path}'"
|
228
|
+
return false
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Check the executables
|
233
|
+
(spec.executables || []).each do |exec|
|
234
|
+
unless base.join(spec.bindir, exec).file?
|
235
|
+
Bundler.logger.warn "#{msg} Missing executable: '#{File.join(spec.bindir, exec)}'"
|
236
|
+
return false
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
true
|
241
|
+
end
|
242
|
+
|
100
243
|
def ==(other)
|
101
244
|
# TMP HAX
|
102
245
|
other.is_a?(DirectorySource)
|
103
246
|
end
|
104
247
|
|
105
248
|
def to_s
|
106
|
-
"#{@name} (#{@version}) Located at: '#{
|
249
|
+
"#{@name} (#{@version}) Located at: '#{location}'"
|
107
250
|
end
|
108
251
|
|
109
|
-
def download(spec
|
110
|
-
|
111
|
-
repository.add_spec(:directory, spec)
|
252
|
+
def download(spec)
|
253
|
+
# Nothing needed here
|
112
254
|
end
|
113
255
|
end
|
114
256
|
|
@@ -120,31 +262,35 @@ module Bundler
|
|
120
262
|
@branch = options[:branch]
|
121
263
|
end
|
122
264
|
|
265
|
+
def location
|
266
|
+
# TMP HAX to get the *.gemspec reading to work
|
267
|
+
repository.path.join('dirs', File.basename(@uri, '.git'))
|
268
|
+
end
|
269
|
+
|
123
270
|
def gems
|
124
|
-
|
271
|
+
unless location.directory?
|
272
|
+
# Raise an error if the source should run in local mode,
|
273
|
+
# but it has not been cached yet.
|
274
|
+
if local
|
275
|
+
raise SourceNotCached, "Git repository '#{@uri}' has not been cloned yet"
|
276
|
+
end
|
125
277
|
|
126
|
-
|
127
|
-
@location = tmp_path.join("gitz", @name)
|
278
|
+
FileUtils.mkdir_p(location.dirname)
|
128
279
|
|
129
|
-
|
130
|
-
|
280
|
+
Bundler.logger.info "Cloning git repository at: #{@uri}"
|
281
|
+
`git clone #{@uri} #{location} --no-hardlinks`
|
131
282
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
283
|
+
if @ref
|
284
|
+
Dir.chdir(location) { `git checkout #{@ref}` }
|
285
|
+
elsif @branch && @branch != "master"
|
286
|
+
Dir.chdir(location) { `git checkout origin/#{@branch}` }
|
287
|
+
end
|
136
288
|
end
|
137
289
|
super
|
138
290
|
end
|
139
291
|
|
140
|
-
def download(spec
|
141
|
-
|
142
|
-
spec.require_paths.map! { |p| File.join(dest, p) }
|
143
|
-
repository.add_spec(:directory, spec)
|
144
|
-
if spec.name == @name
|
145
|
-
FileUtils.mkdir_p(dest.dirname)
|
146
|
-
FileUtils.mv(tmp_path.join("gitz", spec.name), dest)
|
147
|
-
end
|
292
|
+
def download(spec)
|
293
|
+
# Nothing needed here
|
148
294
|
end
|
149
295
|
end
|
150
|
-
end
|
296
|
+
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# DO NOT MODIFY THIS FILE
|
2
2
|
module Bundler
|
3
|
-
|
3
|
+
file = File.expand_path(__FILE__)
|
4
|
+
dir = File.dirname(file)
|
4
5
|
|
5
6
|
<% unless options[:system_gems] -%>
|
6
7
|
ENV["GEM_HOME"] = dir
|
7
8
|
ENV["GEM_PATH"] = dir
|
8
9
|
<% end -%>
|
9
10
|
ENV["PATH"] = "#{dir}/<%= bindir %>:#{ENV["PATH"]}"
|
10
|
-
ENV["RUBYOPT"] = "-r#{
|
11
|
+
ENV["RUBYOPT"] = "-r#{file} #{ENV["RUBYOPT"]}"
|
11
12
|
|
12
13
|
<% load_paths.each do |load_path| -%>
|
13
14
|
$LOAD_PATH.unshift File.expand_path("#{dir}/<%= load_path %>")
|
@@ -57,6 +58,7 @@ module Bundler
|
|
57
58
|
only = _combine_onlys(opt[:only] || opt["only"])
|
58
59
|
except = _combine_excepts(opt[:except] || opt["except"])
|
59
60
|
files = opt[:require_as] || opt["require_as"] || name
|
61
|
+
files = [files] unless files.respond_to?(:each)
|
60
62
|
|
61
63
|
return unless !only || only.any? {|e| e == @env }
|
62
64
|
return if except && except.any? {|e| e == @env }
|
@@ -124,4 +126,4 @@ module Gem
|
|
124
126
|
class VerificationError < Exception; end
|
125
127
|
class SystemExitException < SystemExit; end
|
126
128
|
end
|
127
|
-
<% end -%>
|
129
|
+
<% end -%>
|
metadata
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yehuda Katz
|
8
|
+
- Carl Lerche
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date: 2009-09-
|
13
|
+
date: 2009-09-23 00:00:00 -07:00
|
13
14
|
default_executable:
|
14
15
|
dependencies: []
|
15
16
|
|
16
17
|
description: An easy way to vendor gem dependencies
|
17
|
-
email:
|
18
|
+
email:
|
19
|
+
- wycats@gmail.com
|
20
|
+
- clerche@engineyard.com
|
18
21
|
executables: []
|
19
22
|
|
20
23
|
extensions: []
|
@@ -35,8 +38,7 @@ files:
|
|
35
38
|
- lib/bundler/finder.rb
|
36
39
|
- lib/bundler/gem_bundle.rb
|
37
40
|
- lib/bundler/gem_ext.rb
|
38
|
-
- lib/bundler/
|
39
|
-
- lib/bundler/repository/gem_repository.rb
|
41
|
+
- lib/bundler/remote_specification.rb
|
40
42
|
- lib/bundler/repository.rb
|
41
43
|
- lib/bundler/resolver.rb
|
42
44
|
- lib/bundler/runtime.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module Bundler
|
2
|
-
class Repository
|
3
|
-
class Directory
|
4
|
-
attr_reader :path, :bindir
|
5
|
-
|
6
|
-
def initialize(path, bindir)
|
7
|
-
@path = path
|
8
|
-
@bindir = bindir
|
9
|
-
|
10
|
-
FileUtils.mkdir_p(path.to_s)
|
11
|
-
end
|
12
|
-
|
13
|
-
def source_index
|
14
|
-
index = Gem::SourceIndex.from_gems_in(@path.join("specifications"))
|
15
|
-
index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") }
|
16
|
-
index
|
17
|
-
end
|
18
|
-
|
19
|
-
def gems
|
20
|
-
source_index.gems.values
|
21
|
-
end
|
22
|
-
|
23
|
-
def add_spec(spec)
|
24
|
-
destination = path.join('specifications')
|
25
|
-
destination.mkdir unless destination.exist?
|
26
|
-
|
27
|
-
File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f|
|
28
|
-
f.puts spec.to_ruby
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def download_path_for
|
33
|
-
@path.join("dirs")
|
34
|
-
end
|
35
|
-
|
36
|
-
# Checks whether a gem is installed
|
37
|
-
def expand(options)
|
38
|
-
# raise NotImplementedError
|
39
|
-
end
|
40
|
-
|
41
|
-
def cleanup(gems)
|
42
|
-
# raise NotImplementedError
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,108 +0,0 @@
|
|
1
|
-
module Bundler
|
2
|
-
class Repository
|
3
|
-
class Gems
|
4
|
-
attr_reader :path, :bindir
|
5
|
-
|
6
|
-
def initialize(path, bindir)
|
7
|
-
@path = path
|
8
|
-
@bindir = bindir
|
9
|
-
end
|
10
|
-
|
11
|
-
# Returns the source index for all gems installed in the
|
12
|
-
# repository
|
13
|
-
def source_index
|
14
|
-
index = Gem::SourceIndex.from_gems_in(@path.join("specifications"))
|
15
|
-
index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") }
|
16
|
-
index
|
17
|
-
end
|
18
|
-
|
19
|
-
def gems
|
20
|
-
source_index.gems.values
|
21
|
-
end
|
22
|
-
|
23
|
-
# Checks whether a gem is installed
|
24
|
-
def expand(options)
|
25
|
-
cached_gems.each do |name, version|
|
26
|
-
unless installed?(name, version)
|
27
|
-
install_cached_gem(name, version, options)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def cleanup(gems)
|
33
|
-
glob = gems.map { |g| g.full_name }.join(',')
|
34
|
-
base = path.join("{cache,specifications,gems}")
|
35
|
-
|
36
|
-
(Dir[base.join("*")] - Dir[base.join("{#{glob}}{.gemspec,.gem,}")]).each do |file|
|
37
|
-
if File.basename(file) =~ /\.gem$/
|
38
|
-
name = File.basename(file, '.gem')
|
39
|
-
Bundler.logger.info "Deleting gem: #{name}"
|
40
|
-
end
|
41
|
-
FileUtils.rm_rf(file)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def add_spec(spec)
|
46
|
-
raise NotImplementedError
|
47
|
-
end
|
48
|
-
|
49
|
-
def download_path_for
|
50
|
-
path
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def cache_path
|
56
|
-
@path.join("cache")
|
57
|
-
end
|
58
|
-
|
59
|
-
def cache_files
|
60
|
-
Dir[cache_path.join("*.gem")]
|
61
|
-
end
|
62
|
-
|
63
|
-
def cached_gems
|
64
|
-
cache_files.map do |f|
|
65
|
-
full_name = File.basename(f).gsub(/\.gem$/, '')
|
66
|
-
full_name.split(/-(?=[^-]+$)/)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def spec_path
|
71
|
-
@path.join("specifications")
|
72
|
-
end
|
73
|
-
|
74
|
-
def spec_files
|
75
|
-
Dir[spec_path.join("*.gemspec")]
|
76
|
-
end
|
77
|
-
|
78
|
-
def gem_path
|
79
|
-
@path.join("gems")
|
80
|
-
end
|
81
|
-
|
82
|
-
def gem_paths
|
83
|
-
Dir[gem_path.join("*")]
|
84
|
-
end
|
85
|
-
|
86
|
-
def installed?(name, version)
|
87
|
-
spec_files.any? { |g| File.basename(g) == "#{name}-#{version}.gemspec" } &&
|
88
|
-
gem_paths.any? { |g| File.basename(g) == "#{name}-#{version}" }
|
89
|
-
end
|
90
|
-
|
91
|
-
def install_cached_gem(name, version, options = {})
|
92
|
-
cached_gem = cache_path.join("#{name}-#{version}.gem")
|
93
|
-
# TODO: Add a warning if cached_gem is not a file
|
94
|
-
if cached_gem.file?
|
95
|
-
Bundler.logger.info "Installing #{name}-#{version}.gem"
|
96
|
-
installer = Gem::Installer.new(cached_gem.to_s, options.merge(
|
97
|
-
:install_dir => @path,
|
98
|
-
:ignore_dependencies => true,
|
99
|
-
:env_shebang => true,
|
100
|
-
:wrappers => true,
|
101
|
-
:bin_dir => @bindir
|
102
|
-
))
|
103
|
-
installer.install
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|