bundler 0.9.11 → 0.9.12
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/CHANGELOG.md +109 -0
- data/{README.markdown → README.md} +12 -5
- data/ROADMAP.md +51 -0
- data/lib/bundler.rb +2 -1
- data/lib/bundler/cli.rb +7 -4
- data/lib/bundler/definition.rb +0 -14
- data/lib/bundler/environment.rb +96 -11
- data/lib/bundler/index.rb +31 -16
- data/lib/bundler/installer.rb +19 -52
- data/lib/bundler/resolver.rb +1 -9
- data/lib/bundler/runtime.rb +6 -75
- data/lib/bundler/source.rb +11 -7
- data/lib/bundler/spec_set.rb +65 -0
- data/lib/bundler/specification.rb +2 -2
- data/lib/bundler/templates/environment.erb +6 -1
- metadata +9 -8
- data/ROADMAP.textile +0 -51
data/CHANGELOG.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
## 0.9.12 (???)
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- perform a topological sort on resolved gems (#191)
|
6
|
+
|
7
|
+
## 0.9.11 (March 9, 2010)
|
8
|
+
|
9
|
+
- added roadmap with future development plans
|
10
|
+
|
11
|
+
Features:
|
12
|
+
|
13
|
+
- install command can take the path to the gemfile with --gemfile (#125)
|
14
|
+
- unknown command line options are now rejected (#163)
|
15
|
+
- exec command hugely sped up while locked (#177)
|
16
|
+
- show command prints the install path if you pass it a gem name (#148)
|
17
|
+
- open command edits an installed gem with $EDITOR (#148)
|
18
|
+
- Gemfile allows assigning an array of groups to a gem (#114)
|
19
|
+
- Gemfile allows :tag option on :git sources
|
20
|
+
- improve backtraces when a gemspec is invalid
|
21
|
+
- improve performance by installing gems from the cache if present
|
22
|
+
|
23
|
+
Bugfixes:
|
24
|
+
|
25
|
+
- normalize parameters to Bundler.require (#153)
|
26
|
+
- check now checks installed gems rather than cached gems (#162)
|
27
|
+
- don't update the gem index when installing after locking (#169)
|
28
|
+
- bundle parenthesises arguments for 1.8.6 (#179)
|
29
|
+
- gems can now be assigned to multiple groups without problems (#135)
|
30
|
+
- fix the warning when building extensions for a gem from git with Rubygems 1.3.6
|
31
|
+
- fix a Dependency.to_yaml error due to accidentally including sources and groups
|
32
|
+
- don't reinstall packed gems
|
33
|
+
- fix gems with git sources that are private repositories
|
34
|
+
|
35
|
+
## 0.9.10 (March 1, 2010)
|
36
|
+
|
37
|
+
- depends on Rubygems 1.3.6
|
38
|
+
|
39
|
+
Bugfixes:
|
40
|
+
|
41
|
+
- support locking after install --without
|
42
|
+
- don't reinstall gems from the cache if they're already in the bundle
|
43
|
+
- fixes for Ruby 1.8.7 and 1.9
|
44
|
+
|
45
|
+
## 0.9.9 (February 25, 2010)
|
46
|
+
|
47
|
+
Bugfixes:
|
48
|
+
|
49
|
+
- don't die if GEM_HOME is an empty string
|
50
|
+
- fixes for Ruby 1.8.6 and 1.9
|
51
|
+
|
52
|
+
## 0.9.8 (February 23, 2010)
|
53
|
+
|
54
|
+
Features:
|
55
|
+
|
56
|
+
- pack command which both caches and locks
|
57
|
+
- descriptive error if a cached gem is missing
|
58
|
+
- remember the --without option after installing
|
59
|
+
- expand paths given in the Gemfile via the :path option
|
60
|
+
- add block syntax to the git and group options in the Gemfile
|
61
|
+
- support gems with extensions that don't admit they depend on rake
|
62
|
+
- generate gems using gem build gemspec so git gems can have native extensions
|
63
|
+
- print a useful warning if building a gem fails
|
64
|
+
- allow manual configuration via BUNDLE_PATH
|
65
|
+
|
66
|
+
Bugfixes:
|
67
|
+
|
68
|
+
- eval gemspecs in the gem directory so relative paths work
|
69
|
+
- make default spec for git sources valid
|
70
|
+
- don't reinstall gems that are already packed
|
71
|
+
|
72
|
+
## 0.9.7 (February 17, 2010)
|
73
|
+
|
74
|
+
Bugfixes:
|
75
|
+
|
76
|
+
- don't say that a gem from an excluded group is "installing"
|
77
|
+
- improve crippling rubygems in locked scenarios
|
78
|
+
|
79
|
+
## 0.9.6 (February 16, 2010)
|
80
|
+
|
81
|
+
Features:
|
82
|
+
|
83
|
+
- allow String group names
|
84
|
+
- a number of improvements in the documentation and error messages
|
85
|
+
|
86
|
+
Bugfixes:
|
87
|
+
|
88
|
+
- set SourceIndex#spec_dirs to solve a problem involving Rails 2.3 in unlocked mode
|
89
|
+
- ensure Rubygems is fully loaded in Ruby 1.9 before patching it
|
90
|
+
- fix `bundle install` for a locked app without a .bundle directory
|
91
|
+
- require gems in the order that the resolver determines
|
92
|
+
- make the tests platform agnostic so we can confirm that they're green on JRuby
|
93
|
+
- fixes for Ruby 1.9
|
94
|
+
|
95
|
+
## 0.9.5 (Feburary 12, 2010)
|
96
|
+
|
97
|
+
Features:
|
98
|
+
|
99
|
+
- added support for :path => "relative/path"
|
100
|
+
- added support for older versions of git
|
101
|
+
- added `bundle install --disable-shared-gems`
|
102
|
+
- Bundler.require fails silently if a library does not have a file on the load path with its name
|
103
|
+
- Basic support for multiple rubies by namespacing the default bundle path using the version and engine
|
104
|
+
|
105
|
+
Bugfixes:
|
106
|
+
|
107
|
+
- if the bundle is locked and .bundle/environment.rb is not present when Bundler.setup is called, generate it
|
108
|
+
- same if it's not present with `bundle check`
|
109
|
+
- same if it's not present with `bundle install`
|
@@ -79,7 +79,7 @@ Note that Bundler adds all the gems without an explicit group name to the
|
|
79
79
|
Groups are involved in a number of scenarios:
|
80
80
|
|
81
81
|
1. When installing gems using bundle install, you can choose to leave
|
82
|
-
out any group by specifying `--without
|
82
|
+
out any group by specifying `--without group1 group2`. This can be
|
83
83
|
helpful if, for instance, you have a gem that you cannot compile
|
84
84
|
in certain environments.
|
85
85
|
2. When setting up load paths using Bundler.setup, Bundler will, by
|
@@ -208,8 +208,8 @@ API calls in your Gemfile, and some workarounds if you are using Rails 2.3.
|
|
208
208
|
### Rails 2.3
|
209
209
|
|
210
210
|
Using Bundler 0.9 with Rails 2.3 requires adding a preinitializer, and
|
211
|
-
making a few changes to boot.rb.
|
212
|
-
[
|
211
|
+
making a few changes to boot.rb. A detailed description of the changes
|
212
|
+
needed can be found in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/).
|
213
213
|
|
214
214
|
### Gemfile Removals
|
215
215
|
|
@@ -274,7 +274,7 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs:
|
|
274
274
|
|
275
275
|
## More information
|
276
276
|
|
277
|
-
Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/).
|
277
|
+
Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). Using Bundler with a Rails 2.3.5 app is explained with more detail in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/).
|
278
278
|
|
279
279
|
### Deploying to memory-constrained servers
|
280
280
|
|
@@ -286,12 +286,19 @@ Any remaining questions may be asked via IRC in [#carlhuda](irc://irc.freenode.n
|
|
286
286
|
|
287
287
|
## Reporting bugs
|
288
288
|
|
289
|
-
|
289
|
+
Before reporting a bug, try these troubleshooting steps:
|
290
|
+
|
291
|
+
rm -rf ~/.bundle/ ~/.gem/ .bundle/ Gemfile.lock
|
292
|
+
bundle install
|
293
|
+
|
294
|
+
If you are still having problems, please report bugs to the github issue tracker for the project, located at [http://github.com/carlhuda/bundler/issues/](http://github.com/carlhuda/bundler/issues/).
|
290
295
|
|
291
296
|
The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket:
|
292
297
|
|
293
298
|
- Whether you have locked or not
|
294
299
|
- What version of bundler you are using
|
300
|
+
- What version of Ruby you are using
|
301
|
+
- Whether you are using RVM, and if so what version
|
295
302
|
- Your Gemfile
|
296
303
|
- The command you ran to generate exception(s)
|
297
304
|
- The exception backtrace(s)
|
data/ROADMAP.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
We will be releasing one more point release (0.10.x) followed by 1.0. While
|
2
|
+
the following reflects our current thinking, critical bugs may alter it
|
3
|
+
somewhat.
|
4
|
+
|
5
|
+
# 0.10
|
6
|
+
|
7
|
+
- No breaking changes to the Gemfile are expected
|
8
|
+
- We expect to modify the format of Gemfile.lock.
|
9
|
+
- This should be the final change; it will not change for 1.0
|
10
|
+
- The Gemfile.lock generated by 0.9 will continue to work until 1.0
|
11
|
+
- If you use Bundler 0.10, we will transparently update the format
|
12
|
+
- This means: you will not be able to upgrade a locked app
|
13
|
+
directly from 0.9 to 1.0.
|
14
|
+
- Bundler 0.10 will automatically generate Gemfile.lock when any
|
15
|
+
resolve is successful.
|
16
|
+
- bundle install will conservatively update Gemfile.lock from the
|
17
|
+
last successful resolve if the Gemfile has been modified since
|
18
|
+
the last use of bundler.
|
19
|
+
- This means that adding a new gem to the Gemfile that does not
|
20
|
+
conflict with existing gems will not force an update of other
|
21
|
+
gems.
|
22
|
+
- This also means that we will not force an update to previously
|
23
|
+
resolved dependencies as long as they are compatible with some
|
24
|
+
valid version of the new dependency.
|
25
|
+
- When removing a gem, bundle install will simply remove it, without
|
26
|
+
recalculating all dependencies.
|
27
|
+
- We will be adding `bundle update` for the case where you -do-
|
28
|
+
wish to re-resolve all dependencies and update everything to the
|
29
|
+
latest version.
|
30
|
+
- bundle update will also take a gem name, if you want to force
|
31
|
+
an update to just a single gem (and its dependencies).
|
32
|
+
- Add a way to install dependencies that require build options
|
33
|
+
- Add a way to specify groups that are opt-in at install-time,
|
34
|
+
rather than opt-out.
|
35
|
+
- Some additional features that we have tagged for 0.10. For up
|
36
|
+
to date information, please visit
|
37
|
+
http://github.com/carlhuda/bundler/issues/labels/0.10
|
38
|
+
|
39
|
+
# 1.0
|
40
|
+
|
41
|
+
- No breaking changes to the Gemfile are expected
|
42
|
+
- No breaking changes to the Gemfile.lock are expected
|
43
|
+
- No major changes to the workflow are expected
|
44
|
+
- Reduce open bug count to 0
|
45
|
+
- Some additional features that require more thought. For details,
|
46
|
+
see http://github.com/carlhuda/bundler/issues/labels/1.0
|
47
|
+
|
48
|
+
# No Breaking changes
|
49
|
+
|
50
|
+
We expect no breaking changes of the Gemfile, Gemfile.lock, or
|
51
|
+
basic workflow for 1.x releases.
|
data/lib/bundler.rb
CHANGED
@@ -4,7 +4,7 @@ require 'yaml'
|
|
4
4
|
require 'bundler/rubygems_ext'
|
5
5
|
|
6
6
|
module Bundler
|
7
|
-
VERSION = "0.9.
|
7
|
+
VERSION = "0.9.12"
|
8
8
|
|
9
9
|
autoload :Definition, 'bundler/definition'
|
10
10
|
autoload :Dependency, 'bundler/dependency'
|
@@ -17,6 +17,7 @@ module Bundler
|
|
17
17
|
autoload :Runtime, 'bundler/runtime'
|
18
18
|
autoload :Settings, 'bundler/settings'
|
19
19
|
autoload :SharedHelpers, 'bundler/shared_helpers'
|
20
|
+
autoload :SpecSet, 'bundler/spec_set'
|
20
21
|
autoload :Source, 'bundler/source'
|
21
22
|
autoload :Specification, 'bundler/specification'
|
22
23
|
autoload :UI, 'bundler/ui'
|
data/lib/bundler/cli.rb
CHANGED
@@ -38,11 +38,12 @@ module Bundler
|
|
38
38
|
Bundler.ui.error "Try running `bundle install`"
|
39
39
|
exit 1
|
40
40
|
else
|
41
|
-
not_installed = env.
|
41
|
+
not_installed = env.requested_specs.select { |spec| !spec.loaded_from }
|
42
42
|
|
43
43
|
if not_installed.any?
|
44
44
|
not_installed.each { |s| Bundler.ui.error "#{s.name} (#{s.version}) is cached, but not installed" }
|
45
45
|
Bundler.ui.error "Try running `bundle install`"
|
46
|
+
exit 1
|
46
47
|
else
|
47
48
|
Bundler.ui.info "The Gemfile's dependencies are satisfied"
|
48
49
|
end
|
@@ -68,11 +69,13 @@ module Bundler
|
|
68
69
|
remove_lockfiles if options[:relock]
|
69
70
|
|
70
71
|
Installer.install(Bundler.root, Bundler.definition, opts)
|
71
|
-
# Ensures that .bundle/environment.rb exists
|
72
|
-
# TODO: Figure out a less hackish way to do this
|
73
|
-
Bundler.load
|
74
72
|
|
75
73
|
lock if options[:relock]
|
74
|
+
rescue GemNotFound => e
|
75
|
+
if Bundler.definition.sources.empty?
|
76
|
+
Bundler.ui.warn "Your Gemfile doesn't have any sources. You can add one with a line like 'source :gemcutter'"
|
77
|
+
end
|
78
|
+
raise e
|
76
79
|
end
|
77
80
|
|
78
81
|
desc "lock", "Locks the bundle to the current set of dependencies, including all child dependencies."
|
data/lib/bundler/definition.rb
CHANGED
@@ -32,20 +32,6 @@ module Bundler
|
|
32
32
|
@sources = sources
|
33
33
|
end
|
34
34
|
|
35
|
-
def local_index
|
36
|
-
@local_index ||= begin
|
37
|
-
index = Index.new
|
38
|
-
|
39
|
-
sources.each do |source|
|
40
|
-
next unless source.respond_to?(:local_specs)
|
41
|
-
index = source.local_specs.merge(index)
|
42
|
-
end
|
43
|
-
|
44
|
-
index = Index.from_installed_gems.merge(index)
|
45
|
-
Index.from_cached_specs("#{Bundler.bundle_path}/cache").merge(index)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
35
|
def groups
|
50
36
|
dependencies.map { |d| d.groups }.flatten.uniq
|
51
37
|
end
|
data/lib/bundler/environment.rb
CHANGED
@@ -9,22 +9,107 @@ module Bundler
|
|
9
9
|
@definition = definition
|
10
10
|
end
|
11
11
|
|
12
|
+
def index
|
13
|
+
@index ||= Index.build do |idx|
|
14
|
+
idx.use runtime_gems
|
15
|
+
idx.use Index.cached_gems
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def requested_specs
|
20
|
+
@requested_specs ||= begin
|
21
|
+
groups = @definition.groups - Bundler.settings.without
|
22
|
+
groups.map! { |g| g.to_sym }
|
23
|
+
groups.any? ? specs_for(groups) : []
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
12
27
|
private
|
13
28
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
29
|
+
def runtime_gems
|
30
|
+
@runtime_gems ||= Index.build do |i|
|
31
|
+
sources.each do |s|
|
32
|
+
i.use s.local_specs if s.respond_to?(:local_specs)
|
33
|
+
end
|
34
|
+
|
35
|
+
i.use Index.installed_gems
|
18
36
|
end
|
19
|
-
specs
|
20
37
|
end
|
21
38
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
39
|
+
def specs_for(groups)
|
40
|
+
deps = dependencies.select { |d| (d.groups & groups).any? }
|
41
|
+
# deps.any? ? specs.for(deps) : specs
|
42
|
+
specs.for(deps)
|
43
|
+
end
|
44
|
+
|
45
|
+
# ==== Locking
|
46
|
+
|
47
|
+
def locked?
|
48
|
+
File.exist?("#{root}/Gemfile.lock")
|
49
|
+
end
|
50
|
+
|
51
|
+
def write_rb_lock
|
52
|
+
shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__))
|
53
|
+
template = File.read(File.expand_path("../templates/environment.erb", __FILE__))
|
54
|
+
erb = ERB.new(template, nil, '-')
|
55
|
+
FileUtils.mkdir_p(rb_lock_file.dirname)
|
56
|
+
File.open(rb_lock_file, 'w') do |f|
|
57
|
+
f.puts erb.result(binding)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def rb_lock_file
|
62
|
+
root.join(".bundle/environment.rb")
|
63
|
+
end
|
64
|
+
|
65
|
+
def gemfile_fingerprint
|
66
|
+
Digest::SHA1.hexdigest(File.read("#{root}/Gemfile"))
|
67
|
+
end
|
68
|
+
|
69
|
+
def specs_for_lock_file
|
70
|
+
requested_specs.map do |s|
|
71
|
+
hash = {
|
72
|
+
:name => s.name,
|
73
|
+
:load_paths => s.load_paths
|
74
|
+
}
|
75
|
+
if s.respond_to?(:virtual) && s.virtual
|
76
|
+
hash[:virtual_spec] = s.to_ruby
|
77
|
+
else
|
78
|
+
hash[:loaded_from] = s.loaded_from.to_s
|
79
|
+
end
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def autorequires_for_groups(*groups)
|
85
|
+
groups.map! { |g| g.to_sym }
|
86
|
+
autorequires = Hash.new { |h,k| h[k] = [] }
|
87
|
+
|
88
|
+
ordered_deps = []
|
89
|
+
specs = groups.any? ? specs_for(groups) : requested_specs
|
90
|
+
specs.each do |g|
|
91
|
+
dep = @definition.dependencies.find{|d| d.name == g.name }
|
92
|
+
ordered_deps << dep if dep && !ordered_deps.include?(dep)
|
93
|
+
end
|
94
|
+
|
95
|
+
ordered_deps.each do |dep|
|
96
|
+
dep.groups.each do |group|
|
97
|
+
# If there is no autorequire, then rescue from
|
98
|
+
# autorequiring the gems name
|
99
|
+
if dep.autorequire
|
100
|
+
dep.autorequire.each do |file|
|
101
|
+
autorequires[group] << [file, true]
|
102
|
+
end
|
103
|
+
else
|
104
|
+
autorequires[group] << [dep.name, false]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if groups.empty?
|
110
|
+
autorequires
|
111
|
+
else
|
112
|
+
groups.inject({}) { |h,g| h[g] = autorequires[g]; h }
|
28
113
|
end
|
29
114
|
end
|
30
115
|
end
|
data/lib/bundler/index.rb
CHANGED
@@ -1,9 +1,33 @@
|
|
1
1
|
module Bundler
|
2
2
|
class Index
|
3
|
-
def self.
|
3
|
+
def self.build
|
4
|
+
i = new
|
5
|
+
yield i
|
6
|
+
i
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.installed_gems
|
4
10
|
Source::SystemGems.new.specs
|
5
11
|
end
|
6
12
|
|
13
|
+
def self.cached_gems
|
14
|
+
build do |idx|
|
15
|
+
idx.use application_cached_gems
|
16
|
+
idx.use system_cached_gems
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.application_cached_gems
|
21
|
+
path = "#{Bundler.root}/vendor/cache"
|
22
|
+
if File.directory?(path)
|
23
|
+
from_cached_specs(path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.system_cached_gems
|
28
|
+
from_cached_specs("#{Bundler.bundle_path}/cache")
|
29
|
+
end
|
30
|
+
|
7
31
|
def self.from_cached_specs(path)
|
8
32
|
Source::GemCache.new("path" => path).specs
|
9
33
|
end
|
@@ -52,28 +76,19 @@ module Bundler
|
|
52
76
|
end
|
53
77
|
end
|
54
78
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
79
|
+
def use(other)
|
80
|
+
return unless other
|
81
|
+
other.each do |s|
|
82
|
+
next if search_by_spec(s).any?
|
83
|
+
@specs[s.name] << s
|
58
84
|
end
|
59
85
|
self
|
60
86
|
end
|
61
87
|
|
62
|
-
def merge(other)
|
63
|
-
dup.merge!(other)
|
64
|
-
end
|
65
|
-
|
66
|
-
def freeze
|
67
|
-
@specs.each do |k,v|
|
68
|
-
v.freeze
|
69
|
-
end
|
70
|
-
super
|
71
|
-
end
|
72
|
-
|
73
88
|
private
|
74
89
|
|
75
90
|
def search_by_spec(spec)
|
76
|
-
@specs[spec.name].select { |s| s.version == spec.version }
|
91
|
+
@specs[spec.name].select { |s| s.version == spec.version && s.platform == spec.platform }
|
77
92
|
end
|
78
93
|
|
79
94
|
def search_by_dependency(dependency)
|
data/lib/bundler/installer.rb
CHANGED
@@ -21,20 +21,22 @@ module Bundler
|
|
21
21
|
specs.each do |spec|
|
22
22
|
spec.source.fetch(spec) if spec.source.respond_to?(:fetch)
|
23
23
|
|
24
|
-
|
24
|
+
unless requested_specs.include?(spec)
|
25
25
|
Bundler.ui.debug " * Not in requested group; skipping."
|
26
26
|
next
|
27
27
|
end
|
28
28
|
|
29
|
-
#
|
30
|
-
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) from #{spec.source} "
|
31
|
-
# end
|
29
|
+
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) from #{spec.source} "
|
32
30
|
|
33
31
|
spec.source.install(spec)
|
34
32
|
|
35
33
|
Bundler.ui.info ""
|
36
34
|
end
|
37
35
|
|
36
|
+
if locked?
|
37
|
+
write_rb_lock
|
38
|
+
end
|
39
|
+
|
38
40
|
Bundler.ui.confirm "Your bundle is complete!"
|
39
41
|
end
|
40
42
|
|
@@ -47,7 +49,7 @@ module Bundler
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def specs
|
50
|
-
@specs ||=
|
52
|
+
@specs ||= resolve_locally || resolve_remotely
|
51
53
|
end
|
52
54
|
|
53
55
|
private
|
@@ -67,7 +69,7 @@ module Bundler
|
|
67
69
|
end
|
68
70
|
|
69
71
|
# Run a resolve against the locally available gems
|
70
|
-
specs = Resolver.resolve(actual_dependencies,
|
72
|
+
specs = Resolver.resolve(actual_dependencies, index, source_requirements)
|
71
73
|
|
72
74
|
# Simple logic for now. Can improve later.
|
73
75
|
specs.length == actual_dependencies.length && specs
|
@@ -76,7 +78,7 @@ module Bundler
|
|
76
78
|
end
|
77
79
|
|
78
80
|
def resolve_remotely
|
79
|
-
|
81
|
+
remote_index # trigger building the index
|
80
82
|
Bundler.ui.info "Resolving dependencies"
|
81
83
|
source_requirements = {}
|
82
84
|
actual_dependencies.each do |dep|
|
@@ -84,7 +86,7 @@ module Bundler
|
|
84
86
|
source_requirements[dep.name] = dep.source.specs
|
85
87
|
end
|
86
88
|
|
87
|
-
specs = Resolver.resolve(actual_dependencies,
|
89
|
+
specs = Resolver.resolve(actual_dependencies, remote_index, source_requirements)
|
88
90
|
specs
|
89
91
|
end
|
90
92
|
|
@@ -92,58 +94,23 @@ module Bundler
|
|
92
94
|
dep.requirement.requirements.any? { |op,_| op != '=' }
|
93
95
|
end
|
94
96
|
|
95
|
-
def
|
96
|
-
@
|
97
|
-
|
98
|
-
|
99
|
-
rg_sources = sources.select { |s| s.is_a?(Source::Rubygems) }
|
100
|
-
other_sources = sources.select { |s| !s.is_a?(Source::Rubygems) }
|
97
|
+
def remote_index
|
98
|
+
@remote_index ||= Index.build do |idx|
|
99
|
+
rubygems, other = sources.partition { |s| Source::Rubygems === s }
|
101
100
|
|
102
|
-
|
103
|
-
i = source.specs
|
101
|
+
other.each do |source|
|
104
102
|
Bundler.ui.debug "Source: Processing index"
|
105
|
-
|
103
|
+
idx.use source.specs
|
106
104
|
end
|
107
105
|
|
108
|
-
|
109
|
-
|
106
|
+
idx.use Index.installed_gems
|
107
|
+
idx.use Index.cached_gems
|
110
108
|
|
111
|
-
|
112
|
-
index = cache_source.specs.merge(index)
|
113
|
-
end
|
114
|
-
|
115
|
-
rg_sources.each do |source|
|
116
|
-
i = source.specs
|
109
|
+
rubygems.each do |source|
|
117
110
|
Bundler.ui.debug "Source: Processing index"
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
index
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def local_index
|
126
|
-
@local_index ||= begin
|
127
|
-
index = Index.new
|
128
|
-
|
129
|
-
sources.each do |source|
|
130
|
-
next unless source.respond_to?(:local_specs)
|
131
|
-
index = source.local_specs.merge(index)
|
132
|
-
end
|
133
|
-
|
134
|
-
index = Index.from_installed_gems.merge(index)
|
135
|
-
|
136
|
-
if File.directory?("#{root}/vendor/cache")
|
137
|
-
index = cache_source.specs.merge(index).freeze
|
111
|
+
idx.use source.specs
|
138
112
|
end
|
139
|
-
|
140
|
-
Index.from_cached_specs("#{Bundler.bundle_path}/cache").merge(index)
|
141
113
|
end
|
142
114
|
end
|
143
|
-
|
144
|
-
def cache_source
|
145
|
-
Source::GemCache.new("path" => "#{root}/vendor/cache")
|
146
|
-
end
|
147
|
-
|
148
115
|
end
|
149
116
|
end
|
data/lib/bundler/resolver.rb
CHANGED
@@ -52,15 +52,7 @@ module Bundler
|
|
52
52
|
raise VersionConflict, "No compatible versions could be found for required dependencies:\n #{output}"
|
53
53
|
nil
|
54
54
|
end
|
55
|
-
|
56
|
-
# Dependency ordering was busted anyway. This will be revisted in 0.10
|
57
|
-
ordered = []
|
58
|
-
ordered << result['rake']
|
59
|
-
ordered.concat result.values
|
60
|
-
ordered.compact!
|
61
|
-
ordered.uniq!
|
62
|
-
ordered
|
63
|
-
end
|
55
|
+
SpecSet.new(result.values)
|
64
56
|
end
|
65
57
|
|
66
58
|
def initialize(index, source_requirements)
|
data/lib/bundler/runtime.rb
CHANGED
@@ -15,12 +15,16 @@ module Bundler
|
|
15
15
|
# Has to happen first
|
16
16
|
clean_load_path
|
17
17
|
|
18
|
-
specs = specs_for(
|
18
|
+
specs = groups.any? ? specs_for(groups) : requested_specs
|
19
19
|
|
20
20
|
cripple_rubygems(specs)
|
21
21
|
|
22
22
|
# Activate the specs
|
23
23
|
specs.each do |spec|
|
24
|
+
unless spec.loaded_from
|
25
|
+
raise GemNotFound, "#{spec.full_name} is not installed. Try running `bundle install`."
|
26
|
+
end
|
27
|
+
|
24
28
|
Gem.loaded_specs[spec.name] = spec
|
25
29
|
$LOAD_PATH.unshift(*spec.load_paths)
|
26
30
|
end
|
@@ -63,10 +67,6 @@ module Bundler
|
|
63
67
|
Bundler.ui.info("The bundle is now locked. Use `bundle show` to list the gems in the environment.")
|
64
68
|
end
|
65
69
|
|
66
|
-
def locked?
|
67
|
-
File.exist?("#{root}/Gemfile.lock") || File.exist?("#{root}/.bundle/environment.rb")
|
68
|
-
end
|
69
|
-
|
70
70
|
def dependencies_for(*groups)
|
71
71
|
if groups.empty?
|
72
72
|
dependencies
|
@@ -75,13 +75,6 @@ module Bundler
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def specs_for(*groups)
|
79
|
-
groups = @definition.groups if groups.empty?
|
80
|
-
groups -= Bundler.settings.without
|
81
|
-
groups.map! { |g| g.to_sym }
|
82
|
-
specs.select { |s| (s.groups & groups).any? }
|
83
|
-
end
|
84
|
-
|
85
78
|
def specs
|
86
79
|
@specs ||= begin
|
87
80
|
source_requirements = {}
|
@@ -90,16 +83,12 @@ module Bundler
|
|
90
83
|
source_requirements[dep.name] = dep.source.local_specs
|
91
84
|
end
|
92
85
|
|
93
|
-
|
86
|
+
Resolver.resolve(@definition.actual_dependencies, index, source_requirements)
|
94
87
|
end
|
95
88
|
end
|
96
89
|
|
97
90
|
alias gems specs
|
98
91
|
|
99
|
-
def index
|
100
|
-
@definition.local_index
|
101
|
-
end
|
102
|
-
|
103
92
|
def cache
|
104
93
|
cache_path = "#{root}/vendor/cache/"
|
105
94
|
FileUtils.mkdir_p(cache_path)
|
@@ -126,20 +115,6 @@ module Bundler
|
|
126
115
|
specs.map { |s| s.load_paths }.flatten
|
127
116
|
end
|
128
117
|
|
129
|
-
def rb_lock_file
|
130
|
-
root.join(".bundle/environment.rb")
|
131
|
-
end
|
132
|
-
|
133
|
-
def write_rb_lock
|
134
|
-
shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__))
|
135
|
-
template = File.read(File.expand_path("../templates/environment.erb", __FILE__))
|
136
|
-
erb = ERB.new(template, nil, '-')
|
137
|
-
FileUtils.mkdir_p(rb_lock_file.dirname)
|
138
|
-
File.open(rb_lock_file, 'w') do |f|
|
139
|
-
f.puts erb.result(binding)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
118
|
def write_yml_lock
|
144
119
|
yml = details.to_yaml
|
145
120
|
File.open("#{root}/Gemfile.lock", 'w') do |f|
|
@@ -165,49 +140,5 @@ module Bundler
|
|
165
140
|
end
|
166
141
|
details
|
167
142
|
end
|
168
|
-
|
169
|
-
def gemfile_fingerprint
|
170
|
-
Digest::SHA1.hexdigest(File.read("#{root}/Gemfile"))
|
171
|
-
end
|
172
|
-
|
173
|
-
def specs_for_lock_file
|
174
|
-
specs_for.map do |s|
|
175
|
-
hash = {}
|
176
|
-
hash[:loaded_from] = s.loaded_from.to_s
|
177
|
-
hash[:load_paths] = s.load_paths
|
178
|
-
hash
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def autorequires_for_groups(*groups)
|
183
|
-
groups.map! { |g| g.to_sym }
|
184
|
-
autorequires = Hash.new { |h,k| h[k] = [] }
|
185
|
-
|
186
|
-
ordered_deps = []
|
187
|
-
specs_for(*groups).each do |g|
|
188
|
-
dep = @definition.dependencies.find{|d| d.name == g.name }
|
189
|
-
ordered_deps << dep if dep && !ordered_deps.include?(dep)
|
190
|
-
end
|
191
|
-
|
192
|
-
ordered_deps.each do |dep|
|
193
|
-
dep.groups.each do |group|
|
194
|
-
# If there is no autorequire, then rescue from
|
195
|
-
# autorequiring the gems name
|
196
|
-
if dep.autorequire
|
197
|
-
dep.autorequire.each do |file|
|
198
|
-
autorequires[group] << [file, true]
|
199
|
-
end
|
200
|
-
else
|
201
|
-
autorequires[group] << [dep.name, false]
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
if groups.empty?
|
207
|
-
autorequires
|
208
|
-
else
|
209
|
-
groups.inject({}) { |h,g| h[g] = autorequires[g]; h }
|
210
|
-
end
|
211
|
-
end
|
212
143
|
end
|
213
144
|
end
|
data/lib/bundler/source.rb
CHANGED
@@ -40,6 +40,8 @@ module Bundler
|
|
40
40
|
:bin_dir => "#{Gem.dir}/bin"
|
41
41
|
|
42
42
|
installer.install
|
43
|
+
|
44
|
+
spec.loaded_from = "#{Gem.dir}/specifications/#{spec.full_name}.gemspec"
|
43
45
|
end
|
44
46
|
|
45
47
|
private
|
@@ -62,7 +64,7 @@ module Bundler
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
|
-
index
|
67
|
+
index
|
66
68
|
ensure
|
67
69
|
Gem.sources = old
|
68
70
|
end
|
@@ -131,6 +133,7 @@ module Bundler
|
|
131
133
|
:bin_dir => "#{Gem.dir}/bin"
|
132
134
|
|
133
135
|
installer.install
|
136
|
+
spec.loaded_from = "#{Gem.dir}/specifications/#{spec.full_name}.gemspec"
|
134
137
|
end
|
135
138
|
end
|
136
139
|
|
@@ -152,6 +155,7 @@ module Bundler
|
|
152
155
|
s.version = Gem::Version.new(options["version"])
|
153
156
|
s.summary = "Fake gemspec for #{options["name"]}"
|
154
157
|
s.relative_loaded_from = "#{options["name"]}.gemspec"
|
158
|
+
s.virtual = true
|
155
159
|
end
|
156
160
|
end
|
157
161
|
end
|
@@ -180,7 +184,7 @@ module Bundler
|
|
180
184
|
raise PathError, "The path `#{path}` does not exist."
|
181
185
|
end
|
182
186
|
|
183
|
-
index
|
187
|
+
index
|
184
188
|
end
|
185
189
|
|
186
190
|
def local_specs
|
@@ -252,7 +256,7 @@ module Bundler
|
|
252
256
|
# Start by making sure the git cache is up to date
|
253
257
|
cache
|
254
258
|
checkout
|
255
|
-
|
259
|
+
local_specs
|
256
260
|
end
|
257
261
|
|
258
262
|
def install(spec)
|
@@ -312,17 +316,17 @@ module Bundler
|
|
312
316
|
def cache
|
313
317
|
if cache_path.exist?
|
314
318
|
Bundler.ui.info "Updating #{uri}"
|
315
|
-
in_cache { git "fetch --quiet #{uri} master:master" }
|
319
|
+
in_cache { git "fetch --quiet '#{uri}' master:master" }
|
316
320
|
else
|
317
321
|
Bundler.ui.info "Fetching #{uri}"
|
318
322
|
FileUtils.mkdir_p(cache_path.dirname)
|
319
|
-
git "clone #{uri} #{cache_path} --bare --no-hardlinks"
|
323
|
+
git "clone '#{uri}' '#{cache_path}' --bare --no-hardlinks"
|
320
324
|
end
|
321
325
|
end
|
322
326
|
|
323
327
|
def checkout
|
324
|
-
unless File.exist?("
|
325
|
-
|
328
|
+
unless File.exist?(path.join(".git"))
|
329
|
+
git "clone --no-checkout '#{cache_path}' '#{path}'"
|
326
330
|
end
|
327
331
|
Dir.chdir(path) do
|
328
332
|
git "fetch --quiet"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'tsort'
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
class SpecSet
|
5
|
+
include TSort, Enumerable
|
6
|
+
|
7
|
+
def initialize(specs)
|
8
|
+
@specs = specs.sort_by { |s| s.name }
|
9
|
+
end
|
10
|
+
|
11
|
+
def each
|
12
|
+
sorted.each { |s| yield s }
|
13
|
+
end
|
14
|
+
|
15
|
+
def length
|
16
|
+
@specs.length
|
17
|
+
end
|
18
|
+
|
19
|
+
def for(*deps)
|
20
|
+
specs = {}
|
21
|
+
deps.flatten.each do |dep|
|
22
|
+
current = lookup[dep.respond_to?(:name) ? dep.name : dep]
|
23
|
+
append_subgraph(specs, current)
|
24
|
+
end
|
25
|
+
|
26
|
+
sorted.select { |s| specs[s.name] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_a
|
30
|
+
sorted.dup
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def append_subgraph(specs, current)
|
36
|
+
return if specs[current.name]
|
37
|
+
specs[current.name] = true
|
38
|
+
current.dependencies.each do |dep|
|
39
|
+
next unless dep.type == :runtime
|
40
|
+
append_subgraph(specs, lookup[dep.name])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def sorted
|
45
|
+
@sorted ||= ([lookup['rake']] + tsort).compact.uniq
|
46
|
+
end
|
47
|
+
|
48
|
+
def lookup
|
49
|
+
@lookup ||= Hash.new do |h,k|
|
50
|
+
h[k] = @specs.find { |s| s.name == k }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def tsort_each_node
|
55
|
+
@specs.each { |s| yield s }
|
56
|
+
end
|
57
|
+
|
58
|
+
def tsort_each_child(s)
|
59
|
+
s.dependencies.sort_by { |d| d.name }.each do |d|
|
60
|
+
next if d.type == :development
|
61
|
+
yield lookup[d.name]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bundler
|
2
2
|
class Specification < Gem::Specification
|
3
|
-
attr_accessor :relative_loaded_from
|
3
|
+
attr_accessor :relative_loaded_from, :virtual
|
4
4
|
|
5
5
|
def self.from_gemspec(gemspec)
|
6
6
|
spec = allocate
|
@@ -12,7 +12,7 @@ module Bundler
|
|
12
12
|
|
13
13
|
def loaded_from
|
14
14
|
return super unless relative_loaded_from
|
15
|
-
source.path.join(relative_loaded_from)
|
15
|
+
source.path.join(relative_loaded_from).to_s
|
16
16
|
end
|
17
17
|
|
18
18
|
def full_gem_path
|
@@ -14,7 +14,12 @@ module Bundler
|
|
14
14
|
<%= spec.inspect %>,
|
15
15
|
<% end -%>
|
16
16
|
].map do |hash|
|
17
|
-
|
17
|
+
if hash[:loaded_from]
|
18
|
+
dir = File.dirname(hash[:loaded_from])
|
19
|
+
spec = Dir.chdir(dir){ eval(File.read(hash[:loaded_from]), binding, hash[:loaded_from]) }
|
20
|
+
else
|
21
|
+
spec = eval(hash[:virtual_spec], binding, "<virtual spec for '#{hash[:name]}'>")
|
22
|
+
end
|
18
23
|
spec.loaded_from = hash[:loaded_from]
|
19
24
|
spec.require_paths = hash[:load_paths]
|
20
25
|
spec
|
metadata
CHANGED
@@ -5,17 +5,18 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 12
|
9
|
+
version: 0.9.12
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Carl Lerche
|
13
13
|
- Yehuda Katz
|
14
|
+
- "Andr\xC3\xA9 Arko"
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2010-03-
|
19
|
+
date: 2010-03-17 00:00:00 -07:00
|
19
20
|
default_executable:
|
20
21
|
dependencies: []
|
21
22
|
|
@@ -45,6 +46,7 @@ files:
|
|
45
46
|
- lib/bundler/setup.rb
|
46
47
|
- lib/bundler/shared_helpers.rb
|
47
48
|
- lib/bundler/source.rb
|
49
|
+
- lib/bundler/spec_set.rb
|
48
50
|
- lib/bundler/specification.rb
|
49
51
|
- lib/bundler/templates/environment.erb
|
50
52
|
- lib/bundler/templates/Gemfile
|
@@ -69,15 +71,14 @@ files:
|
|
69
71
|
- lib/bundler/vendor/thor.rb
|
70
72
|
- lib/bundler.rb
|
71
73
|
- LICENSE
|
72
|
-
- README.
|
73
|
-
- ROADMAP.
|
74
|
+
- README.md
|
75
|
+
- ROADMAP.md
|
76
|
+
- CHANGELOG.md
|
74
77
|
has_rdoc: true
|
75
78
|
homepage: http://github.com/carlhuda/bundler
|
76
79
|
licenses: []
|
77
80
|
|
78
|
-
post_install_message:
|
79
|
-
Due to a rubygems bug, you must uninstall older versions of the bundler gem for 0.9 to work.
|
80
|
-
If you still need bundler 0.8, install the 'bundler08' gem.
|
81
|
+
post_install_message:
|
81
82
|
rdoc_options: []
|
82
83
|
|
83
84
|
require_paths:
|
data/ROADMAP.textile
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
We will be releasing one more point release (0.10.x) followed by 1.0. While
|
2
|
-
the following reflects our current thinking, critical bugs may alter it
|
3
|
-
somewhat.
|
4
|
-
|
5
|
-
h1. 0.10
|
6
|
-
|
7
|
-
* No breaking changes to the Gemfile are expected
|
8
|
-
* We expect to modify the format of Gemfile.lock.
|
9
|
-
** This should be the final change; it will not change for 1.0
|
10
|
-
** The Gemfile.lock generated by 0.9 will continue to work until 1.0
|
11
|
-
** If you use Bundler 0.10, we will transparently update the format
|
12
|
-
** This means: you will not be able to upgrade a locked app
|
13
|
-
directly from 0.9 to 1.0.
|
14
|
-
* Bundler 0.10 will automatically generate Gemfile.lock when any
|
15
|
-
resolve is successful.
|
16
|
-
* bundle install will conservatively update Gemfile.lock from the
|
17
|
-
last successful resolve if the Gemfile has been modified since
|
18
|
-
the last use of bundler.
|
19
|
-
** This means that adding a new gem to the Gemfile that does not
|
20
|
-
conflict with existing gems will not force an update of other
|
21
|
-
gems.
|
22
|
-
** This also means that we will not force an update to previously
|
23
|
-
resolved dependencies as long as they are compatible with some
|
24
|
-
valid version of the new dependency.
|
25
|
-
** When removing a gem, bundle install will simply remove it, without
|
26
|
-
recalculating all dependencies.
|
27
|
-
* We will be adding `bundle update` for the case where you *do*
|
28
|
-
wish to re-resolve all dependencies and update everything to the
|
29
|
-
latest version.
|
30
|
-
** bundle update will also take a gem name, if you want to force
|
31
|
-
an update to just a single gem (and its dependencies).
|
32
|
-
* Add a way to install dependencies that require build options
|
33
|
-
* Add a way to specify groups that are opt-in at install-time,
|
34
|
-
rather than opt-out.
|
35
|
-
* Some additional features that we have tagged for 0.10. For up
|
36
|
-
to date information, please visit
|
37
|
-
http://github.com/carlhuda/bundler/issues/labels/0.10
|
38
|
-
|
39
|
-
h1. 1.0
|
40
|
-
|
41
|
-
* No breaking changes to the Gemfile are expected
|
42
|
-
* No breaking changes to the Gemfile.lock are expected
|
43
|
-
* No major changes to the workflow are expected
|
44
|
-
* Reduce open bug count to 0
|
45
|
-
* Some additional features that require more thought. For details,
|
46
|
-
see http://github.com/carlhuda/bundler/issues/labels/1.0
|
47
|
-
|
48
|
-
h1. No Breaking changes
|
49
|
-
|
50
|
-
We expect no breaking changes of the Gemfile, Gemfile.lock, or
|
51
|
-
basic workflow for 1.x releases.
|