bundler 1.6.9 → 1.7.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.

@@ -316,7 +316,8 @@ module Bundler
316
316
 
317
317
  # fetch from modern index: specs.4.8.gz
318
318
  def fetch_all_remote_specs
319
- Bundler.rubygems.sources = ["#{@remote_uri}"]
319
+ old_sources = Bundler.rubygems.sources
320
+ Bundler.rubygems.sources = [@remote_uri.to_s]
320
321
  Bundler.rubygems.fetch_all_remote_specs
321
322
  rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e
322
323
  case e.message
@@ -330,6 +331,8 @@ module Bundler
330
331
  Bundler.ui.trace e
331
332
  raise HTTPError, "Could not fetch specs from #{uri}"
332
333
  end
334
+ ensure
335
+ Bundler.rubygems.sources = old_sources
333
336
  end
334
337
 
335
338
  def well_formed_dependency(name, *requirements)
@@ -10,13 +10,14 @@ module Bundler
10
10
  i
11
11
  end
12
12
 
13
- attr_reader :specs, :sources
14
- protected :specs
13
+ attr_reader :specs, :all_specs, :sources
14
+ protected :specs, :all_specs
15
15
 
16
16
  def initialize
17
17
  @sources = []
18
18
  @cache = {}
19
19
  @specs = Hash.new { |h,k| h[k] = [] }
20
+ @all_specs = Hash.new { |h,k| h[k] = [] }
20
21
  end
21
22
 
22
23
  def initialize_copy(o)
@@ -24,10 +25,14 @@ module Bundler
24
25
  @sources = @sources.dup
25
26
  @cache = {}
26
27
  @specs = Hash.new { |h,k| h[k] = [] }
28
+ @all_specs = Hash.new { |h,k| h[k] = [] }
27
29
 
28
30
  o.specs.each do |name, array|
29
31
  @specs[name] = array.dup
30
32
  end
33
+ o.all_specs.each do |name, array|
34
+ @all_specs[name] = array.dup
35
+ end
31
36
  end
32
37
 
33
38
  def inspect
@@ -39,6 +44,14 @@ module Bundler
39
44
  true
40
45
  end
41
46
 
47
+ def search_all(name)
48
+ all_matches = @all_specs[name] + local_search(name)
49
+ @sources.each do |source|
50
+ all_matches.concat(source.search_all(name))
51
+ end
52
+ all_matches
53
+ end
54
+
42
55
  # Search this index's specs, and any source indexes that this index knows
43
56
  # about, returning all of the results.
44
57
  def search(query, base = nil)
@@ -105,6 +118,7 @@ module Bundler
105
118
  return unless other
106
119
  other.each do |s|
107
120
  if (dupes = search_by_spec(s)) && dupes.any?
121
+ @all_specs[s.name] = [s] + dupes
108
122
  next unless override_dupes
109
123
  @specs[s.name] -= dupes
110
124
  end
@@ -5,7 +5,10 @@ require 'bundler/parallel_workers'
5
5
  module Bundler
6
6
  class Installer < Environment
7
7
  class << self
8
- attr_accessor :post_install_messages
8
+ attr_accessor :post_install_messages, :ambiguous_gems
9
+
10
+ Installer.post_install_messages = {}
11
+ Installer.ambiguous_gems = []
9
12
  end
10
13
 
11
14
  # Begins the installation process for Bundler.
@@ -75,10 +78,6 @@ module Bundler
75
78
  unless local
76
79
  options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
77
80
  end
78
- # Must install gems in the order that the resolver provides
79
- # as dependencies might actually affect the installation of
80
- # the gem.
81
- Installer.post_install_messages = {}
82
81
 
83
82
  # the order that the resolver provides is significant, since
84
83
  # dependencies might actually affect the installation of a gem.
@@ -29,6 +29,8 @@ module Bundler
29
29
  @state = :source
30
30
  @specs = {}
31
31
 
32
+ @rubygems_aggregate = Source::Rubygems.new
33
+
32
34
  if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
33
35
  raise LockfileError, "Your Gemfile.lock contains merge conflicts.\n" \
34
36
  "Run `git checkout HEAD -- Gemfile.lock` first to get a clean lock."
@@ -43,6 +45,7 @@ module Bundler
43
45
  send("parse_#{@state}", line)
44
46
  end
45
47
  end
48
+ @sources << @rubygems_aggregate
46
49
  @specs = @specs.values
47
50
  end
48
51
 
@@ -60,14 +63,24 @@ module Bundler
60
63
  @current_source = nil
61
64
  @opts, @type = {}, line
62
65
  when SPECS
63
- @current_source = TYPES[@type].from_lock(@opts)
64
-
65
- # Strip out duplicate GIT sections
66
- if @sources.include?(@current_source) && @current_source.is_a?(Bundler::Source::Git)
67
- @current_source = @sources.find { |s| s == @current_source }
66
+ case @type
67
+ when "PATH"
68
+ @current_source = TYPES[@type].from_lock(@opts)
69
+ @sources << @current_source
70
+ when "GIT"
71
+ @current_source = TYPES[@type].from_lock(@opts)
72
+ # Strip out duplicate GIT sections
73
+ if @type == "GIT" && @sources.include?(@current_source)
74
+ @current_source = @sources.find { |s| s == @current_source }
75
+ else
76
+ @sources << @current_source
77
+ end
78
+ when "GEM"
79
+ Array(@opts["remote"]).each do |url|
80
+ @rubygems_aggregate.add_remote(url)
81
+ end
82
+ @current_source = @rubygems_aggregate
68
83
  end
69
-
70
- @sources << @current_source
71
84
  when OPTIONS
72
85
  value = $2
73
86
  value = true if value == "true"
@@ -139,7 +139,7 @@ module Bundler
139
139
  gemspec_files = Dir["#{Gem.dir}/specifications/*.gemspec"]
140
140
  spec_gem_paths = []
141
141
  # need to keep git sources around
142
- spec_git_paths = @definition.sources.select {|s| s.is_a?(Bundler::Source::Git) }.map {|s| s.path.to_s }
142
+ spec_git_paths = @definition.spec_git_paths
143
143
  spec_git_cache_dirs = []
144
144
  spec_gem_executables = []
145
145
  spec_cache_paths = []
@@ -24,5 +24,8 @@ module Bundler
24
24
  message
25
25
  end
26
26
 
27
+ def can_lock?(spec)
28
+ spec.source == self
29
+ end
27
30
  end
28
31
  end
@@ -12,12 +12,14 @@ module Bundler
12
12
 
13
13
  def initialize(options = {})
14
14
  @options = options
15
- @remotes = (options["remotes"] || []).map { |r| normalize_uri(r) }
15
+ @remotes = []
16
16
  @fetchers = {}
17
17
  @dependency_names = []
18
18
  @allow_remote = false
19
19
  @allow_cached = false
20
20
  @caches = [Bundler.app_cache, *Bundler.rubygems.gem_cache]
21
+
22
+ Array(options["remotes"] || []).reverse_each{|r| add_remote(r) }
21
23
  end
22
24
 
23
25
  def remote!
@@ -29,23 +31,25 @@ module Bundler
29
31
  end
30
32
 
31
33
  def hash
32
- Rubygems.hash
34
+ @remotes.hash
33
35
  end
34
36
 
35
37
  def eql?(o)
36
- o.is_a?(Rubygems)
38
+ o.is_a?(Rubygems) && remotes == o.remotes
37
39
  end
38
40
 
39
41
  alias == eql?
40
42
 
43
+ def can_lock?(spec)
44
+ spec.source.is_a?(Rubygems)
45
+ end
46
+
41
47
  def options
42
48
  { "remotes" => @remotes.map { |r| r.to_s } }
43
49
  end
44
50
 
45
51
  def self.from_lock(options)
46
- s = new(options)
47
- Array(options["remote"]).each { |r| s.add_remote(r) }
48
- s
52
+ new(options)
49
53
  end
50
54
 
51
55
  def to_lock
@@ -72,6 +76,13 @@ module Bundler
72
76
  # Download the gem to get the spec, because some specs that are returned
73
77
  # by rubygems.org are broken and wrong.
74
78
  if spec.source_uri
79
+ # Check for this spec from other sources
80
+ uris = [spec.source_uri]
81
+ uris += source_uris_for_spec(spec)
82
+ uris.compact!
83
+ uris.uniq!
84
+ Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
85
+
75
86
  s = Bundler.rubygems.spec_from_gem(fetch_gem(spec), Bundler.settings["trust-policy"])
76
87
  spec.__swap__(s)
77
88
  end
@@ -148,18 +159,14 @@ module Bundler
148
159
  end
149
160
 
150
161
  def add_remote(source)
151
- @remotes << normalize_uri(source)
162
+ uri = normalize_uri(source)
163
+ @remotes.unshift(uri) unless @remotes.include?(uri)
152
164
  end
153
165
 
154
- def replace_remotes(source)
155
- return false if source.remotes == @remotes
156
-
157
- @remotes = []
158
- source.remotes.each do |r|
159
- add_remote r.to_s
160
- end
166
+ protected
161
167
 
162
- true
168
+ def source_uris_for_spec(spec)
169
+ specs.search_all(spec.name).map{|s| s.source_uri }
163
170
  end
164
171
 
165
172
  private
@@ -186,7 +193,7 @@ module Bundler
186
193
  end
187
194
 
188
195
  def suppress_configured_credentials(remote)
189
- remote_nouser = remote.dup.tap { |uri| uri.user = uri.password = nil }.to_s
196
+ remote_nouser = remote.tap { |uri| uri.user = uri.password = nil }.to_s
190
197
  if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser]
191
198
  remote_nouser
192
199
  else
@@ -0,0 +1,79 @@
1
+ module Bundler
2
+ class SourceList
3
+ attr_reader :path_sources,
4
+ :git_sources,
5
+ :rubygems_sources
6
+
7
+ def initialize
8
+ @path_sources = []
9
+ @git_sources = []
10
+ @rubygems_aggregate = Source::Rubygems.new
11
+ @rubygems_sources = [@rubygems_aggregate]
12
+ end
13
+
14
+ def add_path_source(options = {})
15
+ add_source_to_list Source::Path.new(options), path_sources
16
+ end
17
+
18
+ def add_git_source(options = {})
19
+ add_source_to_list Source::Git.new(options), git_sources
20
+ end
21
+
22
+ def add_rubygems_source(options = {})
23
+ add_source_to_list Source::Rubygems.new(options), @rubygems_sources
24
+ end
25
+
26
+ def add_rubygems_remote(uri)
27
+ @rubygems_aggregate.add_remote(uri)
28
+ @rubygems_aggregate
29
+ end
30
+
31
+ def all_sources
32
+ path_sources + git_sources + rubygems_sources
33
+ end
34
+
35
+ def get(source)
36
+ source_list_for(source).find { |s| source == s }
37
+ end
38
+
39
+ def lock_sources
40
+ (path_sources + git_sources) << combine_rubygems_sources
41
+ end
42
+
43
+ def replace_sources!(replacement_sources)
44
+ [path_sources, git_sources, rubygems_sources].each do |source_list|
45
+ source_list.map! do |source|
46
+ replacement_sources.find { |s| s == source } || source
47
+ end
48
+ end
49
+ end
50
+
51
+ def cached!
52
+ all_sources.each(&:cached!)
53
+ end
54
+
55
+ def remote!
56
+ all_sources.each(&:remote!)
57
+ end
58
+
59
+ private
60
+
61
+ def add_source_to_list(source, list)
62
+ list.unshift(source).uniq!
63
+ source
64
+ end
65
+
66
+ def source_list_for(source)
67
+ case source
68
+ when Source::Git then git_sources
69
+ when Source::Path then path_sources
70
+ when Source::Rubygems then rubygems_sources
71
+ else raise ArgumentError, "Invalid source: #{source.inspect}"
72
+ end
73
+ end
74
+
75
+ def combine_rubygems_sources
76
+ Source::Rubygems.new("remotes" => rubygems_sources.map(&:remotes).flatten.uniq.reverse)
77
+ end
78
+ end
79
+ end
@@ -1,6 +1,4 @@
1
1
  require 'fileutils'
2
- require 'net/https'
3
- require 'openssl'
4
2
 
5
3
  module Bundler
6
4
  module SSLCerts
@@ -11,21 +9,17 @@ module Bundler
11
9
  new(rubygems_path).update!
12
10
  end
13
11
 
14
- def initialize(rubygems_path = nil)
15
- if rubygems_path
16
- rubygems_cert_path = File.join(rubygems_path, 'lib/rubygems/ssl_certs')
17
- @rubygems_certs = certificates_in(rubygems_cert_path)
18
- end
12
+ def initialize(rubygems_path)
13
+ rubygems_certs = File.join(rubygems_path, 'lib/rubygems/ssl_certs')
14
+ @rubygems_certs = certificates_in(rubygems_certs)
19
15
 
20
16
  @bundler_cert_path = File.expand_path("..", __FILE__)
21
17
  @bundler_certs = certificates_in(bundler_cert_path)
22
18
  end
23
19
 
24
20
  def up_to_date?
25
- rubygems_certs.all? do |rc|
26
- bundler_certs.find do |bc|
27
- File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc)
28
- end
21
+ bundler_certs.zip(rubygems_certs).all? do |bc, rc|
22
+ File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc)
29
23
  end
30
24
  end
31
25
 
@@ -36,30 +30,12 @@ module Bundler
36
30
  FileUtils.cp rubygems_certs, bundler_cert_path
37
31
  end
38
32
 
39
- def connect_to(host)
40
- http = Net::HTTP.new(host, 443)
41
- http.use_ssl = true
42
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
43
- http.cert_store = store
44
- http.head('/')
45
- end
46
-
47
33
  private
48
34
 
49
35
  def certificates_in(path)
50
36
  Dir[File.join(path, "*.pem")].sort
51
37
  end
52
38
 
53
- def store
54
- @store ||= begin
55
- store = OpenSSL::X509::Store.new
56
- bundler_certs.each do |cert|
57
- store.add_file cert
58
- end
59
- store
60
- end
61
- end
62
-
63
39
  end
64
40
  end
65
41
  end
@@ -2,5 +2,5 @@ module Bundler
2
2
  # We're doing this because we might write tests that deal
3
3
  # with other versions of bundler and we are unsure how to
4
4
  # handle this better.
5
- VERSION = "1.6.9" unless defined?(::Bundler::VERSION)
5
+ VERSION = "1.7.0" unless defined?(::Bundler::VERSION)
6
6
  end
@@ -145,26 +145,11 @@ Finally, Bundler also ensures that the current revision in the
145
145
  `Gemfile.lock` exists in the local git repository. By doing this, Bundler
146
146
  forces you to fetch the latest changes in the remotes.
147
147
 
148
- ## MIRRORS OF GEM SOURCES
148
+ ## MIRRORS OF GEM REPOSITORIES
149
149
 
150
150
  Bundler supports overriding gem sources with mirrors. This allows you to
151
151
  configure rubygems.org as the gem source in your Gemfile while still using your
152
152
  mirror to fetch gems.
153
153
 
154
- bundle config mirror.SOURCE_URL MIRROR_URL
155
-
156
- For example, to use a mirror of rubygems.org hosted at
157
-
158
154
  bundle config mirror.http://rubygems.org http://rubygems-mirror.org
159
155
 
160
- ## CREDENTIALS FOR GEM SOURCES
161
-
162
- Bundler allows you to configure credentials for any gem source, which allows
163
- you to avoid putting secrets into your Gemfile.
164
-
165
- bundle config SOURCE_URL USERNAME:PASSWORD
166
-
167
- For example, to save the credentials of user `claudette` for the gem source at
168
- `gems.longerous.com`, you would run:
169
-
170
- bundle config https://gems.longerous.com/ claudette:s00pers3krit
@@ -15,33 +15,23 @@ directory as the `Rakefile`.
15
15
  A `Gemfile` is evaluated as Ruby code, in a context which makes available
16
16
  a number of methods used to describe the gem requirements.
17
17
 
18
- ## SOURCES (#source)
18
+ ## GLOBAL SOURCES (#source)
19
19
 
20
- At the top of the `Gemfile`, add one line for each `Rubygems` source that
21
- might contain the gems listed in the `Gemfile`.
20
+ At the top of the `Gemfile`, add a line for the `Rubygems` source that contains
21
+ the gems listed in the `Gemfile`.
22
22
 
23
23
  source "https://rubygems.org"
24
- source "http://gems.github.com"
25
24
 
26
- Each of these _source_s `MUST` be a valid Rubygems repository. Sources are
27
- checked for gems following the heuristics described in [SOURCE PRIORITY][].
25
+ It is possible, but not recommended as of Bundler 1.7, to add multiple global
26
+ `source` lines. Each of these `source`s `MUST` be a valid Rubygems repository.
28
27
 
29
- ### CREDENTIALS (#credentials)
30
-
31
- Some gem sources require a username and password. Use `bundle config` to set
32
- the username and password for any sources that need it. The command must be run
33
- once on each computer that will install the Gemfile, but this keeps the
34
- credentials from being stored in plain text in version control.
35
-
36
- bundle config https://gems.example.com/ user:password
37
-
38
- For some sources, like a company Gemfury account, it may be easier to simply
39
- include the credentials in the Gemfile as part of the source URL.
40
-
41
- source "https://user:password@gems.example.com"
42
-
43
- Credentials in the source URL will take precedence over credentials set using
44
- `config`.
28
+ Sources are checked for gems following the heuristics described in
29
+ [SOURCE PRIORITY][]. If a gem is found in more than one global source, Bundler
30
+ will print a warning after installing the gem indicating which source was used,
31
+ and listing the other sources where the gem is available. A specific source can
32
+ be selected for gems that need to use a non-standard repository, suppressing
33
+ this warning, by using the [`:source` option](#SOURCE-source-) or a
34
+ [`source` block](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
45
35
 
46
36
  ## RUBY (#ruby)
47
37
 
@@ -217,6 +207,25 @@ All operations involving groups (`bundle install`, `Bundler.setup`,
217
207
  `Bundler.require`) behave exactly the same as if any groups not
218
208
  matching the current platform were explicitly excluded.
219
209
 
210
+ ### SOURCE (:source)
211
+
212
+ You can select an alternate Rubygems repository for a gem using the ':source'
213
+ option.
214
+
215
+ gem "some_internal_gem", :source => "https://gems.example.com"
216
+
217
+ This forces the gem to be loaded from this source and ignores any global sources
218
+ declared at the top level of the file. If the gem does not exist in this source,
219
+ it will not be installed.
220
+
221
+ Bundler will search for child dependencies of this gem by first looking in the
222
+ source selected for the parent, but if they are not found there, it will fall
223
+ back on global sources using the ordering described in [SOURCE PRIORITY][].
224
+
225
+ Selecting a specific source repository this way also suppresses the ambiguous
226
+ gem warning described above in
227
+ [GLOBAL SOURCES (#source)](#GLOBAL-SOURCES-source-).
228
+
220
229
  ### GIT (:git)
221
230
 
222
231
  If necessary, you can specify that a gem is located at a particular
@@ -315,11 +324,16 @@ gems specified as paths.
315
324
 
316
325
  gem "rails", :path => "vendor/rails"
317
326
 
318
- ## BLOCK FORM OF GIT, PATH, GROUP and PLATFORMS
327
+ ## BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS
319
328
 
320
- The `:git`, `:path`, `:group`, and `:platforms` options may be
329
+ The `:source`, `:git`, `:path`, `:group`, and `:platforms` options may be
321
330
  applied to a group of gems by using block form.
322
331
 
332
+ source "https://gems.example.com" do
333
+ gem "some_internal_gem"
334
+ gem "another_internal_gem"
335
+ end
336
+
323
337
  git "git://github.com/rails/rails.git" do
324
338
  gem "activesupport"
325
339
  gem "actionpack"
@@ -363,10 +377,11 @@ dependencies are included in.
363
377
  When attempting to locate a gem to satisfy a gem requirement,
364
378
  bundler uses the following priority order:
365
379
 
366
- 1. The source explicitly attached to the gem (using `:path` or `:git`)
367
- 2. For implicit gems (dependencies of explicit gems), any git or path
368
- repository otherwise declared. This results in bundler prioritizing the
380
+ 1. The source explicitly attached to the gem (using `:source`, `:path`, or
381
+ `:git`)
382
+ 2. For implicit gems (dependencies of explicit gems), any source, git, or path
383
+ repository declared on the parent. This results in bundler prioritizing the
369
384
  ActiveSupport gem from the Rails git repository over ones from
370
385
  `rubygems.org`
371
- 3. The sources specified via `source`, searching each source in your `Gemfile`
372
- from last added to first added.
386
+ 3. The sources specified via global `source` lines, searching each source in
387
+ your `Gemfile` from last added to first added.