bundler 1.2.5 → 1.3.0.pre
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/.gitignore +10 -7
- data/.travis.yml +12 -3
- data/CHANGELOG.md +26 -19
- data/CONTRIBUTE.md +97 -0
- data/README.md +4 -2
- data/Rakefile +17 -59
- data/bundler.gemspec +2 -1
- data/lib/bundler.rb +23 -20
- data/lib/bundler/cli.rb +68 -22
- data/lib/bundler/definition.rb +3 -2
- data/lib/bundler/deprecate.rb +15 -0
- data/lib/bundler/dsl.rb +14 -16
- data/lib/bundler/environment.rb +0 -5
- data/lib/bundler/fetcher.rb +23 -78
- data/lib/bundler/friendly_errors.rb +4 -5
- data/lib/bundler/gem_helper.rb +14 -16
- data/lib/bundler/injector.rb +64 -0
- data/lib/bundler/installer.rb +1 -7
- data/lib/bundler/lazy_specification.rb +6 -3
- data/lib/bundler/lockfile_parser.rb +25 -13
- data/lib/bundler/resolver.rb +0 -1
- data/lib/bundler/rubygems_integration.rb +83 -17
- data/lib/bundler/settings.rb +4 -2
- data/lib/bundler/similarity_detector.rb +63 -0
- data/lib/bundler/source.rb +3 -886
- data/lib/bundler/source/git.rb +267 -0
- data/lib/bundler/source/git/git_proxy.rb +142 -0
- data/lib/bundler/source/path.rb +209 -0
- data/lib/bundler/source/path/installer.rb +33 -0
- data/lib/bundler/source/rubygems.rb +261 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -0
- data/lib/bundler/templates/newgem/rspec.tt +2 -0
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +9 -0
- data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -0
- data/lib/bundler/templates/newgem/test/minitest_helper.rb.tt +4 -0
- data/lib/bundler/templates/newgem/test/test_newgem.rb.tt +11 -0
- data/lib/bundler/ui.rb +20 -5
- data/lib/bundler/vendor/.document +0 -0
- data/lib/bundler/vendor/thor.rb +74 -5
- data/lib/bundler/vendor/thor/actions.rb +5 -5
- data/lib/bundler/vendor/thor/actions/directory.rb +1 -0
- data/lib/bundler/vendor/thor/actions/file_manipulation.rb +7 -1
- data/lib/bundler/vendor/thor/base.rb +44 -11
- data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +5 -0
- data/lib/bundler/vendor/thor/parser/argument.rb +14 -7
- data/lib/bundler/vendor/thor/parser/arguments.rb +7 -1
- data/lib/bundler/vendor/thor/parser/option.rb +8 -8
- data/lib/bundler/vendor/thor/parser/options.rb +62 -24
- data/lib/bundler/vendor/thor/runner.rb +1 -1
- data/lib/bundler/vendor/thor/shell/basic.rb +2 -2
- data/lib/bundler/vendor/thor/task.rb +2 -2
- data/lib/bundler/vendor/thor/version.rb +1 -1
- data/lib/bundler/vendored_persistent.rb +3 -15
- data/lib/bundler/version.rb +1 -1
- data/man/bundle-exec.ronn +1 -1
- data/man/bundle-update.ronn +1 -1
- data/man/bundle.ronn +4 -1
- data/spec/bundler/bundler_spec.rb +2 -28
- data/spec/bundler/cli_rspec.rb +9 -0
- data/spec/bundler/definition_spec.rb +1 -1
- data/spec/bundler/dsl_spec.rb +15 -8
- data/spec/bundler/gem_helper_spec.rb +38 -21
- data/spec/bundler/psyched_yaml_spec.rb +1 -0
- data/spec/bundler/source_spec.rb +3 -3
- data/spec/cache/gems_spec.rb +24 -24
- data/spec/cache/git_spec.rb +21 -23
- data/spec/cache/path_spec.rb +11 -11
- data/spec/cache/platform_spec.rb +6 -6
- data/spec/install/deploy_spec.rb +38 -38
- data/spec/install/gems/c_ext_spec.rb +2 -2
- data/spec/install/gems/dependency_api_spec.rb +23 -116
- data/spec/install/gems/env_spec.rb +1 -1
- data/spec/install/gems/flex_spec.rb +7 -8
- data/spec/install/gems/groups_spec.rb +10 -10
- data/spec/install/gems/packed_spec.rb +4 -4
- data/spec/install/gems/platform_spec.rb +3 -3
- data/spec/install/gems/post_install_spec.rb +9 -9
- data/spec/install/gems/resolving_spec.rb +2 -2
- data/spec/install/gems/simple_case_spec.rb +50 -53
- data/spec/install/gems/standalone_spec.rb +19 -19
- data/spec/install/gems/sudo_spec.rb +31 -16
- data/spec/install/gems/win32_spec.rb +1 -1
- data/spec/install/gemspec_spec.rb +6 -6
- data/spec/install/git_spec.rb +34 -34
- data/spec/install/invalid_spec.rb +3 -3
- data/spec/install/path_spec.rb +71 -8
- data/spec/install/upgrade_spec.rb +2 -2
- data/spec/integration/inject.rb +78 -0
- data/spec/lock/git_spec.rb +2 -2
- data/spec/lock/lockfile_spec.rb +14 -14
- data/spec/other/check_spec.rb +29 -29
- data/spec/other/clean_spec.rb +47 -48
- data/spec/other/config_spec.rb +20 -20
- data/spec/other/console_spec.rb +5 -5
- data/spec/other/exec_spec.rb +48 -28
- data/spec/other/ext_spec.rb +3 -3
- data/spec/other/help_spec.rb +6 -6
- data/spec/other/init_spec.rb +8 -8
- data/spec/other/newgem_spec.rb +95 -15
- data/spec/other/open_spec.rb +10 -5
- data/spec/other/outdated_spec.rb +8 -8
- data/spec/other/platform_spec.rb +45 -45
- data/spec/other/show_spec.rb +10 -10
- data/spec/quality_spec.rb +2 -2
- data/spec/realworld/dependency_api_spec.rb +61 -0
- data/spec/realworld/edgecases_spec.rb +8 -8
- data/spec/runtime/executable_spec.rb +13 -13
- data/spec/runtime/load_spec.rb +12 -12
- data/spec/runtime/platform_spec.rb +1 -1
- data/spec/runtime/require_spec.rb +24 -24
- data/spec/runtime/setup_spec.rb +113 -56
- data/spec/runtime/with_clean_env_spec.rb +11 -13
- data/spec/spec_helper.rb +6 -0
- data/spec/support/artifice/endpoint.rb +28 -13
- data/spec/support/artifice/endpoint_extra.rb +4 -0
- data/spec/support/builders.rb +1 -1
- data/spec/support/helpers.rb +2 -7
- data/spec/support/indexes.rb +3 -3
- data/spec/support/matchers.rb +6 -6
- data/spec/update/gems_spec.rb +19 -8
- data/spec/update/git_spec.rb +10 -10
- data/spec/update/source_spec.rb +1 -1
- metadata +86 -55
- data/.rspec +0 -2
data/lib/bundler/settings.rb
CHANGED
@@ -111,6 +111,7 @@ module Bundler
|
|
111
111
|
hash[key] = value
|
112
112
|
hash.delete(key) if value.nil?
|
113
113
|
FileUtils.mkdir_p(file.dirname)
|
114
|
+
require 'bundler/psyched_yaml'
|
114
115
|
File.open(file, "w") { |f| f.puts hash.to_yaml }
|
115
116
|
end
|
116
117
|
value
|
@@ -127,9 +128,10 @@ module Bundler
|
|
127
128
|
|
128
129
|
def load_config(config_file)
|
129
130
|
if config_file.exist? && !config_file.size.zero?
|
130
|
-
|
131
|
+
Hash[config_file.read.scan(/^(BUNDLE_.+): '?(.+?)'?$/)]
|
132
|
+
else
|
133
|
+
{}
|
131
134
|
end
|
132
|
-
yaml || {}
|
133
135
|
end
|
134
136
|
|
135
137
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Bundler
|
2
|
+
class SimilarityDetector
|
3
|
+
SimilarityScore = Struct.new(:string, :distance)
|
4
|
+
|
5
|
+
# initialize with an array of words to be matched against
|
6
|
+
def initialize(corpus)
|
7
|
+
@corpus = corpus
|
8
|
+
end
|
9
|
+
|
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)
|
14
|
+
end
|
15
|
+
|
16
|
+
# return the result of 'similar_words', concatenated into a list
|
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
|
21
|
+
words[0]
|
22
|
+
elsif words.length>1
|
23
|
+
[words[0..-2].join(', '), words[-1]].join(' or ')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
protected
|
29
|
+
# http://www.informit.com/articles/article.aspx?p=683059&seqNum=36
|
30
|
+
def levenshtein_distance(this, that, ins=2, del=2, sub=1)
|
31
|
+
# ins, del, sub are weighted costs
|
32
|
+
return nil if this.nil?
|
33
|
+
return nil if that.nil?
|
34
|
+
dm = [] # distance matrix
|
35
|
+
|
36
|
+
# Initialize first row values
|
37
|
+
dm[0] = (0..this.length).collect { |i| i * ins }
|
38
|
+
fill = [0] * (this.length - 1)
|
39
|
+
|
40
|
+
# Initialize first column values
|
41
|
+
for i in 1..that.length
|
42
|
+
dm[i] = [i * del, fill.flatten]
|
43
|
+
end
|
44
|
+
|
45
|
+
# populate matrix
|
46
|
+
for i in 1..that.length
|
47
|
+
for j in 1..this.length
|
48
|
+
# critical comparison
|
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
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# The last value in matrix is the Levenshtein distance between the strings
|
59
|
+
dm[that.length][this.length]
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/lib/bundler/source.rb
CHANGED
@@ -1,890 +1,7 @@
|
|
1
|
-
require "uri"
|
2
|
-
require 'rubygems/user_interaction'
|
3
|
-
require "rubygems/installer"
|
4
|
-
require "rubygems/spec_fetcher"
|
5
|
-
require "rubygems/format"
|
6
|
-
require "digest/sha1"
|
7
|
-
require "fileutils"
|
8
|
-
|
9
1
|
module Bundler
|
10
2
|
module Source
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :remotes, :caches
|
16
|
-
attr_accessor :dependency_names
|
17
|
-
|
18
|
-
def initialize(options = {})
|
19
|
-
@options = options
|
20
|
-
@remotes = (options["remotes"] || []).map { |r| normalize_uri(r) }
|
21
|
-
@fetchers = {}
|
22
|
-
@allow_remote = false
|
23
|
-
@allow_cached = false
|
24
|
-
|
25
|
-
@caches = [ Bundler.app_cache ] +
|
26
|
-
Bundler.rubygems.gem_path.map{|p| File.expand_path("#{p}/cache") }
|
27
|
-
end
|
28
|
-
|
29
|
-
def remote!
|
30
|
-
@allow_remote = true
|
31
|
-
end
|
32
|
-
|
33
|
-
def cached!
|
34
|
-
@allow_cached = true
|
35
|
-
end
|
36
|
-
|
37
|
-
def hash
|
38
|
-
Rubygems.hash
|
39
|
-
end
|
40
|
-
|
41
|
-
def eql?(o)
|
42
|
-
Rubygems === o
|
43
|
-
end
|
44
|
-
|
45
|
-
alias == eql?
|
46
|
-
|
47
|
-
def options
|
48
|
-
{ "remotes" => @remotes.map { |r| r.to_s } }
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.from_lock(options)
|
52
|
-
s = new(options)
|
53
|
-
Array(options["remote"]).each { |r| s.add_remote(r) }
|
54
|
-
s
|
55
|
-
end
|
56
|
-
|
57
|
-
def to_lock
|
58
|
-
out = "GEM\n"
|
59
|
-
out << remotes.map {|r| " remote: #{r}\n" }.join
|
60
|
-
out << " specs:\n"
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_s
|
64
|
-
remote_names = self.remotes.map { |r| r.to_s }.join(', ')
|
65
|
-
"rubygems repository #{remote_names}"
|
66
|
-
end
|
67
|
-
alias_method :name, :to_s
|
68
|
-
|
69
|
-
def specs
|
70
|
-
@specs ||= fetch_specs
|
71
|
-
end
|
72
|
-
|
73
|
-
def install(spec)
|
74
|
-
if installed_specs[spec].any?
|
75
|
-
Bundler.ui.info "Using #{spec.name} (#{spec.version}) "
|
76
|
-
return
|
77
|
-
end
|
78
|
-
|
79
|
-
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) "
|
80
|
-
path = cached_gem(spec)
|
81
|
-
if Bundler.requires_sudo?
|
82
|
-
install_path = Bundler.tmp
|
83
|
-
bin_path = install_path.join("bin")
|
84
|
-
else
|
85
|
-
install_path = Bundler.rubygems.gem_dir
|
86
|
-
bin_path = Bundler.system_bindir
|
87
|
-
end
|
88
|
-
|
89
|
-
Bundler.rubygems.preserve_paths do
|
90
|
-
Bundler::GemInstaller.new(path,
|
91
|
-
:install_dir => install_path.to_s,
|
92
|
-
:bin_dir => bin_path.to_s,
|
93
|
-
:ignore_dependencies => true,
|
94
|
-
:wrappers => true,
|
95
|
-
:env_shebang => true
|
96
|
-
).install
|
97
|
-
end
|
98
|
-
|
99
|
-
if spec.post_install_message
|
100
|
-
Installer.post_install_messages[spec.name] = spec.post_install_message
|
101
|
-
end
|
102
|
-
|
103
|
-
# SUDO HAX
|
104
|
-
if Bundler.requires_sudo?
|
105
|
-
Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/gems"
|
106
|
-
Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/specifications"
|
107
|
-
Bundler.sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Bundler.rubygems.gem_dir}/gems/"
|
108
|
-
Bundler.sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Bundler.rubygems.gem_dir}/specifications/"
|
109
|
-
Bundler.mkdir_p Bundler.system_bindir
|
110
|
-
spec.executables.each do |exe|
|
111
|
-
Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.system_bindir}"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
spec.loaded_from = "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
|
116
|
-
end
|
117
|
-
|
118
|
-
def cache(spec)
|
119
|
-
cached_path = cached_gem(spec)
|
120
|
-
raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
|
121
|
-
return if File.dirname(cached_path) == Bundler.app_cache.to_s
|
122
|
-
Bundler.ui.info " * #{File.basename(cached_path)}"
|
123
|
-
FileUtils.cp(cached_path, Bundler.app_cache)
|
124
|
-
end
|
125
|
-
|
126
|
-
def add_remote(source)
|
127
|
-
@remotes << normalize_uri(source)
|
128
|
-
end
|
129
|
-
|
130
|
-
def replace_remotes(source)
|
131
|
-
return false if source.remotes == @remotes
|
132
|
-
|
133
|
-
@remotes = []
|
134
|
-
source.remotes.each do |r|
|
135
|
-
add_remote r.to_s
|
136
|
-
end
|
137
|
-
|
138
|
-
true
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def cached_gem(spec)
|
144
|
-
possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" }
|
145
|
-
cached_gem = possibilities.find { |p| File.exist?(p) }
|
146
|
-
unless cached_gem
|
147
|
-
raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
|
148
|
-
end
|
149
|
-
cached_gem
|
150
|
-
end
|
151
|
-
|
152
|
-
def normalize_uri(uri)
|
153
|
-
uri = uri.to_s
|
154
|
-
uri = "#{uri}/" unless uri =~ %r'/$'
|
155
|
-
uri = URI(uri)
|
156
|
-
raise ArgumentError, "The source must be an absolute URI" unless uri.absolute?
|
157
|
-
uri
|
158
|
-
end
|
159
|
-
|
160
|
-
def fetch_specs
|
161
|
-
# remote_specs usually generates a way larger Index than the other
|
162
|
-
# sources, and large_idx.use small_idx is way faster than
|
163
|
-
# small_idx.use large_idx.
|
164
|
-
if @allow_remote
|
165
|
-
idx = remote_specs.dup
|
166
|
-
else
|
167
|
-
idx = Index.new
|
168
|
-
end
|
169
|
-
idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
|
170
|
-
idx.use(installed_specs, :override_dupes)
|
171
|
-
idx
|
172
|
-
end
|
173
|
-
|
174
|
-
def installed_specs
|
175
|
-
@installed_specs ||= begin
|
176
|
-
idx = Index.new
|
177
|
-
have_bundler = false
|
178
|
-
Bundler.rubygems.all_specs.reverse.each do |spec|
|
179
|
-
next if spec.name == 'bundler' && spec.version.to_s != VERSION
|
180
|
-
have_bundler = true if spec.name == 'bundler'
|
181
|
-
spec.source = self
|
182
|
-
idx << spec
|
183
|
-
end
|
184
|
-
|
185
|
-
# Always have bundler locally
|
186
|
-
unless have_bundler
|
187
|
-
# We're running bundler directly from the source
|
188
|
-
# so, let's create a fake gemspec for it (it's a path)
|
189
|
-
# gemspec
|
190
|
-
bundler = Gem::Specification.new do |s|
|
191
|
-
s.name = 'bundler'
|
192
|
-
s.version = VERSION
|
193
|
-
s.platform = Gem::Platform::RUBY
|
194
|
-
s.source = self
|
195
|
-
s.authors = ["bundler team"]
|
196
|
-
s.loaded_from = File.expand_path("..", __FILE__)
|
197
|
-
end
|
198
|
-
idx << bundler
|
199
|
-
end
|
200
|
-
idx
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def cached_specs
|
205
|
-
@cached_specs ||= begin
|
206
|
-
idx = installed_specs.dup
|
207
|
-
|
208
|
-
path = Bundler.app_cache
|
209
|
-
Dir["#{path}/*.gem"].each do |gemfile|
|
210
|
-
next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
|
211
|
-
|
212
|
-
begin
|
213
|
-
s ||= Bundler.rubygems.spec_from_gem(gemfile)
|
214
|
-
rescue Gem::Package::FormatError
|
215
|
-
raise GemspecError, "Could not read gem at #{gemfile}. It may be corrupted."
|
216
|
-
end
|
217
|
-
|
218
|
-
s.source = self
|
219
|
-
idx << s
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
idx
|
224
|
-
end
|
225
|
-
|
226
|
-
def remote_specs
|
227
|
-
@remote_specs ||= begin
|
228
|
-
idx = Index.new
|
229
|
-
old = Bundler.rubygems.sources
|
230
|
-
|
231
|
-
sources = {}
|
232
|
-
remotes.each do |uri|
|
233
|
-
fetcher = Bundler::Fetcher.new(uri)
|
234
|
-
specs = fetcher.specs(dependency_names, self)
|
235
|
-
sources[fetcher] = specs.size
|
236
|
-
|
237
|
-
idx.use specs
|
238
|
-
end
|
239
|
-
|
240
|
-
# don't need to fetch all specifications for every gem/version on
|
241
|
-
# the rubygems repo if there's no api endpoints to search over
|
242
|
-
# or it has too many specs to fetch
|
243
|
-
fetchers = sources.keys
|
244
|
-
api_fetchers = fetchers.select {|fetcher| fetcher.has_api }
|
245
|
-
modern_index_fetchers = fetchers - api_fetchers
|
246
|
-
if api_fetchers.any? && modern_index_fetchers.all? {|fetcher| sources[fetcher] < FORCE_MODERN_INDEX_LIMIT }
|
247
|
-
# this will fetch all the specifications on the rubygems repo
|
248
|
-
unmet_dependency_names = idx.unmet_dependency_names
|
249
|
-
unmet_dependency_names -= ['bundler'] # bundler will always be unmet
|
250
|
-
|
251
|
-
Bundler.ui.debug "Unmet Dependencies: #{unmet_dependency_names}"
|
252
|
-
if unmet_dependency_names.any?
|
253
|
-
api_fetchers.each do |fetcher|
|
254
|
-
idx.use fetcher.specs(unmet_dependency_names, self)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
else
|
258
|
-
Bundler::Fetcher.disable_endpoint = true
|
259
|
-
api_fetchers.each {|fetcher| idx.use fetcher.specs([], self) }
|
260
|
-
end
|
261
|
-
|
262
|
-
idx
|
263
|
-
ensure
|
264
|
-
Bundler.rubygems.sources = old
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
|
270
|
-
class Path
|
271
|
-
class Installer < Bundler::GemInstaller
|
272
|
-
def initialize(spec, options = {})
|
273
|
-
@spec = spec
|
274
|
-
@bin_dir = Bundler.requires_sudo? ? "#{Bundler.tmp}/bin" : "#{Bundler.rubygems.gem_dir}/bin"
|
275
|
-
@gem_dir = Bundler.rubygems.path(spec.full_gem_path)
|
276
|
-
@wrappers = options[:wrappers] || true
|
277
|
-
@env_shebang = options[:env_shebang] || true
|
278
|
-
@format_executable = options[:format_executable] || false
|
279
|
-
end
|
280
|
-
|
281
|
-
def generate_bin
|
282
|
-
return if spec.executables.nil? || spec.executables.empty?
|
283
|
-
|
284
|
-
if Bundler.requires_sudo?
|
285
|
-
FileUtils.mkdir_p("#{Bundler.tmp}/bin") unless File.exist?("#{Bundler.tmp}/bin")
|
286
|
-
end
|
287
|
-
super
|
288
|
-
if Bundler.requires_sudo?
|
289
|
-
Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/bin"
|
290
|
-
spec.executables.each do |exe|
|
291
|
-
Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.rubygems.gem_dir}/bin/"
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
attr_reader :path, :options
|
298
|
-
attr_writer :name
|
299
|
-
attr_accessor :version
|
300
|
-
|
301
|
-
DEFAULT_GLOB = "{,*,*/*}.gemspec"
|
302
|
-
|
303
|
-
def initialize(options)
|
304
|
-
@options = options
|
305
|
-
@glob = options["glob"] || DEFAULT_GLOB
|
306
|
-
|
307
|
-
@allow_cached = false
|
308
|
-
@allow_remote = false
|
309
|
-
|
310
|
-
if options["path"]
|
311
|
-
@path = Pathname.new(options["path"])
|
312
|
-
@path = @path.expand_path(Bundler.root) unless @path.relative?
|
313
|
-
end
|
314
|
-
|
315
|
-
@name = options["name"]
|
316
|
-
@version = options["version"]
|
317
|
-
|
318
|
-
# Stores the original path. If at any point we move to the
|
319
|
-
# cached directory, we still have the original path to copy from.
|
320
|
-
@original_path = @path
|
321
|
-
end
|
322
|
-
|
323
|
-
def remote!
|
324
|
-
@allow_remote = true
|
325
|
-
end
|
326
|
-
|
327
|
-
def cached!
|
328
|
-
@allow_cached = true
|
329
|
-
end
|
330
|
-
|
331
|
-
def self.from_lock(options)
|
332
|
-
new(options.merge("path" => options.delete("remote")))
|
333
|
-
end
|
334
|
-
|
335
|
-
def to_lock
|
336
|
-
out = "PATH\n"
|
337
|
-
out << " remote: #{relative_path}\n"
|
338
|
-
out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
|
339
|
-
out << " specs:\n"
|
340
|
-
end
|
341
|
-
|
342
|
-
def to_s
|
343
|
-
"source at #{@path}"
|
344
|
-
end
|
345
|
-
|
346
|
-
def hash
|
347
|
-
self.class.hash
|
348
|
-
end
|
349
|
-
|
350
|
-
def eql?(o)
|
351
|
-
o.instance_of?(Path) &&
|
352
|
-
path.expand_path(Bundler.root) == o.path.expand_path(Bundler.root) &&
|
353
|
-
version == o.version
|
354
|
-
end
|
355
|
-
|
356
|
-
alias == eql?
|
357
|
-
|
358
|
-
def name
|
359
|
-
File.basename(path.expand_path(Bundler.root).to_s)
|
360
|
-
end
|
361
|
-
|
362
|
-
def install(spec)
|
363
|
-
Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
|
364
|
-
# Let's be honest, when we're working from a path, we can't
|
365
|
-
# really expect native extensions to work because the whole point
|
366
|
-
# is to just be able to modify what's in that path and go. So, let's
|
367
|
-
# not put ourselves through the pain of actually trying to generate
|
368
|
-
# the full gem.
|
369
|
-
Installer.new(spec).generate_bin
|
370
|
-
end
|
371
|
-
|
372
|
-
def cache(spec)
|
373
|
-
return unless Bundler.settings[:cache_all]
|
374
|
-
return if @original_path.expand_path(Bundler.root).to_s.index(Bundler.root.to_s) == 0
|
375
|
-
FileUtils.rm_rf(app_cache_path)
|
376
|
-
FileUtils.cp_r("#{@original_path}/.", app_cache_path)
|
377
|
-
FileUtils.touch(app_cache_path.join(".bundlecache"))
|
378
|
-
end
|
379
|
-
|
380
|
-
def local_specs(*)
|
381
|
-
@local_specs ||= load_spec_files
|
382
|
-
end
|
383
|
-
|
384
|
-
def specs
|
385
|
-
if has_app_cache?
|
386
|
-
@path = app_cache_path
|
387
|
-
end
|
388
|
-
local_specs
|
389
|
-
end
|
390
|
-
|
391
|
-
def app_cache_dirname
|
392
|
-
name
|
393
|
-
end
|
394
|
-
|
395
|
-
private
|
396
|
-
|
397
|
-
def app_cache_path
|
398
|
-
@app_cache_path ||= Bundler.app_cache.join(app_cache_dirname)
|
399
|
-
end
|
400
|
-
|
401
|
-
def has_app_cache?
|
402
|
-
SharedHelpers.in_bundle? && app_cache_path.exist?
|
403
|
-
end
|
404
|
-
|
405
|
-
def load_spec_files
|
406
|
-
index = Index.new
|
407
|
-
expanded_path = path.expand_path(Bundler.root)
|
408
|
-
|
409
|
-
if File.directory?(expanded_path)
|
410
|
-
Dir["#{expanded_path}/#{@glob}"].each do |file|
|
411
|
-
spec = Bundler.load_gemspec(file)
|
412
|
-
if spec
|
413
|
-
spec.loaded_from = file.to_s
|
414
|
-
spec.source = self
|
415
|
-
index << spec
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
if index.empty? && @name && @version
|
420
|
-
index << Gem::Specification.new do |s|
|
421
|
-
s.name = @name
|
422
|
-
s.source = self
|
423
|
-
s.version = Gem::Version.new(@version)
|
424
|
-
s.platform = Gem::Platform::RUBY
|
425
|
-
s.summary = "Fake gemspec for #{@name}"
|
426
|
-
s.relative_loaded_from = "#{@name}.gemspec"
|
427
|
-
s.authors = ["no one"]
|
428
|
-
if expanded_path.join("bin").exist?
|
429
|
-
executables = expanded_path.join("bin").children
|
430
|
-
executables.reject!{|p| File.directory?(p) }
|
431
|
-
s.executables = executables.map{|c| c.basename.to_s }
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
else
|
436
|
-
raise PathError, "The path `#{expanded_path}` does not exist."
|
437
|
-
end
|
438
|
-
|
439
|
-
index
|
440
|
-
end
|
441
|
-
|
442
|
-
def relative_path
|
443
|
-
if path.to_s.match(%r{^#{Regexp.escape Bundler.root.to_s}})
|
444
|
-
return path.relative_path_from(Bundler.root)
|
445
|
-
end
|
446
|
-
path
|
447
|
-
end
|
448
|
-
|
449
|
-
def generate_bin(spec)
|
450
|
-
gem_dir = Pathname.new(spec.full_gem_path)
|
451
|
-
|
452
|
-
# Some gem authors put absolute paths in their gemspec
|
453
|
-
# and we have to save them from themselves
|
454
|
-
spec.files = spec.files.map do |p|
|
455
|
-
next if File.directory?(p)
|
456
|
-
begin
|
457
|
-
Pathname.new(p).relative_path_from(gem_dir).to_s
|
458
|
-
rescue ArgumentError
|
459
|
-
p
|
460
|
-
end
|
461
|
-
end.compact
|
462
|
-
|
463
|
-
gem_file = Dir.chdir(gem_dir){ Gem::Builder.new(spec).build }
|
464
|
-
|
465
|
-
installer = Path::Installer.new(spec, :env_shebang => false)
|
466
|
-
run_hooks(:pre_install, installer)
|
467
|
-
installer.build_extensions
|
468
|
-
run_hooks(:post_build, installer)
|
469
|
-
installer.generate_bin
|
470
|
-
run_hooks(:post_install, installer)
|
471
|
-
rescue Gem::InvalidSpecificationException => e
|
472
|
-
Bundler.ui.warn "\n#{spec.name} at #{spec.full_gem_path} did not have a valid gemspec.\n" \
|
473
|
-
"This prevents bundler from installing bins or native extensions, but " \
|
474
|
-
"that may not affect its functionality."
|
475
|
-
|
476
|
-
if !spec.extensions.empty? && !spec.email.empty?
|
477
|
-
Bundler.ui.warn "If you need to use this package without installing it from a gem " \
|
478
|
-
"repository, please contact #{spec.email} and ask them " \
|
479
|
-
"to modify their .gemspec so it can work with `gem build`."
|
480
|
-
end
|
481
|
-
|
482
|
-
Bundler.ui.warn "The validation message from Rubygems was:\n #{e.message}"
|
483
|
-
ensure
|
484
|
-
Dir.chdir(gem_dir){ FileUtils.rm_rf(gem_file) if gem_file && File.exist?(gem_file) }
|
485
|
-
end
|
486
|
-
|
487
|
-
def run_hooks(type, installer)
|
488
|
-
hooks_meth = "#{type}_hooks"
|
489
|
-
return unless Gem.respond_to?(hooks_meth)
|
490
|
-
Gem.send(hooks_meth).each do |hook|
|
491
|
-
result = hook.call(installer)
|
492
|
-
if result == false
|
493
|
-
location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
|
494
|
-
message = "#{type} hook#{location} failed for #{installer.spec.full_name}"
|
495
|
-
raise InstallHookError, message
|
496
|
-
end
|
497
|
-
end
|
498
|
-
end
|
499
|
-
end
|
500
|
-
|
501
|
-
class Git < Path
|
502
|
-
# The GitProxy is responsible to iteract with git repositories.
|
503
|
-
# All actions required by the Git source is encapsualted in this
|
504
|
-
# object.
|
505
|
-
class GitProxy
|
506
|
-
attr_accessor :path, :uri, :ref, :revision
|
507
|
-
|
508
|
-
def initialize(path, uri, ref, revision=nil, &allow)
|
509
|
-
@path = path
|
510
|
-
@uri = uri
|
511
|
-
@ref = ref
|
512
|
-
@revision = revision
|
513
|
-
@allow = allow || Proc.new { true }
|
514
|
-
end
|
515
|
-
|
516
|
-
remove_method :revision if method_defined? :revision
|
517
|
-
def revision
|
518
|
-
@revision ||= allowed_in_path { git("rev-parse #{ref}").strip }
|
519
|
-
end
|
520
|
-
|
521
|
-
def branch
|
522
|
-
@branch ||= allowed_in_path do
|
523
|
-
git("branch") =~ /^\* (.*)$/ && $1.strip
|
524
|
-
end
|
525
|
-
end
|
526
|
-
|
527
|
-
def contains?(commit)
|
528
|
-
allowed_in_path do
|
529
|
-
result = git_null("branch --contains #{commit}")
|
530
|
-
$? == 0 && result =~ /^\* (.*)$/
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
def checkout
|
535
|
-
if path.exist?
|
536
|
-
return if has_revision_cached?
|
537
|
-
Bundler.ui.info "Updating #{uri}"
|
538
|
-
in_path do
|
539
|
-
git %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"|
|
540
|
-
end
|
541
|
-
else
|
542
|
-
Bundler.ui.info "Fetching #{uri}"
|
543
|
-
FileUtils.mkdir_p(path.dirname)
|
544
|
-
git %|clone #{uri_escaped} "#{path}" --bare --no-hardlinks|
|
545
|
-
end
|
546
|
-
end
|
547
|
-
|
548
|
-
def copy_to(destination, submodules=false)
|
549
|
-
unless File.exist?(destination.join(".git"))
|
550
|
-
FileUtils.mkdir_p(destination.dirname)
|
551
|
-
FileUtils.rm_rf(destination)
|
552
|
-
git %|clone --no-checkout "#{path}" "#{destination}"|
|
553
|
-
File.chmod((0777 & ~File.umask), destination)
|
554
|
-
end
|
555
|
-
|
556
|
-
Dir.chdir(destination) do
|
557
|
-
git %|fetch --force --quiet --tags "#{path}"|
|
558
|
-
git "reset --hard #{@revision}"
|
559
|
-
|
560
|
-
if submodules
|
561
|
-
git "submodule update --init --recursive"
|
562
|
-
end
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
private
|
567
|
-
|
568
|
-
# TODO: Do not rely on /dev/null.
|
569
|
-
# Given that open3 is not cross platform until Ruby 1.9.3,
|
570
|
-
# the best solution is to pipe to /dev/null if it exists.
|
571
|
-
# If it doesn't, everything will work fine, but the user
|
572
|
-
# will get the $stderr messages as well.
|
573
|
-
def git_null(command)
|
574
|
-
if !Bundler::WINDOWS && File.exist?("/dev/null")
|
575
|
-
git("#{command} 2>/dev/null", false)
|
576
|
-
else
|
577
|
-
git(command, false)
|
578
|
-
end
|
579
|
-
end
|
580
|
-
|
581
|
-
def git(command, check_errors=true)
|
582
|
-
if allow?
|
583
|
-
out = %x{git #{command}}
|
584
|
-
|
585
|
-
if check_errors && $?.exitstatus != 0
|
586
|
-
msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed."
|
587
|
-
msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
|
588
|
-
raise GitError, msg
|
589
|
-
end
|
590
|
-
out
|
591
|
-
else
|
592
|
-
raise GitError, "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " \
|
593
|
-
"this error message could probably be more useful. Please submit a ticket at http://github.com/carlhuda/bundler/issues " \
|
594
|
-
"with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
|
595
|
-
end
|
596
|
-
end
|
597
|
-
|
598
|
-
def has_revision_cached?
|
599
|
-
return unless @revision
|
600
|
-
in_path { git("cat-file -e #{@revision}") }
|
601
|
-
true
|
602
|
-
rescue GitError
|
603
|
-
false
|
604
|
-
end
|
605
|
-
|
606
|
-
# Escape the URI for git commands
|
607
|
-
def uri_escaped
|
608
|
-
if Bundler::WINDOWS
|
609
|
-
# Windows quoting requires double quotes only, with double quotes
|
610
|
-
# inside the string escaped by being doubled.
|
611
|
-
'"' + uri.gsub('"') {|s| '""'} + '"'
|
612
|
-
else
|
613
|
-
# Bash requires single quoted strings, with the single quotes escaped
|
614
|
-
# by ending the string, escaping the quote, and restarting the string.
|
615
|
-
"'" + uri.gsub("'") {|s| "'\\''"} + "'"
|
616
|
-
end
|
617
|
-
end
|
618
|
-
|
619
|
-
def allow?
|
620
|
-
@allow.call
|
621
|
-
end
|
622
|
-
|
623
|
-
def in_path(&blk)
|
624
|
-
checkout unless path.exist?
|
625
|
-
Dir.chdir(path, &blk)
|
626
|
-
end
|
627
|
-
|
628
|
-
def allowed_in_path
|
629
|
-
if allow?
|
630
|
-
in_path { yield }
|
631
|
-
else
|
632
|
-
raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"
|
633
|
-
end
|
634
|
-
end
|
635
|
-
end
|
636
|
-
|
637
|
-
attr_reader :uri, :ref, :branch, :options, :submodules
|
638
|
-
|
639
|
-
def initialize(options)
|
640
|
-
@options = options
|
641
|
-
@glob = options["glob"] || DEFAULT_GLOB
|
642
|
-
|
643
|
-
@allow_cached = false
|
644
|
-
@allow_remote = false
|
645
|
-
|
646
|
-
# Stringify options that could be set as symbols
|
647
|
-
%w(ref branch tag revision).each{|k| options[k] = options[k].to_s if options[k] }
|
648
|
-
|
649
|
-
@uri = options["uri"]
|
650
|
-
@branch = options["branch"]
|
651
|
-
@ref = options["ref"] || options["branch"] || options["tag"] || 'master'
|
652
|
-
@submodules = options["submodules"]
|
653
|
-
@name = options["name"]
|
654
|
-
@version = options["version"]
|
655
|
-
|
656
|
-
@update = false
|
657
|
-
@installed = nil
|
658
|
-
@local = false
|
659
|
-
end
|
660
|
-
|
661
|
-
def self.from_lock(options)
|
662
|
-
new(options.merge("uri" => options.delete("remote")))
|
663
|
-
end
|
664
|
-
|
665
|
-
def to_lock
|
666
|
-
out = "GIT\n"
|
667
|
-
out << " remote: #{@uri}\n"
|
668
|
-
out << " revision: #{revision}\n"
|
669
|
-
%w(ref branch tag submodules).each do |opt|
|
670
|
-
out << " #{opt}: #{options[opt]}\n" if options[opt]
|
671
|
-
end
|
672
|
-
out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
|
673
|
-
out << " specs:\n"
|
674
|
-
end
|
675
|
-
|
676
|
-
def eql?(o)
|
677
|
-
Git === o &&
|
678
|
-
uri == o.uri &&
|
679
|
-
ref == o.ref &&
|
680
|
-
branch == o.branch &&
|
681
|
-
name == o.name &&
|
682
|
-
version == o.version &&
|
683
|
-
submodules == o.submodules
|
684
|
-
end
|
685
|
-
|
686
|
-
alias == eql?
|
687
|
-
|
688
|
-
def to_s
|
689
|
-
at = if local?
|
690
|
-
path
|
691
|
-
elsif options["ref"]
|
692
|
-
shortref_for_display(options["ref"])
|
693
|
-
else
|
694
|
-
ref
|
695
|
-
end
|
696
|
-
"#{uri} (at #{at})"
|
697
|
-
end
|
698
|
-
|
699
|
-
def name
|
700
|
-
File.basename(@uri, '.git')
|
701
|
-
end
|
702
|
-
|
703
|
-
# This is the path which is going to contain a specific
|
704
|
-
# checkout of the git repository. When using local git
|
705
|
-
# repos, this is set to the local repo.
|
706
|
-
def install_path
|
707
|
-
@install_path ||= begin
|
708
|
-
git_scope = "#{base_name}-#{shortref_for_path(revision)}"
|
709
|
-
|
710
|
-
if Bundler.requires_sudo?
|
711
|
-
Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
|
712
|
-
else
|
713
|
-
Bundler.install_path.join(git_scope)
|
714
|
-
end
|
715
|
-
end
|
716
|
-
end
|
717
|
-
|
718
|
-
alias :path :install_path
|
719
|
-
|
720
|
-
def unlock!
|
721
|
-
git_proxy.revision = nil
|
722
|
-
end
|
723
|
-
|
724
|
-
def local_override!(path)
|
725
|
-
return false if local?
|
726
|
-
|
727
|
-
path = Pathname.new(path)
|
728
|
-
path = path.expand_path(Bundler.root) unless path.relative?
|
729
|
-
|
730
|
-
unless options["branch"] || Bundler.settings[:disable_local_branch_check]
|
731
|
-
raise GitError, "Cannot use local override for #{name} at #{path} because " \
|
732
|
-
":branch is not specified in Gemfile. Specify a branch or use " \
|
733
|
-
"`bundle config --delete` to remove the local override"
|
734
|
-
end
|
735
|
-
|
736
|
-
unless path.exist?
|
737
|
-
raise GitError, "Cannot use local override for #{name} because #{path} " \
|
738
|
-
"does not exist. Check `bundle config --delete` to remove the local override"
|
739
|
-
end
|
740
|
-
|
741
|
-
set_local!(path)
|
742
|
-
|
743
|
-
# Create a new git proxy without the cached revision
|
744
|
-
# so the Gemfile.lock always picks up the new revision.
|
745
|
-
@git_proxy = GitProxy.new(path, uri, ref)
|
746
|
-
|
747
|
-
if git_proxy.branch != options["branch"] && !Bundler.settings[:disable_local_branch_check]
|
748
|
-
raise GitError, "Local override for #{name} at #{path} is using branch " \
|
749
|
-
"#{git_proxy.branch} but Gemfile specifies #{options["branch"]}"
|
750
|
-
end
|
751
|
-
|
752
|
-
changed = cached_revision && cached_revision != git_proxy.revision
|
753
|
-
|
754
|
-
if changed && !git_proxy.contains?(cached_revision)
|
755
|
-
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
|
756
|
-
"but the current branch in your local override for #{name} does not contain such commit. " \
|
757
|
-
"Please make sure your branch is up to date."
|
758
|
-
end
|
759
|
-
|
760
|
-
changed
|
761
|
-
end
|
762
|
-
|
763
|
-
# TODO: actually cache git specs
|
764
|
-
def specs(*)
|
765
|
-
if has_app_cache? && !local?
|
766
|
-
set_local!(app_cache_path)
|
767
|
-
end
|
768
|
-
|
769
|
-
if requires_checkout? && !@update
|
770
|
-
git_proxy.checkout
|
771
|
-
git_proxy.copy_to(install_path, submodules)
|
772
|
-
@update = true
|
773
|
-
end
|
774
|
-
|
775
|
-
local_specs
|
776
|
-
end
|
777
|
-
|
778
|
-
def install(spec)
|
779
|
-
Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
|
780
|
-
if requires_checkout? && !@installed
|
781
|
-
Bundler.ui.debug " * Checking out revision: #{ref}"
|
782
|
-
git_proxy.copy_to(install_path, submodules)
|
783
|
-
@installed = true
|
784
|
-
end
|
785
|
-
generate_bin(spec)
|
786
|
-
end
|
787
|
-
|
788
|
-
def cache(spec)
|
789
|
-
return unless Bundler.settings[:cache_all]
|
790
|
-
return if path == app_cache_path
|
791
|
-
cached!
|
792
|
-
FileUtils.rm_rf(app_cache_path)
|
793
|
-
git_proxy.checkout if requires_checkout?
|
794
|
-
git_proxy.copy_to(app_cache_path, @submodules)
|
795
|
-
FileUtils.rm_rf(app_cache_path.join(".git"))
|
796
|
-
FileUtils.touch(app_cache_path.join(".bundlecache"))
|
797
|
-
end
|
798
|
-
|
799
|
-
def load_spec_files
|
800
|
-
super
|
801
|
-
rescue PathError, GitError
|
802
|
-
raise GitError, "#{to_s} is not checked out. Please run `bundle install`"
|
803
|
-
end
|
804
|
-
|
805
|
-
# This is the path which is going to contain a cache
|
806
|
-
# of the git repository. When using the same git repository
|
807
|
-
# across different projects, this cache will be shared.
|
808
|
-
# When using local git repos, this is set to the local repo.
|
809
|
-
def cache_path
|
810
|
-
@cache_path ||= begin
|
811
|
-
git_scope = "#{base_name}-#{uri_hash}"
|
812
|
-
|
813
|
-
if Bundler.requires_sudo?
|
814
|
-
Bundler.user_bundle_path.join("cache/git", git_scope)
|
815
|
-
else
|
816
|
-
Bundler.cache.join("git", git_scope)
|
817
|
-
end
|
818
|
-
end
|
819
|
-
end
|
820
|
-
|
821
|
-
def app_cache_dirname
|
822
|
-
"#{base_name}-#{shortref_for_path(cached_revision || revision)}"
|
823
|
-
end
|
824
|
-
|
825
|
-
private
|
826
|
-
|
827
|
-
def set_local!(path)
|
828
|
-
@local = true
|
829
|
-
@local_specs = @git_proxy = nil
|
830
|
-
@cache_path = @install_path = path
|
831
|
-
end
|
832
|
-
|
833
|
-
def has_app_cache?
|
834
|
-
cached_revision && super
|
835
|
-
end
|
836
|
-
|
837
|
-
def local?
|
838
|
-
@local
|
839
|
-
end
|
840
|
-
|
841
|
-
def requires_checkout?
|
842
|
-
allow_git_ops? && !local?
|
843
|
-
end
|
844
|
-
|
845
|
-
def base_name
|
846
|
-
File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*},''),".git")
|
847
|
-
end
|
848
|
-
|
849
|
-
def shortref_for_display(ref)
|
850
|
-
ref[0..6]
|
851
|
-
end
|
852
|
-
|
853
|
-
def shortref_for_path(ref)
|
854
|
-
ref[0..11]
|
855
|
-
end
|
856
|
-
|
857
|
-
def uri_hash
|
858
|
-
if uri =~ %r{^\w+://(\w+@)?}
|
859
|
-
# Downcase the domain component of the URI
|
860
|
-
# and strip off a trailing slash, if one is present
|
861
|
-
input = URI.parse(uri).normalize.to_s.sub(%r{/$},'')
|
862
|
-
else
|
863
|
-
# If there is no URI scheme, assume it is an ssh/git URI
|
864
|
-
input = uri
|
865
|
-
end
|
866
|
-
Digest::SHA1.hexdigest(input)
|
867
|
-
end
|
868
|
-
|
869
|
-
def allow_git_ops?
|
870
|
-
@allow_remote || @allow_cached
|
871
|
-
end
|
872
|
-
|
873
|
-
def cached_revision
|
874
|
-
options["revision"]
|
875
|
-
end
|
876
|
-
|
877
|
-
def revision
|
878
|
-
git_proxy.revision
|
879
|
-
end
|
880
|
-
|
881
|
-
def cached?
|
882
|
-
cache_path.exist?
|
883
|
-
end
|
884
|
-
|
885
|
-
def git_proxy
|
886
|
-
@git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision){ allow_git_ops? }
|
887
|
-
end
|
888
|
-
end
|
3
|
+
autoload :Rubygems, 'bundler/source/rubygems'
|
4
|
+
autoload :Path, 'bundler/source/path'
|
5
|
+
autoload :Git, 'bundler/source/git'
|
889
6
|
end
|
890
7
|
end
|