bundler 1.10.6 → 1.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +105 -0
  3. data/.rubocop_todo.yml +120 -0
  4. data/.travis.yml +8 -23
  5. data/CHANGELOG.md +95 -0
  6. data/CODE_OF_CONDUCT.md +6 -4
  7. data/DEVELOPMENT.md +4 -5
  8. data/README.md +2 -2
  9. data/Rakefile +71 -88
  10. data/bin/rake +14 -0
  11. data/bin/rspec +10 -0
  12. data/bin/rubocop +11 -0
  13. data/bundler.gemspec +17 -15
  14. data/exe/bundle +20 -0
  15. data/{bin → exe}/bundle_ruby +6 -4
  16. data/exe/bundler +20 -0
  17. data/lib/bundler/capistrano.rb +2 -2
  18. data/lib/bundler/cli/binstubs.rb +1 -2
  19. data/lib/bundler/cli/cache.rb +0 -1
  20. data/lib/bundler/cli/check.rb +7 -5
  21. data/lib/bundler/cli/clean.rb +0 -1
  22. data/lib/bundler/cli/common.rb +6 -7
  23. data/lib/bundler/cli/config.rb +69 -56
  24. data/lib/bundler/cli/console.rb +8 -8
  25. data/lib/bundler/cli/exec.rb +5 -4
  26. data/lib/bundler/cli/gem.rb +52 -40
  27. data/lib/bundler/cli/init.rb +5 -6
  28. data/lib/bundler/cli/inject.rb +1 -2
  29. data/lib/bundler/cli/install.rb +18 -21
  30. data/lib/bundler/cli/lock.rb +8 -3
  31. data/lib/bundler/cli/open.rb +4 -5
  32. data/lib/bundler/cli/outdated.rb +7 -8
  33. data/lib/bundler/cli/package.rb +1 -1
  34. data/lib/bundler/cli/platform.rb +2 -3
  35. data/lib/bundler/cli/show.rb +9 -9
  36. data/lib/bundler/cli/update.rb +2 -3
  37. data/lib/bundler/cli/viz.rb +1 -2
  38. data/lib/bundler/cli.rb +85 -74
  39. data/lib/bundler/constants.rb +1 -1
  40. data/lib/bundler/current_ruby.rb +38 -3
  41. data/lib/bundler/definition.rb +83 -88
  42. data/lib/bundler/dep_proxy.rb +11 -9
  43. data/lib/bundler/dependency.rb +17 -11
  44. data/lib/bundler/deployment.rb +2 -2
  45. data/lib/bundler/deprecate.rb +3 -3
  46. data/lib/bundler/dsl.rb +62 -43
  47. data/lib/bundler/env.rb +19 -12
  48. data/lib/bundler/environment.rb +1 -2
  49. data/lib/bundler/errors.rb +82 -0
  50. data/lib/bundler/fetcher/base.rb +20 -7
  51. data/lib/bundler/fetcher/dependency.rb +5 -5
  52. data/lib/bundler/fetcher/downloader.rb +1 -2
  53. data/lib/bundler/fetcher/index.rb +4 -7
  54. data/lib/bundler/fetcher.rb +49 -40
  55. data/lib/bundler/friendly_errors.rb +15 -8
  56. data/lib/bundler/gem_helper.rb +44 -35
  57. data/lib/bundler/gem_helpers.rb +7 -8
  58. data/lib/bundler/gem_remote_fetcher.rb +41 -0
  59. data/lib/bundler/gem_tasks.rb +4 -1
  60. data/lib/bundler/graph.rb +25 -24
  61. data/lib/bundler/index.rb +21 -18
  62. data/lib/bundler/injector.rb +2 -4
  63. data/lib/bundler/inline.rb +3 -3
  64. data/lib/bundler/installer/gem_installer.rb +76 -0
  65. data/lib/bundler/installer/parallel_installer.rb +22 -13
  66. data/lib/bundler/installer/standalone.rb +48 -0
  67. data/lib/bundler/installer.rb +57 -144
  68. data/lib/bundler/lazy_specification.rb +4 -5
  69. data/lib/bundler/lockfile_parser.rb +21 -19
  70. data/lib/bundler/man/bundle +2 -2
  71. data/lib/bundler/man/bundle-config +2 -2
  72. data/lib/bundler/man/bundle-config.txt +6 -4
  73. data/lib/bundler/man/bundle-exec +1 -1
  74. data/lib/bundler/man/bundle-exec.txt +1 -1
  75. data/lib/bundler/man/bundle-gem +80 -0
  76. data/lib/bundler/man/bundle-gem.txt +90 -0
  77. data/lib/bundler/man/bundle-install +37 -6
  78. data/lib/bundler/man/bundle-install.txt +68 -44
  79. data/lib/bundler/man/bundle-lock +55 -0
  80. data/lib/bundler/man/bundle-lock.txt +60 -0
  81. data/lib/bundler/man/bundle-package +1 -1
  82. data/lib/bundler/man/bundle-package.txt +1 -1
  83. data/lib/bundler/man/bundle-platform +1 -1
  84. data/lib/bundler/man/bundle-platform.txt +1 -1
  85. data/lib/bundler/man/bundle-update +1 -1
  86. data/lib/bundler/man/bundle-update.txt +1 -1
  87. data/lib/bundler/man/bundle.txt +2 -2
  88. data/lib/bundler/man/gemfile.5 +17 -1
  89. data/lib/bundler/man/gemfile.5.txt +12 -1
  90. data/lib/bundler/match_platform.rb +4 -4
  91. data/lib/bundler/psyched_yaml.rb +5 -5
  92. data/lib/bundler/remote_specification.rb +1 -1
  93. data/lib/bundler/resolver.rb +93 -88
  94. data/lib/bundler/retry.rb +9 -10
  95. data/lib/bundler/ruby_dsl.rb +1 -1
  96. data/lib/bundler/ruby_version.rb +7 -10
  97. data/lib/bundler/rubygems_ext.rb +32 -27
  98. data/lib/bundler/{gem_installer.rb → rubygems_gem_installer.rb} +2 -2
  99. data/lib/bundler/rubygems_integration.rb +85 -70
  100. data/lib/bundler/runtime.rb +65 -61
  101. data/lib/bundler/settings.rb +27 -26
  102. data/lib/bundler/setup.rb +3 -3
  103. data/lib/bundler/shared_helpers.rb +45 -20
  104. data/lib/bundler/similarity_detector.rb +19 -21
  105. data/lib/bundler/source/git/git_proxy.rb +52 -26
  106. data/lib/bundler/source/git.rb +29 -31
  107. data/lib/bundler/source/path/installer.rb +4 -4
  108. data/lib/bundler/source/path.rb +25 -28
  109. data/lib/bundler/source/rubygems/remote.rb +3 -3
  110. data/lib/bundler/source/rubygems.rb +62 -48
  111. data/lib/bundler/source.rb +4 -5
  112. data/lib/bundler/source_list.rb +4 -4
  113. data/lib/bundler/spec_set.rb +17 -15
  114. data/lib/bundler/ssl_certs/certificate_manager.rb +5 -6
  115. data/lib/bundler/stub_specification.rb +2 -2
  116. data/lib/bundler/templates/Executable +5 -5
  117. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +42 -6
  118. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  119. data/lib/bundler/templates/newgem/Rakefile.tt +4 -2
  120. data/lib/bundler/templates/newgem/bin/setup.tt +2 -1
  121. data/lib/bundler/templates/newgem/newgem.gemspec.tt +2 -2
  122. data/lib/bundler/ui/rg_proxy.rb +2 -2
  123. data/lib/bundler/ui/shell.rb +10 -6
  124. data/lib/bundler/ui.rb +3 -3
  125. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +82 -71
  126. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  127. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +9 -0
  128. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +40 -21
  129. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -0
  130. data/lib/bundler/vendored_molinillo.rb +1 -1
  131. data/lib/bundler/vendored_persistent.rb +3 -3
  132. data/lib/bundler/vendored_thor.rb +2 -2
  133. data/lib/bundler/version.rb +1 -1
  134. data/lib/bundler/vlad.rb +1 -1
  135. data/lib/bundler/worker.rb +4 -5
  136. data/lib/bundler.rb +99 -120
  137. data/man/bundle-config.ronn +4 -2
  138. data/man/bundle-gem.ronn +77 -0
  139. data/man/bundle-install.ronn +13 -6
  140. data/man/bundle-lock.ronn +47 -0
  141. data/man/bundle.ronn +1 -1
  142. data/man/gemfile.5.ronn +8 -0
  143. data/man/index.txt +1 -0
  144. metadata +36 -8
  145. data/bin/bundle +0 -21
  146. data/bin/bundler +0 -21
@@ -1,10 +1,10 @@
1
- require 'uri'
1
+ require "uri"
2
2
 
3
3
  module Bundler
4
4
  class Settings
5
- BOOL_KEYS = %w(frozen cache_all no_prune disable_local_branch_check ignore_messages gem.mit gem.coc).freeze
6
- NUMBER_KEYS = %w(retry timeout redirect).freeze
7
- DEFAULT_CONFIG = {:retry => 3, :timeout => 10, :redirect => 5}
5
+ BOOL_KEYS = %w(frozen cache_all no_prune disable_local_branch_check ignore_messages gem.mit gem.coc silence_root_warning).freeze
6
+ NUMBER_KEYS = %w(retry timeout redirect ssl_verify_mode).freeze
7
+ DEFAULT_CONFIG = { :retry => 3, :timeout => 10, :redirect => 5 }
8
8
 
9
9
  def initialize(root = nil)
10
10
  @root = root
@@ -17,9 +17,11 @@ module Bundler
17
17
  value = (@local_config[key] || ENV[key] || @global_config[key] || DEFAULT_CONFIG[name])
18
18
 
19
19
  case
20
- when !value.nil? && is_bool(name)
20
+ when value.nil?
21
+ nil
22
+ when is_bool(name) || value == "false"
21
23
  to_bool(value)
22
- when !value.nil? && is_num(name)
24
+ when is_num(name)
23
25
  value.to_i
24
26
  else
25
27
  value
@@ -27,11 +29,11 @@ module Bundler
27
29
  end
28
30
 
29
31
  def []=(key, value)
30
- local_config_file or raise GemfileNotFound, "Could not locate Gemfile"
32
+ local_config_file || raise(GemfileNotFound, "Could not locate Gemfile")
31
33
  set_key(key, value, @local_config, local_config_file)
32
34
  end
33
35
 
34
- alias :set_local :[]=
36
+ alias_method :set_local, :[]=
35
37
 
36
38
  def delete(key)
37
39
  @local_config.delete(key_for(key))
@@ -42,21 +44,19 @@ module Bundler
42
44
  end
43
45
 
44
46
  def all
45
- env_keys = ENV.keys.select { |k| k =~ /BUNDLE_.*/ }
47
+ env_keys = ENV.keys.select {|k| k =~ /BUNDLE_.*/ }
46
48
 
47
49
  keys = @global_config.keys | @local_config.keys | env_keys
48
50
 
49
51
  keys.map do |key|
50
- key.sub(/^BUNDLE_/, '').gsub(/__/, ".").downcase
52
+ key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase
51
53
  end
52
54
  end
53
55
 
54
56
  def local_overrides
55
57
  repos = {}
56
58
  all.each do |k|
57
- if k =~ /^local\./
58
- repos[$'] = self[k]
59
- end
59
+ repos[$'] = self[k] if k =~ /^local\./
60
60
  end
61
61
  repos
62
62
  end
@@ -147,7 +147,7 @@ module Bundler
147
147
  end
148
148
 
149
149
  def ignore_config?
150
- ENV['BUNDLE_IGNORE_CONFIG']
150
+ ENV["BUNDLE_IGNORE_CONFIG"]
151
151
  end
152
152
 
153
153
  def app_cache_path
@@ -159,10 +159,9 @@ module Bundler
159
159
  end
160
160
 
161
161
  private
162
+
162
163
  def key_for(key)
163
- if key.is_a?(String) && /https?:/ =~ key
164
- key = normalize_uri(key).to_s
165
- end
164
+ key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
166
165
  key = key.to_s.gsub(".", "__").upcase
167
166
  "BUNDLE_#{key}"
168
167
  end
@@ -184,7 +183,7 @@ module Bundler
184
183
  end
185
184
 
186
185
  def to_bool(value)
187
- !(value.nil? || value == '' || value =~ /^(false|f|no|n|0)$/i || value == false)
186
+ !(value.nil? || value == "" || value =~ /^(false|f|no|n|0)$/i || value == false)
188
187
  end
189
188
 
190
189
  def is_num(value)
@@ -192,11 +191,11 @@ module Bundler
192
191
  end
193
192
 
194
193
  def get_array(key)
195
- self[key] ? self[key].split(":").map { |w| w.to_sym } : []
194
+ self[key] ? self[key].split(":").map(&:to_sym) : []
196
195
  end
197
196
 
198
197
  def set_array(key, array)
199
- self[key] = (array.empty? ? nil : array.join(":")) if array
198
+ self[key] = (array.empty? ? nil : array.join(":")) if array
200
199
  end
201
200
 
202
201
  def set_key(key, value, hash, file)
@@ -205,9 +204,11 @@ module Bundler
205
204
  unless hash[key] == value
206
205
  hash[key] = value
207
206
  hash.delete(key) if value.nil?
208
- FileUtils.mkdir_p(file.dirname)
209
- require 'bundler/psyched_yaml'
210
- File.open(file, "w") { |f| f.puts YAML.dump(hash) }
207
+ SharedHelpers.filesystem_access(file) do |p|
208
+ FileUtils.mkdir_p(p.dirname)
209
+ require "bundler/psyched_yaml"
210
+ File.open(p, "w") {|f| f.puts YAML.dump(hash) }
211
+ end
211
212
  end
212
213
 
213
214
  value
@@ -226,6 +227,7 @@ module Bundler
226
227
  valid_file = config_file && config_file.exist? && !config_file.size.zero?
227
228
  if !ignore_config? && valid_file
228
229
  config_regex = /^(BUNDLE_.+): (['"]?)(.*(?:\n(?!BUNDLE).+)?)\2$/
230
+ raise PermissionError.new(config_file, :read) unless config_file.readable?
229
231
  config_pairs = config_file.read.scan(config_regex).map do |m|
230
232
  key, _, value = m
231
233
  [convert_to_backward_compatible_key(key), value.gsub(/\s+/, " ").tr('"', "'")]
@@ -237,7 +239,7 @@ module Bundler
237
239
  end
238
240
 
239
241
  def convert_to_backward_compatible_key(key)
240
- key = "#{key}/" if key =~ /https?:/i && key !~ %r[/\Z]
242
+ key = "#{key}/" if key =~ /https?:/i && key !~ %r{/\Z}
241
243
  key = key.gsub(".", "__") if key.include?(".")
242
244
  key
243
245
  end
@@ -246,13 +248,12 @@ module Bundler
246
248
  # TODO: is this the correct place to validate mirror URIs?
247
249
  def normalize_uri(uri)
248
250
  uri = uri.to_s
249
- uri = "#{uri}/" unless uri =~ %r[/\Z]
251
+ uri = "#{uri}/" unless uri =~ %r{/\Z}
250
252
  uri = URI(uri)
251
253
  unless uri.absolute?
252
254
  raise ArgumentError, "Gem sources must be absolute. You provided '#{uri}'."
253
255
  end
254
256
  uri
255
257
  end
256
-
257
258
  end
258
259
  end
data/lib/bundler/setup.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'bundler/shared_helpers'
1
+ require "bundler/shared_helpers"
2
2
 
3
3
  if Bundler::SharedHelpers.in_bundle?
4
- require 'bundler'
4
+ require "bundler"
5
5
 
6
- if STDOUT.tty? || ENV['BUNDLER_FORCE_TTY']
6
+ if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"]
7
7
  begin
8
8
  Bundler.setup
9
9
  rescue Bundler::BundlerError => e
@@ -1,13 +1,13 @@
1
- require 'pathname'
2
- require 'rubygems'
1
+ require "pathname"
2
+ require "rubygems"
3
3
 
4
- require 'bundler/constants'
5
- require 'bundler/rubygems_integration'
6
- require 'bundler/current_ruby'
4
+ require "bundler/constants"
5
+ require "bundler/rubygems_integration"
6
+ require "bundler/current_ruby"
7
7
 
8
8
  module Gem
9
9
  class Dependency
10
- if !instance_methods.map { |m| m.to_s }.include?("requirement")
10
+ unless method_defined? :requirement
11
11
  def requirement
12
12
  version_requirements
13
13
  end
@@ -29,7 +29,7 @@ module Bundler
29
29
  gemfile = default_gemfile
30
30
 
31
31
  case gemfile.basename.to_s
32
- when 'gems.rb' then Pathname.new(gemfile.sub(/.rb$/, '.locked'))
32
+ when "gems.rb" then Pathname.new(gemfile.sub(/.rb$/, ".locked"))
33
33
  else Pathname.new("#{gemfile}.lock")
34
34
  end
35
35
  end
@@ -56,12 +56,12 @@ module Bundler
56
56
 
57
57
  def pwd
58
58
  Bundler.rubygems.ext_lock.synchronize do
59
- Dir.pwd
59
+ Pathname.pwd
60
60
  end
61
61
  end
62
62
 
63
63
  def with_clean_git_env(&block)
64
- keys = %w[GIT_DIR GIT_WORK_TREE]
64
+ keys = %w(GIT_DIR GIT_WORK_TREE)
65
65
  old_env = keys.inject({}) do |h, k|
66
66
  h.update(k => ENV[k])
67
67
  end
@@ -81,30 +81,54 @@ module Bundler
81
81
 
82
82
  # Set RUBYOPT
83
83
  rubyopt = [ENV["RUBYOPT"]].compact
84
- if rubyopt.empty? || rubyopt.first !~ /-rbundler\/setup/
85
- rubyopt.unshift %|-rbundler/setup|
86
- ENV["RUBYOPT"] = rubyopt.join(' ')
84
+ if rubyopt.empty? || rubyopt.first !~ %r{-rbundler/setup}
85
+ rubyopt.unshift %(-rbundler/setup)
86
+ ENV["RUBYOPT"] = rubyopt.join(" ")
87
87
  end
88
88
 
89
89
  # Set RUBYLIB
90
90
  rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR)
91
- rubylib.unshift File.expand_path('../..', __FILE__)
91
+ rubylib.unshift File.expand_path("../..", __FILE__)
92
92
  ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR)
93
93
  end
94
94
 
95
+ # Rescues permissions errors raised by file system operations
96
+ # (ie. Errno:EACCESS) and raises more friendly errors instead.
97
+ #
98
+ # @param path [String] the path that the action will be attempted to
99
+ # @param action [Symbol, #to_s] the type of operation that will be
100
+ # performed. For example: :write, :read, :exec
101
+ #
102
+ # @yield path
103
+ #
104
+ # @raise [Bundler::PermissionError] if Errno:EACCES is raised in the
105
+ # given block
106
+ #
107
+ # @example
108
+ # filesystem_access("vendor/cache", :write) do
109
+ # FileUtils.mkdir_p("vendor/cache")
110
+ # end
111
+ #
112
+ # @see {Bundler::PermissionError}
113
+ def filesystem_access(path, action = :write)
114
+ yield path
115
+ rescue Errno::EACCES
116
+ raise PermissionError.new(path, action)
117
+ end
118
+
95
119
  private
96
120
 
97
121
  def find_gemfile
98
- given = ENV['BUNDLE_GEMFILE']
122
+ given = ENV["BUNDLE_GEMFILE"]
99
123
  return given if given && !given.empty?
100
124
 
101
- find_file('Gemfile', 'gems.rb')
125
+ find_file("Gemfile", "gems.rb")
102
126
  end
103
127
 
104
128
  def find_file(*names)
105
- search_up(*names) {|filename|
129
+ search_up(*names) do |filename|
106
130
  return filename if File.file?(filename)
107
- }
131
+ end
108
132
  end
109
133
 
110
134
  def find_directory(*names)
@@ -118,16 +142,17 @@ module Bundler
118
142
  current = File.expand_path(SharedHelpers.pwd)
119
143
 
120
144
  until !File.directory?(current) || current == previous
121
- if ENV['BUNDLE_SPEC_RUN']
145
+ if ENV["BUNDLE_SPEC_RUN"]
122
146
  # avoid stepping above the tmp directory when testing
123
- return nil if File.file?(File.join(current, 'bundler.gemspec'))
147
+ return nil if File.file?(File.join(current, "bundler.gemspec"))
124
148
  end
125
149
 
126
150
  names.each do |name|
127
151
  filename = File.join(current, name)
128
152
  yield filename
129
153
  end
130
- current, previous = File.expand_path("..", current), current
154
+ previous = current
155
+ current = File.expand_path("..", current)
131
156
  end
132
157
  end
133
158
 
@@ -8,56 +8,54 @@ module Bundler
8
8
  end
9
9
 
10
10
  # return an array of words similar to 'word' from the corpus
11
- def similar_words(word, limit=3)
12
- words_by_similarity = @corpus.map{|w| SimilarityScore.new(w, levenshtein_distance(word, w))}
13
- words_by_similarity.select{|s| s.distance<=limit}.sort_by(&:distance).map(&:string)
11
+ def similar_words(word, limit = 3)
12
+ words_by_similarity = @corpus.map {|w| SimilarityScore.new(w, levenshtein_distance(word, w)) }
13
+ words_by_similarity.select {|s| s.distance <= limit }.sort_by(&:distance).map(&:string)
14
14
  end
15
15
 
16
16
  # return the result of 'similar_words', concatenated into a list
17
17
  # (eg "a, b, or c")
18
- def similar_word_list(word, limit=3)
19
- words = similar_words(word,limit)
20
- if words.length==1
18
+ def similar_word_list(word, limit = 3)
19
+ words = similar_words(word, limit)
20
+ if words.length == 1
21
21
  words[0]
22
- elsif words.length>1
23
- [words[0..-2].join(', '), words[-1]].join(' or ')
22
+ elsif words.length > 1
23
+ [words[0..-2].join(", "), words[-1]].join(" or ")
24
24
  end
25
25
  end
26
26
 
27
-
28
27
  protected
28
+
29
29
  # http://www.informit.com/articles/article.aspx?p=683059&seqNum=36
30
- def levenshtein_distance(this, that, ins=2, del=2, sub=1)
30
+ def levenshtein_distance(this, that, ins = 2, del = 2, sub = 1)
31
31
  # ins, del, sub are weighted costs
32
32
  return nil if this.nil?
33
33
  return nil if that.nil?
34
- dm = [] # distance matrix
34
+ dm = [] # distance matrix
35
35
 
36
36
  # Initialize first row values
37
- dm[0] = (0..this.length).collect { |i| i * ins }
37
+ dm[0] = (0..this.length).collect {|i| i * ins }
38
38
  fill = [0] * (this.length - 1)
39
39
 
40
40
  # Initialize first column values
41
- for i in 1..that.length
41
+ (1..that.length).each do |i|
42
42
  dm[i] = [i * del, fill.flatten]
43
43
  end
44
44
 
45
45
  # populate matrix
46
- for i in 1..that.length
47
- for j in 1..this.length
46
+ (1..that.length).each do |i|
47
+ (1..this.length).each do |j|
48
48
  # critical comparison
49
49
  dm[i][j] = [
50
- dm[i-1][j-1] +
51
- (this[j-1] == that[i-1] ? 0 : sub),
52
- dm[i][j-1] + ins,
53
- dm[i-1][j] + del
54
- ].min
50
+ dm[i - 1][j - 1] + (this[j - 1] == that[i - 1] ? 0 : sub),
51
+ dm[i][j - 1] + ins,
52
+ dm[i - 1][j] + del
53
+ ].min
55
54
  end
56
55
  end
57
56
 
58
57
  # The last value in matrix is the Levenshtein distance between the strings
59
58
  dm[that.length][this.length]
60
59
  end
61
-
62
60
  end
63
61
  end
@@ -1,7 +1,6 @@
1
1
  module Bundler
2
2
  class Source
3
3
  class Git < Path
4
-
5
4
  class GitNotInstalledError < GitError
6
5
  def initialize
7
6
  msg = "You need to install git to be able to use gems from git repositories. "
@@ -20,8 +19,9 @@ module Bundler
20
19
  end
21
20
 
22
21
  class GitCommandError < GitError
23
- def initialize(command, path = nil)
24
- msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed."
22
+ def initialize(command, path = nil, extra_info = nil)
23
+ msg = "Git error: command `git #{command}` in directory #{SharedHelpers.pwd} has failed."
24
+ msg << "\n#{extra_info}" if extra_info
25
25
  msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path && path.exist?
26
26
  super msg
27
27
  end
@@ -44,7 +44,10 @@ module Bundler
44
44
  end
45
45
 
46
46
  def revision
47
- @revision ||= allowed_in_path { git("rev-parse #{ref}").strip }
47
+ @revision ||= allowed_in_path do
48
+ msg = "Ref '#{ref}' was not found. Perhaps you mispelled it?"
49
+ git("rev-parse --verify #{ref}", true, msg).strip
50
+ end
48
51
  end
49
52
 
50
53
  def branch
@@ -67,32 +70,44 @@ module Bundler
67
70
  def checkout
68
71
  if path.exist?
69
72
  return if has_revision_cached?
70
- Bundler.ui.confirm "Updating #{uri}"
73
+ Bundler.ui.info "Fetching #{uri}"
71
74
  in_path do
72
- git_retry %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"|
75
+ git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*")
73
76
  end
74
77
  else
75
78
  Bundler.ui.info "Fetching #{uri}"
76
- FileUtils.mkdir_p(path.dirname)
77
- git_retry %|clone #{uri_escaped} "#{path}" --bare --no-hardlinks --quiet|
79
+ SharedHelpers.filesystem_access(path.dirname) do |p|
80
+ FileUtils.mkdir_p(p)
81
+ end
82
+ git_retry %(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet)
78
83
  end
79
84
  end
80
85
 
81
- def copy_to(destination, submodules=false)
86
+ def copy_to(destination, submodules = false)
87
+ # method 1
82
88
  unless File.exist?(destination.join(".git"))
83
- FileUtils.mkdir_p(destination.dirname)
84
- FileUtils.rm_rf(destination)
85
- git_retry %|clone --no-checkout --quiet "#{path}" "#{destination}"|
86
- File.chmod(((File.stat(destination).mode | 0777) & ~File.umask), destination)
89
+ begin
90
+ SharedHelpers.filesystem_access(destination.dirname) do |p|
91
+ FileUtils.mkdir_p(p)
92
+ end
93
+ SharedHelpers.filesystem_access(destination) do |p|
94
+ FileUtils.rm_rf(p)
95
+ end
96
+ git_retry %(clone --no-checkout --quiet "#{path}" "#{destination}")
97
+ File.chmod(((File.stat(destination).mode | 0777) & ~File.umask), destination)
98
+ rescue Errno::EEXIST => e
99
+ file_path = e.message[%r{.*?(/.*)}, 1]
100
+ raise GitError, "Bundler could not install a gem because it needs to " \
101
+ "create a directory, but a file exists - #{file_path}. Please delete " \
102
+ "this file and try again."
103
+ end
87
104
  end
88
-
105
+ # method 2
89
106
  SharedHelpers.chdir(destination) do
90
- git_retry %|fetch --force --quiet --tags "#{path}"|
107
+ git_retry %(fetch --force --quiet --tags "#{path}")
91
108
  git "reset --hard #{@revision}"
92
109
 
93
- if submodules
94
- git_retry "submodule update --init --recursive"
95
- end
110
+ git_retry "submodule update --init --recursive" if submodules
96
111
  end
97
112
  end
98
113
 
@@ -113,10 +128,10 @@ module Bundler
113
128
  end
114
129
  end
115
130
 
116
- def git(command, check_errors=true)
131
+ def git(command, check_errors = true, error_msg = nil)
117
132
  raise GitNotAllowedError.new(command) unless allow?
118
- out = SharedHelpers.with_clean_git_env { %x{git #{command}} }
119
- raise GitCommandError.new(command, path) if check_errors && !$?.success?
133
+ out = SharedHelpers.with_clean_git_env { `git #{command}` }
134
+ raise GitCommandError.new(command, path, error_msg) if check_errors && !$?.success?
120
135
  out
121
136
  end
122
137
 
@@ -129,15 +144,28 @@ module Bundler
129
144
  end
130
145
 
131
146
  # Escape the URI for git commands
132
- def uri_escaped
147
+ def uri_escaped_with_configured_credentials
148
+ remote = configured_uri_for(uri)
133
149
  if Bundler::WINDOWS
134
150
  # Windows quoting requires double quotes only, with double quotes
135
151
  # inside the string escaped by being doubled.
136
- '"' + uri.gsub('"') {|s| '""'} + '"'
152
+ '"' + remote.gsub('"') { '""' } + '"'
137
153
  else
138
154
  # Bash requires single quoted strings, with the single quotes escaped
139
155
  # by ending the string, escaping the quote, and restarting the string.
140
- "'" + uri.gsub("'") {|s| "'\\''"} + "'"
156
+ "'" + remote.gsub("'") { "'\\''" } + "'"
157
+ end
158
+ end
159
+
160
+ # Adds credentials to the URI as Fetcher#configured_uri_for does
161
+ def configured_uri_for(uri)
162
+ if /https?:/ =~ uri
163
+ remote = URI(uri)
164
+ config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
165
+ remote.userinfo ||= config_auth
166
+ remote.to_s
167
+ else
168
+ uri
141
169
  end
142
170
  end
143
171
 
@@ -154,9 +182,7 @@ module Bundler
154
182
  return in_path { yield } if allow?
155
183
  raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"
156
184
  end
157
-
158
185
  end
159
-
160
186
  end
161
187
  end
162
188
  end
@@ -1,12 +1,11 @@
1
- require 'fileutils'
2
- require 'uri'
3
- require 'digest/sha1'
1
+ require "fileutils"
2
+ require "uri"
3
+ require "digest/sha1"
4
4
 
5
5
  module Bundler
6
6
  class Source
7
-
8
7
  class Git < Path
9
- autoload :GitProxy, 'bundler/source/git/git_proxy'
8
+ autoload :GitProxy, "bundler/source/git/git_proxy"
10
9
 
11
10
  attr_reader :uri, :ref, :branch, :options, :submodules
12
11
 
@@ -18,11 +17,11 @@ module Bundler
18
17
  @allow_remote = false
19
18
 
20
19
  # Stringify options that could be set as symbols
21
- %w(ref branch tag revision).each{|k| options[k] = options[k].to_s if options[k] }
20
+ %w(ref branch tag revision).each {|k| options[k] = options[k].to_s if options[k] }
22
21
 
23
- @uri = options["uri"] || ''
22
+ @uri = options["uri"] || ""
24
23
  @branch = options["branch"]
25
- @ref = options["ref"] || options["branch"] || options["tag"] || 'master'
24
+ @ref = options["ref"] || options["branch"] || options["tag"] || "master"
26
25
  @submodules = options["submodules"]
27
26
  @name = options["name"]
28
27
  @version = options["version"]
@@ -50,17 +49,13 @@ module Bundler
50
49
  [self.class, uri, ref, branch, name, version, submodules].hash
51
50
  end
52
51
 
53
- def eql?(o)
54
- o.is_a?(Git) &&
55
- uri == o.uri &&
56
- ref == o.ref &&
57
- branch == o.branch &&
58
- name == o.name &&
59
- version == o.version &&
60
- submodules == o.submodules
52
+ def eql?(other)
53
+ other.is_a?(Git) && uri == other.uri && ref == other.ref &&
54
+ branch == other.branch && name == other.name &&
55
+ version == other.version && submodules == other.submodules
61
56
  end
62
57
 
63
- alias == eql?
58
+ alias_method :==, :eql?
64
59
 
65
60
  def to_s
66
61
  at = if local?
@@ -70,11 +65,18 @@ module Bundler
70
65
  else
71
66
  ref
72
67
  end
73
- "#{uri} (at #{at})"
68
+
69
+ rev = begin
70
+ "@#{shortref_for_display(revision)}"
71
+ rescue GitError
72
+ nil
73
+ end
74
+
75
+ "#{uri} (at #{at}#{rev})"
74
76
  end
75
77
 
76
78
  def name
77
- File.basename(@uri, '.git')
79
+ File.basename(@uri, ".git")
78
80
  end
79
81
 
80
82
  # This is the path which is going to contain a specific
@@ -93,7 +95,7 @@ module Bundler
93
95
  end
94
96
  end
95
97
 
96
- alias :path :install_path
98
+ alias_method :path, :install_path
97
99
 
98
100
  def extension_dir_name
99
101
  "#{base_name}-#{shortref_for_path(revision)}"
@@ -145,9 +147,7 @@ module Bundler
145
147
 
146
148
  # TODO: actually cache git specs
147
149
  def specs(*)
148
- if has_app_cache? && !local?
149
- set_local!(app_cache_path)
150
- end
150
+ set_local!(app_cache_path) if has_app_cache? && !local?
151
151
 
152
152
  if requires_checkout? && !@copied
153
153
  git_proxy.checkout
@@ -160,7 +160,7 @@ module Bundler
160
160
  end
161
161
 
162
162
  def install(spec, force = false)
163
- Bundler.ui.info "Using #{version_message(spec)} from #{to_s}"
163
+ Bundler.ui.info "Using #{version_message(spec)} from #{self}"
164
164
 
165
165
  if requires_checkout? && !@copied && !force
166
166
  Bundler.ui.debug " * Checking out revision: #{ref}"
@@ -188,7 +188,7 @@ module Bundler
188
188
  super
189
189
  rescue PathError => e
190
190
  Bundler.ui.trace e
191
- raise GitError, "#{to_s} is not yet checked out. Run `bundle install` first."
191
+ raise GitError, "#{self} is not yet checked out. Run `bundle install` first."
192
192
  end
193
193
 
194
194
  # This is the path which is going to contain a cache
@@ -219,7 +219,7 @@ module Bundler
219
219
  @allow_remote || @allow_cached
220
220
  end
221
221
 
222
- private
222
+ private
223
223
 
224
224
  def serialize_gemspecs_in(destination)
225
225
  expanded_path = destination.expand_path(Bundler.root)
@@ -229,7 +229,7 @@ module Bundler
229
229
  # The gemspecs we cache should already be evaluated.
230
230
  spec = Bundler.load_gemspec(spec_path)
231
231
  next unless spec
232
- File.open(spec_path, 'wb') {|file| file.write(spec.to_ruby) }
232
+ File.open(spec_path, "wb") {|file| file.write(spec.to_ruby) }
233
233
  end
234
234
  end
235
235
 
@@ -252,7 +252,7 @@ module Bundler
252
252
  end
253
253
 
254
254
  def base_name
255
- File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*},''),".git")
255
+ File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*}, ""), ".git")
256
256
  end
257
257
 
258
258
  def shortref_for_display(ref)
@@ -267,7 +267,7 @@ module Bundler
267
267
  if uri =~ %r{^\w+://(\w+@)?}
268
268
  # Downcase the domain component of the URI
269
269
  # and strip off a trailing slash, if one is present
270
- input = URI.parse(uri).normalize.to_s.sub(%r{/$},'')
270
+ input = URI.parse(uri).normalize.to_s.sub(%r{/$}, "")
271
271
  else
272
272
  # If there is no URI scheme, assume it is an ssh/git URI
273
273
  input = uri
@@ -286,8 +286,6 @@ module Bundler
286
286
  def git_proxy
287
287
  @git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision, self)
288
288
  end
289
-
290
289
  end
291
-
292
290
  end
293
291
  end