bundler_package_git 1.1.pre.1
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.
- data/.gitignore +22 -0
- data/.rvmrc +1 -0
- data/CHANGELOG.md +659 -0
- data/ISSUES.md +47 -0
- data/LICENSE +23 -0
- data/README.md +29 -0
- data/Rakefile +167 -0
- data/UPGRADING.md +103 -0
- data/bin/bundle +22 -0
- data/bundler.gemspec +30 -0
- data/lib/bundler.rb +283 -0
- data/lib/bundler/capistrano.rb +11 -0
- data/lib/bundler/cli.rb +490 -0
- data/lib/bundler/definition.rb +429 -0
- data/lib/bundler/dependency.rb +130 -0
- data/lib/bundler/deployment.rb +53 -0
- data/lib/bundler/dsl.rb +243 -0
- data/lib/bundler/environment.rb +47 -0
- data/lib/bundler/fetcher.rb +101 -0
- data/lib/bundler/gem_helper.rb +146 -0
- data/lib/bundler/graph.rb +130 -0
- data/lib/bundler/index.rb +131 -0
- data/lib/bundler/installer.rb +117 -0
- data/lib/bundler/lazy_specification.rb +71 -0
- data/lib/bundler/lockfile_parser.rb +108 -0
- data/lib/bundler/remote_specification.rb +57 -0
- data/lib/bundler/resolver.rb +470 -0
- data/lib/bundler/rubygems_ext.rb +226 -0
- data/lib/bundler/runtime.rb +201 -0
- data/lib/bundler/settings.rb +117 -0
- data/lib/bundler/setup.rb +16 -0
- data/lib/bundler/shared_helpers.rb +167 -0
- data/lib/bundler/source.rb +675 -0
- data/lib/bundler/spec_set.rb +134 -0
- data/lib/bundler/templates/Executable +16 -0
- data/lib/bundler/templates/Gemfile +4 -0
- data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
- data/lib/bundler/templates/newgem/Rakefile.tt +2 -0
- data/lib/bundler/templates/newgem/bin/newgem.tt +3 -0
- data/lib/bundler/templates/newgem/gitignore.tt +4 -0
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +7 -0
- data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +21 -0
- data/lib/bundler/ui.rb +73 -0
- data/lib/bundler/vendor/net/http/faster.rb +27 -0
- data/lib/bundler/vendor/net/http/persistent.rb +464 -0
- data/lib/bundler/vendor/thor.rb +319 -0
- data/lib/bundler/vendor/thor/actions.rb +297 -0
- data/lib/bundler/vendor/thor/actions/create_file.rb +105 -0
- data/lib/bundler/vendor/thor/actions/directory.rb +93 -0
- data/lib/bundler/vendor/thor/actions/empty_directory.rb +134 -0
- data/lib/bundler/vendor/thor/actions/file_manipulation.rb +229 -0
- data/lib/bundler/vendor/thor/actions/inject_into_file.rb +104 -0
- data/lib/bundler/vendor/thor/base.rb +556 -0
- data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +75 -0
- data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/bundler/vendor/thor/error.rb +30 -0
- data/lib/bundler/vendor/thor/invocation.rb +168 -0
- data/lib/bundler/vendor/thor/parser.rb +4 -0
- data/lib/bundler/vendor/thor/parser/argument.rb +67 -0
- data/lib/bundler/vendor/thor/parser/arguments.rb +161 -0
- data/lib/bundler/vendor/thor/parser/option.rb +120 -0
- data/lib/bundler/vendor/thor/parser/options.rb +174 -0
- data/lib/bundler/vendor/thor/shell.rb +88 -0
- data/lib/bundler/vendor/thor/shell/basic.rb +275 -0
- data/lib/bundler/vendor/thor/shell/color.rb +108 -0
- data/lib/bundler/vendor/thor/shell/html.rb +121 -0
- data/lib/bundler/vendor/thor/task.rb +114 -0
- data/lib/bundler/vendor/thor/util.rb +229 -0
- data/lib/bundler/vendor/thor/version.rb +3 -0
- data/lib/bundler/version.rb +6 -0
- data/lib/bundler/vlad.rb +9 -0
- data/man/bundle-config.ronn +90 -0
- data/man/bundle-exec.ronn +111 -0
- data/man/bundle-install.ronn +314 -0
- data/man/bundle-package.ronn +59 -0
- data/man/bundle-update.ronn +176 -0
- data/man/bundle.ronn +80 -0
- data/man/gemfile.5.ronn +279 -0
- data/man/index.txt +6 -0
- data/spec/cache/gems_spec.rb +219 -0
- data/spec/cache/git_spec.rb +9 -0
- data/spec/cache/path_spec.rb +27 -0
- data/spec/cache/platform_spec.rb +57 -0
- data/spec/install/deploy_spec.rb +197 -0
- data/spec/install/deprecated_spec.rb +37 -0
- data/spec/install/gems/c_ext_spec.rb +48 -0
- data/spec/install/gems/dependency_api_spec.rb +85 -0
- data/spec/install/gems/env_spec.rb +107 -0
- data/spec/install/gems/flex_spec.rb +313 -0
- data/spec/install/gems/groups_spec.rb +245 -0
- data/spec/install/gems/packed_spec.rb +84 -0
- data/spec/install/gems/platform_spec.rb +208 -0
- data/spec/install/gems/resolving_spec.rb +72 -0
- data/spec/install/gems/simple_case_spec.rb +715 -0
- data/spec/install/gems/standalone_spec.rb +162 -0
- data/spec/install/gems/sudo_spec.rb +73 -0
- data/spec/install/gems/win32_spec.rb +26 -0
- data/spec/install/gemspec_spec.rb +108 -0
- data/spec/install/git_spec.rb +571 -0
- data/spec/install/invalid_spec.rb +17 -0
- data/spec/install/path_spec.rb +353 -0
- data/spec/install/upgrade_spec.rb +26 -0
- data/spec/lock/git_spec.rb +35 -0
- data/spec/lock/lockfile_spec.rb +683 -0
- data/spec/other/check_spec.rb +221 -0
- data/spec/other/clean_spec.rb +202 -0
- data/spec/other/config_spec.rb +40 -0
- data/spec/other/console_spec.rb +54 -0
- data/spec/other/exec_spec.rb +241 -0
- data/spec/other/ext_spec.rb +16 -0
- data/spec/other/gem_helper_spec.rb +128 -0
- data/spec/other/help_spec.rb +38 -0
- data/spec/other/init_spec.rb +40 -0
- data/spec/other/newgem_spec.rb +24 -0
- data/spec/other/open_spec.rb +35 -0
- data/spec/other/show_spec.rb +82 -0
- data/spec/pack/gems_spec.rb +54 -0
- data/spec/quality_spec.rb +58 -0
- data/spec/resolver/basic_spec.rb +20 -0
- data/spec/resolver/platform_spec.rb +82 -0
- data/spec/runtime/executable_spec.rb +110 -0
- data/spec/runtime/load_spec.rb +107 -0
- data/spec/runtime/platform_spec.rb +90 -0
- data/spec/runtime/require_spec.rb +231 -0
- data/spec/runtime/setup_spec.rb +688 -0
- data/spec/runtime/with_clean_env_spec.rb +15 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/support/artifice/endpoint.rb +50 -0
- data/spec/support/artifice/endpoint_fallback.rb +22 -0
- data/spec/support/artifice/endpoint_marshal_fail.rb +11 -0
- data/spec/support/artifice/endpoint_redirect.rb +11 -0
- data/spec/support/builders.rb +574 -0
- data/spec/support/fakeweb/rack-1.0.0.marshal +2 -0
- data/spec/support/fakeweb/windows.rb +23 -0
- data/spec/support/helpers.rb +246 -0
- data/spec/support/indexes.rb +112 -0
- data/spec/support/matchers.rb +89 -0
- data/spec/support/path.rb +73 -0
- data/spec/support/platforms.rb +53 -0
- data/spec/support/ruby_ext.rb +20 -0
- data/spec/support/rubygems_ext.rb +35 -0
- data/spec/support/rubygems_hax/platform.rb +11 -0
- data/spec/support/sudo.rb +21 -0
- data/spec/update/gems_spec.rb +121 -0
- data/spec/update/git_spec.rb +196 -0
- data/spec/update/source_spec.rb +51 -0
- metadata +294 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'bundler/shared_helpers'
|
|
2
|
+
|
|
3
|
+
if Bundler::SharedHelpers.in_bundle?
|
|
4
|
+
require 'bundler'
|
|
5
|
+
begin
|
|
6
|
+
Bundler.setup
|
|
7
|
+
rescue Bundler::BundlerError => e
|
|
8
|
+
puts "\e[31m#{e.message}\e[0m"
|
|
9
|
+
puts e.backtrace.join("\n") if ENV["DEBUG"]
|
|
10
|
+
exit e.status_code
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Add bundler to the load path after disabling system gems
|
|
14
|
+
bundler_lib = File.expand_path("../..", __FILE__)
|
|
15
|
+
$LOAD_PATH.unshift(bundler_lib) unless $LOAD_PATH.include?(bundler_lib)
|
|
16
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
Gem.source_index # ensure Rubygems is fully loaded in Ruby 1.9
|
|
4
|
+
|
|
5
|
+
module Gem
|
|
6
|
+
class Dependency
|
|
7
|
+
if !instance_methods.map { |m| m.to_s }.include?("requirement")
|
|
8
|
+
def requirement
|
|
9
|
+
version_requirements
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module Bundler
|
|
16
|
+
module SharedHelpers
|
|
17
|
+
attr_accessor :gem_loaded
|
|
18
|
+
|
|
19
|
+
def default_gemfile
|
|
20
|
+
gemfile = find_gemfile
|
|
21
|
+
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
|
|
22
|
+
Pathname.new(gemfile)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_lockfile
|
|
26
|
+
Pathname.new("#{default_gemfile}.lock")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def in_bundle?
|
|
30
|
+
find_gemfile
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def find_gemfile
|
|
36
|
+
given = ENV['BUNDLE_GEMFILE']
|
|
37
|
+
return given if given && !given.empty?
|
|
38
|
+
|
|
39
|
+
previous = nil
|
|
40
|
+
current = File.expand_path(Dir.pwd)
|
|
41
|
+
|
|
42
|
+
until !File.directory?(current) || current == previous
|
|
43
|
+
if ENV['BUNDLE_SPEC_RUN']
|
|
44
|
+
# avoid stepping above the tmp directory when testing
|
|
45
|
+
return nil if File.file?(File.join(current, 'bundler.gemspec'))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# otherwise return the Gemfile if it's there
|
|
49
|
+
filename = File.join(current, 'Gemfile')
|
|
50
|
+
return filename if File.file?(filename)
|
|
51
|
+
current, previous = File.expand_path("..", current), current
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def clean_load_path
|
|
56
|
+
# handle 1.9 where system gems are always on the load path
|
|
57
|
+
if defined?(::Gem)
|
|
58
|
+
me = File.expand_path("../../", __FILE__)
|
|
59
|
+
$LOAD_PATH.reject! do |p|
|
|
60
|
+
next if File.expand_path(p) =~ /^#{me}/
|
|
61
|
+
p != File.dirname(__FILE__) &&
|
|
62
|
+
Gem.path.any?{|gp| p =~ /^#{gp}/ }
|
|
63
|
+
end
|
|
64
|
+
$LOAD_PATH.uniq!
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def reverse_rubygems_kernel_mixin
|
|
69
|
+
# Disable rubygems' gem activation system
|
|
70
|
+
::Kernel.class_eval do
|
|
71
|
+
if private_method_defined?(:gem_original_require)
|
|
72
|
+
alias rubygems_require require
|
|
73
|
+
alias require gem_original_require
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
undef gem
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def cripple_rubygems(specs)
|
|
81
|
+
reverse_rubygems_kernel_mixin
|
|
82
|
+
|
|
83
|
+
executables = specs.map { |s| s.executables }.flatten
|
|
84
|
+
Gem.source_index # ensure RubyGems is fully loaded
|
|
85
|
+
|
|
86
|
+
::Kernel.send(:define_method, :gem) do |dep, *reqs|
|
|
87
|
+
if executables.include? File.basename(caller.first.split(':').first)
|
|
88
|
+
return
|
|
89
|
+
end
|
|
90
|
+
opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
|
|
91
|
+
|
|
92
|
+
unless dep.respond_to?(:name) && dep.respond_to?(:requirement)
|
|
93
|
+
dep = Gem::Dependency.new(dep, reqs)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
spec = specs.find { |s| s.name == dep.name }
|
|
97
|
+
|
|
98
|
+
if spec.nil?
|
|
99
|
+
|
|
100
|
+
e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile."
|
|
101
|
+
e.name = dep.name
|
|
102
|
+
if e.respond_to?(:requirement=)
|
|
103
|
+
e.requirement = dep.requirement
|
|
104
|
+
else
|
|
105
|
+
e.version_requirement = dep.requirement
|
|
106
|
+
end
|
|
107
|
+
raise e
|
|
108
|
+
elsif dep !~ spec
|
|
109
|
+
e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
|
|
110
|
+
"Make sure all dependencies are added to Gemfile."
|
|
111
|
+
e.name = dep.name
|
|
112
|
+
if e.respond_to?(:requirement=)
|
|
113
|
+
e.requirement = dep.requirement
|
|
114
|
+
else
|
|
115
|
+
e.version_requirement = dep.requirement
|
|
116
|
+
end
|
|
117
|
+
raise e
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
true
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# === Following hacks are to improve on the generated bin wrappers ===
|
|
124
|
+
|
|
125
|
+
# Yeah, talk about a hack
|
|
126
|
+
source_index_class = (class << Gem::SourceIndex ; self ; end)
|
|
127
|
+
source_index_class.send(:remove_method, :from_gems_in)
|
|
128
|
+
source_index_class.send(:define_method, :from_gems_in) do |*args|
|
|
129
|
+
source_index = Gem::SourceIndex.new
|
|
130
|
+
source_index.spec_dirs = *args
|
|
131
|
+
source_index.add_specs(*specs)
|
|
132
|
+
source_index
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# OMG more hacks
|
|
136
|
+
gem_class = (class << Gem ; self ; end)
|
|
137
|
+
gem_class.send(:remove_method, :refresh)
|
|
138
|
+
gem_class.send(:define_method, :refresh) { }
|
|
139
|
+
gem_class.send(:remove_method, :bin_path)
|
|
140
|
+
gem_class.send(:define_method, :bin_path) do |name, *args|
|
|
141
|
+
exec_name, *reqs = args
|
|
142
|
+
|
|
143
|
+
if exec_name == 'bundle'
|
|
144
|
+
return ENV['BUNDLE_BIN_PATH']
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
spec = nil
|
|
148
|
+
|
|
149
|
+
if exec_name
|
|
150
|
+
spec = specs.find { |s| s.executables.include?(exec_name) }
|
|
151
|
+
spec or raise Gem::Exception, "can't find executable #{exec_name}"
|
|
152
|
+
else
|
|
153
|
+
spec = specs.find { |s| s.name == name }
|
|
154
|
+
exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
|
|
158
|
+
gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
|
|
159
|
+
File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
Gem.clear_paths
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
extend self
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,675 @@
|
|
|
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 "open3"
|
|
8
|
+
|
|
9
|
+
module Bundler
|
|
10
|
+
module Source
|
|
11
|
+
# TODO: Refactor this class
|
|
12
|
+
class Rubygems
|
|
13
|
+
attr_reader :remotes
|
|
14
|
+
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
@options = options
|
|
17
|
+
@remotes = (options["remotes"] || []).map { |r| normalize_uri(r) }
|
|
18
|
+
@fetchers = {}
|
|
19
|
+
@allow_remote = false
|
|
20
|
+
@allow_cached = false
|
|
21
|
+
|
|
22
|
+
@caches = [ Bundler.app_cache ] + Gem.path.map{ |p| File.expand_path("#{p}/cache") }
|
|
23
|
+
@spec_fetch_map = {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def remote!
|
|
27
|
+
@allow_remote = true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def cached!
|
|
31
|
+
@allow_cached = true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def hash
|
|
35
|
+
Rubygems.hash
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def eql?(o)
|
|
39
|
+
Rubygems === o
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
alias == eql?
|
|
43
|
+
|
|
44
|
+
def options
|
|
45
|
+
{ "remotes" => @remotes.map { |r| r.to_s } }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.from_lock(options)
|
|
49
|
+
s = new(options)
|
|
50
|
+
Array(options["remote"]).each { |r| s.add_remote(r) }
|
|
51
|
+
s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_lock
|
|
55
|
+
out = "GEM\n"
|
|
56
|
+
out << remotes.map {|r| " remote: #{r}\n" }.join
|
|
57
|
+
out << " specs:\n"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_s
|
|
61
|
+
remote_names = self.remotes.map { |r| r.to_s }.join(', ')
|
|
62
|
+
"rubygems repository #{remote_names}"
|
|
63
|
+
end
|
|
64
|
+
alias_method :name, :to_s
|
|
65
|
+
|
|
66
|
+
def specs(dependencies = nil)
|
|
67
|
+
@specs ||= fetch_specs(dependencies)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fetch(spec)
|
|
71
|
+
spec, uri = @spec_fetch_map[spec.full_name]
|
|
72
|
+
if spec
|
|
73
|
+
path = download_gem_from_uri(spec, uri)
|
|
74
|
+
s = Gem::Format.from_file_by_path(path).spec
|
|
75
|
+
spec.__swap__(s)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def install(spec)
|
|
80
|
+
path = cached_gem(spec)
|
|
81
|
+
|
|
82
|
+
if installed_specs[spec].any?
|
|
83
|
+
Bundler.ui.info "Using #{spec.name} (#{spec.version}) "
|
|
84
|
+
return
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) "
|
|
88
|
+
|
|
89
|
+
install_path = Bundler.requires_sudo? ? Bundler.tmp : Gem.dir
|
|
90
|
+
options = { :install_dir => install_path,
|
|
91
|
+
:ignore_dependencies => true,
|
|
92
|
+
:wrappers => true,
|
|
93
|
+
:env_shebang => true }
|
|
94
|
+
options.merge!(:bin_dir => "#{install_path}/bin") unless spec.executables.nil? || spec.executables.empty?
|
|
95
|
+
|
|
96
|
+
installer = Gem::Installer.new path, options
|
|
97
|
+
installer.install
|
|
98
|
+
|
|
99
|
+
# SUDO HAX
|
|
100
|
+
if Bundler.requires_sudo?
|
|
101
|
+
sudo "mkdir -p #{Gem.dir}/gems #{Gem.dir}/specifications"
|
|
102
|
+
sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Gem.dir}/gems/"
|
|
103
|
+
sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Gem.dir}/specifications/"
|
|
104
|
+
spec.executables.each do |exe|
|
|
105
|
+
sudo "mkdir -p #{Gem.bindir}"
|
|
106
|
+
sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Gem.bindir}"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
spec.loaded_from = "#{Gem.dir}/specifications/#{spec.full_name}.gemspec"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def sudo(str)
|
|
114
|
+
Bundler.sudo(str)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def cache(spec)
|
|
118
|
+
cached_path = cached_gem(spec)
|
|
119
|
+
raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
|
|
120
|
+
return if File.dirname(cached_path) == Bundler.app_cache.to_s
|
|
121
|
+
Bundler.ui.info " * #{File.basename(cached_path)}"
|
|
122
|
+
FileUtils.cp(cached_path, Bundler.app_cache)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def add_remote(source)
|
|
126
|
+
@remotes << normalize_uri(source)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def merge_remotes(source)
|
|
130
|
+
@remotes = []
|
|
131
|
+
source.remotes.each do |r|
|
|
132
|
+
add_remote r.to_s
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def cached_gem(spec)
|
|
139
|
+
possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" }
|
|
140
|
+
possibilities.find { |p| File.exist?(p) }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def normalize_uri(uri)
|
|
144
|
+
uri = uri.to_s
|
|
145
|
+
uri = "#{uri}/" unless uri =~ %r'/$'
|
|
146
|
+
uri = URI(uri)
|
|
147
|
+
raise ArgumentError, "The source must be an absolute URI" unless uri.absolute?
|
|
148
|
+
uri
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def fetch_specs(dependencies = nil)
|
|
152
|
+
Index.build do |idx|
|
|
153
|
+
idx.use installed_specs
|
|
154
|
+
idx.use cached_specs if @allow_cached || @allow_remote
|
|
155
|
+
idx.use remote_specs(dependencies) if @allow_remote
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def installed_specs
|
|
160
|
+
@installed_specs ||= begin
|
|
161
|
+
idx = Index.new
|
|
162
|
+
have_bundler = false
|
|
163
|
+
Gem.source_index.to_a.reverse.each do |dont_use_this_var, spec|
|
|
164
|
+
next if spec.name == 'bundler' && spec.version.to_s != VERSION
|
|
165
|
+
have_bundler = true if spec.name == 'bundler'
|
|
166
|
+
spec.source = self
|
|
167
|
+
idx << spec
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Always have bundler locally
|
|
171
|
+
unless have_bundler
|
|
172
|
+
# We're running bundler directly from the source
|
|
173
|
+
# so, let's create a fake gemspec for it (it's a path)
|
|
174
|
+
# gemspec
|
|
175
|
+
bundler = Gem::Specification.new do |s|
|
|
176
|
+
s.name = 'bundler'
|
|
177
|
+
s.version = VERSION
|
|
178
|
+
s.platform = Gem::Platform::RUBY
|
|
179
|
+
s.source = self
|
|
180
|
+
s.loaded_from = File.expand_path("..", __FILE__)
|
|
181
|
+
end
|
|
182
|
+
idx << bundler
|
|
183
|
+
end
|
|
184
|
+
idx
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def cached_specs
|
|
189
|
+
@cached_specs ||= begin
|
|
190
|
+
idx = installed_specs.dup
|
|
191
|
+
|
|
192
|
+
path = Bundler.app_cache
|
|
193
|
+
Dir["#{path}/*.gem"].each do |gemfile|
|
|
194
|
+
next if gemfile =~ /bundler\-[\d\.]+?\.gem/
|
|
195
|
+
|
|
196
|
+
begin
|
|
197
|
+
s ||= Gem::Format.from_file_by_path(gemfile).spec
|
|
198
|
+
rescue Gem::Package::FormatError
|
|
199
|
+
raise GemspecError, "Could not read gem at #{gemfile}. It may be corrupted."
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
s.source = self
|
|
203
|
+
idx << s
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
idx
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def remote_specs(dependencies = nil)
|
|
211
|
+
@remote_specs ||= begin
|
|
212
|
+
idx = Index.new
|
|
213
|
+
old = Gem.sources
|
|
214
|
+
|
|
215
|
+
remotes.each do |uri|
|
|
216
|
+
Bundler.ui.info "Fetching source index for #{uri}"
|
|
217
|
+
|
|
218
|
+
@fetchers[uri] = Bundler::Fetcher.new(uri)
|
|
219
|
+
gem_names =
|
|
220
|
+
if dependencies
|
|
221
|
+
dependencies.map {|d| d.name }
|
|
222
|
+
end
|
|
223
|
+
@fetchers[uri].fetch_remote_specs(gem_names) do |n,v|
|
|
224
|
+
v.each do |name, version, platform|
|
|
225
|
+
next if name == 'bundler'
|
|
226
|
+
spec = RemoteSpecification.new(name, version, platform, @fetchers[uri])
|
|
227
|
+
spec.source = self
|
|
228
|
+
@spec_fetch_map[spec.full_name] = [spec, uri]
|
|
229
|
+
idx << spec
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
idx
|
|
234
|
+
ensure
|
|
235
|
+
Gem.sources = old
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def download_gem_from_uri(spec, uri)
|
|
240
|
+
spec.fetch_platform
|
|
241
|
+
|
|
242
|
+
download_path = Bundler.requires_sudo? ? Bundler.tmp : Gem.dir
|
|
243
|
+
gem_path = "#{Gem.dir}/cache/#{spec.full_name}.gem"
|
|
244
|
+
|
|
245
|
+
FileUtils.mkdir_p("#{download_path}/cache")
|
|
246
|
+
Gem::RemoteFetcher.fetcher.download(spec, uri, download_path)
|
|
247
|
+
|
|
248
|
+
if Bundler.requires_sudo?
|
|
249
|
+
sudo "mkdir -p #{Gem.dir}/cache"
|
|
250
|
+
sudo "mv #{Bundler.tmp}/cache/#{spec.full_name}.gem #{gem_path}"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
gem_path
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class Path
|
|
258
|
+
attr_reader :path, :options
|
|
259
|
+
# Kind of a hack, but needed for the lock file parser
|
|
260
|
+
attr_writer :name
|
|
261
|
+
attr_accessor :version
|
|
262
|
+
|
|
263
|
+
DEFAULT_GLOB = "{,*/}*.gemspec"
|
|
264
|
+
|
|
265
|
+
def initialize(options)
|
|
266
|
+
@options = options
|
|
267
|
+
@glob = options["glob"] || DEFAULT_GLOB
|
|
268
|
+
|
|
269
|
+
@allow_cached = false
|
|
270
|
+
@allow_remote = false
|
|
271
|
+
|
|
272
|
+
if options["path"]
|
|
273
|
+
@path = Pathname.new(options["path"])
|
|
274
|
+
@path = @path.expand_path(Bundler.root) unless @path.relative?
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
@name = options["name"]
|
|
278
|
+
@version = options["version"]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def remote!
|
|
282
|
+
@allow_remote = true
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def cached!
|
|
286
|
+
@allow_cached = true
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def self.from_lock(options)
|
|
290
|
+
new(options.merge("path" => options.delete("remote")))
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def to_lock
|
|
294
|
+
out = "PATH\n"
|
|
295
|
+
out << " remote: #{relative_path}\n"
|
|
296
|
+
out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
|
|
297
|
+
out << " specs:\n"
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def to_s
|
|
301
|
+
"source at #{@path}"
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def hash
|
|
305
|
+
self.class.hash
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def eql?(o)
|
|
309
|
+
o.instance_of?(Path) &&
|
|
310
|
+
path.expand_path(Bundler.root) == o.path.expand_path(Bundler.root) &&
|
|
311
|
+
name == o.name &&
|
|
312
|
+
version == o.version
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
alias == eql?
|
|
316
|
+
|
|
317
|
+
def name
|
|
318
|
+
File.basename(@path.to_s)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def load_spec_files
|
|
322
|
+
index = Index.new
|
|
323
|
+
|
|
324
|
+
expanded_path = path.expand_path(Bundler.root)
|
|
325
|
+
|
|
326
|
+
if File.directory?(expanded_path)
|
|
327
|
+
Dir["#{expanded_path}/#{@glob}"].each do |file|
|
|
328
|
+
spec = Bundler.load_gemspec(file)
|
|
329
|
+
if spec
|
|
330
|
+
spec.loaded_from = file.to_s
|
|
331
|
+
spec.source = self
|
|
332
|
+
index << spec
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
if index.empty? && @name && @version
|
|
337
|
+
index << Gem::Specification.new do |s|
|
|
338
|
+
s.name = @name
|
|
339
|
+
s.source = self
|
|
340
|
+
s.version = Gem::Version.new(@version)
|
|
341
|
+
s.platform = Gem::Platform::RUBY
|
|
342
|
+
s.summary = "Fake gemspec for #{@name}"
|
|
343
|
+
s.relative_loaded_from = "#{@name}.gemspec"
|
|
344
|
+
if expanded_path.join("bin").exist?
|
|
345
|
+
binaries = expanded_path.join("bin").children.map{|c| c.basename.to_s }
|
|
346
|
+
s.executables = binaries
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
else
|
|
351
|
+
raise PathError, "The path `#{expanded_path}` does not exist."
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
index
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def local_specs(*)
|
|
358
|
+
@local_specs ||= load_spec_files
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
class Installer < Gem::Installer
|
|
362
|
+
def initialize(spec, options = {})
|
|
363
|
+
@spec = spec
|
|
364
|
+
@bin_dir = Bundler.requires_sudo? ? "#{Bundler.tmp}/bin" : "#{Gem.dir}/bin"
|
|
365
|
+
@gem_dir = spec.full_gem_path
|
|
366
|
+
@wrappers = options[:wrappers] || true
|
|
367
|
+
@env_shebang = options[:env_shebang] || true
|
|
368
|
+
@format_executable = options[:format_executable] || false
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def generate_bin
|
|
372
|
+
return if spec.executables.nil? || spec.executables.empty?
|
|
373
|
+
|
|
374
|
+
if Bundler.requires_sudo?
|
|
375
|
+
FileUtils.mkdir_p("#{Bundler.tmp}/bin") unless File.exist?("#{Bundler.tmp}/bin")
|
|
376
|
+
end
|
|
377
|
+
super
|
|
378
|
+
if Bundler.requires_sudo?
|
|
379
|
+
Bundler.mkdir_p "#{Gem.dir}/bin"
|
|
380
|
+
spec.executables.each do |exe|
|
|
381
|
+
Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Gem.dir}/bin/"
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def install(spec)
|
|
388
|
+
Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
|
|
389
|
+
# Let's be honest, when we're working from a path, we can't
|
|
390
|
+
# really expect native extensions to work because the whole point
|
|
391
|
+
# is to just be able to modify what's in that path and go. So, let's
|
|
392
|
+
# not put ourselves through the pain of actually trying to generate
|
|
393
|
+
# the full gem.
|
|
394
|
+
Installer.new(spec).generate_bin
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
alias specs local_specs
|
|
398
|
+
|
|
399
|
+
def cache(spec)
|
|
400
|
+
unless path.expand_path(Bundler.root).to_s.index(Bundler.root.to_s) == 0
|
|
401
|
+
Bundler.ui.warn " * #{spec.name} at `#{path}` will not be cached."
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
private
|
|
406
|
+
|
|
407
|
+
def relative_path
|
|
408
|
+
if path.to_s.include?(Bundler.root.to_s)
|
|
409
|
+
return path.relative_path_from(Bundler.root)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
path
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def generate_bin(spec)
|
|
416
|
+
gem_dir = Pathname.new(spec.full_gem_path)
|
|
417
|
+
|
|
418
|
+
# Some gem authors put absolute paths in their gemspec
|
|
419
|
+
# and we have to save them from themselves
|
|
420
|
+
spec.files = spec.files.map do |p|
|
|
421
|
+
next if File.directory?(p)
|
|
422
|
+
begin
|
|
423
|
+
Pathname.new(p).relative_path_from(gem_dir).to_s
|
|
424
|
+
rescue ArgumentError
|
|
425
|
+
p
|
|
426
|
+
end
|
|
427
|
+
end.compact
|
|
428
|
+
|
|
429
|
+
gem_file = Dir.chdir(gem_dir){ Gem::Builder.new(spec).build }
|
|
430
|
+
|
|
431
|
+
installer = Installer.new(spec, :env_shebang => false)
|
|
432
|
+
installer.build_extensions
|
|
433
|
+
installer.generate_bin
|
|
434
|
+
rescue Gem::InvalidSpecificationException => e
|
|
435
|
+
Bundler.ui.warn "\n#{spec.name} at #{spec.full_gem_path} did not have a valid gemspec.\n" \
|
|
436
|
+
"This prevents bundler from installing bins or native extensions, but " \
|
|
437
|
+
"that may not affect its functionality."
|
|
438
|
+
|
|
439
|
+
if !spec.extensions.empty? && !spec.email.empty?
|
|
440
|
+
Bundler.ui.warn "If you need to use this package without installing it from a gem " \
|
|
441
|
+
"repository, please contact #{spec.email} and ask them " \
|
|
442
|
+
"to modify their .gemspec so it can work with `gem build`."
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
Bundler.ui.warn "The validation message from Rubygems was:\n #{e.message}"
|
|
446
|
+
ensure
|
|
447
|
+
Dir.chdir(gem_dir){ FileUtils.rm_rf(gem_file) if gem_file && File.exist?(gem_file) }
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
class Git < Path
|
|
453
|
+
attr_reader :uri, :ref, :options, :submodules
|
|
454
|
+
|
|
455
|
+
def initialize(options)
|
|
456
|
+
super
|
|
457
|
+
|
|
458
|
+
# stringify options that could be set as symbols
|
|
459
|
+
%w(ref branch tag revision).each{|k| options[k] = options[k].to_s if options[k] }
|
|
460
|
+
|
|
461
|
+
@uri = options["uri"]
|
|
462
|
+
@ref = options["ref"] || options["branch"] || options["tag"] || 'master'
|
|
463
|
+
@revision = options["revision"]
|
|
464
|
+
@submodules = options["submodules"]
|
|
465
|
+
@update = false
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def self.from_lock(options)
|
|
469
|
+
new(options.merge("uri" => options.delete("remote")))
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def cache(spec)
|
|
473
|
+
raise GemNotFound, "Missing git repository for '#{spec.full_name}': '#{cache_path}'." unless cache_path
|
|
474
|
+
return if File.directory?(File.join(Bundler.app_cache, "#{base_name}-#{uri_hash}"))
|
|
475
|
+
Bundler.ui.info " * #{spec.full_name} revision #{revision}"
|
|
476
|
+
FileUtils.cp_r cache_path, Bundler.app_cache
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def to_lock
|
|
480
|
+
out = "GIT\n"
|
|
481
|
+
out << " remote: #{@uri}\n"
|
|
482
|
+
out << " revision: #{revision}\n"
|
|
483
|
+
%w(ref branch tag submodules).each do |opt|
|
|
484
|
+
out << " #{opt}: #{options[opt]}\n" if options[opt]
|
|
485
|
+
end
|
|
486
|
+
out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
|
|
487
|
+
out << " specs:\n"
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
def eql?(o)
|
|
491
|
+
Git === o &&
|
|
492
|
+
uri == o.uri &&
|
|
493
|
+
ref == o.ref &&
|
|
494
|
+
name == o.name &&
|
|
495
|
+
version == o.version &&
|
|
496
|
+
submodules == o.submodules
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
alias == eql?
|
|
500
|
+
|
|
501
|
+
def to_s
|
|
502
|
+
sref = options["ref"] ? shortref_for_display(options["ref"]) : ref
|
|
503
|
+
"#{uri} (at #{sref})"
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def name
|
|
507
|
+
File.basename(@uri, '.git')
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def path
|
|
511
|
+
@install_path ||= begin
|
|
512
|
+
git_scope = "#{base_name}-#{shortref_for_path(revision)}"
|
|
513
|
+
|
|
514
|
+
if Bundler.requires_sudo?
|
|
515
|
+
Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
|
|
516
|
+
else
|
|
517
|
+
Bundler.install_path.join(git_scope)
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def unlock!
|
|
523
|
+
@revision = nil
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# TODO: actually cache git specs
|
|
527
|
+
def specs(*)
|
|
528
|
+
if allow_git_ops? && !@update
|
|
529
|
+
# Start by making sure the git cache is up to date
|
|
530
|
+
repository_cache
|
|
531
|
+
checkout
|
|
532
|
+
@update = true
|
|
533
|
+
end
|
|
534
|
+
local_specs
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def install(spec)
|
|
538
|
+
Bundler.ui.info "Using #{spec.name} (#{spec.version}) from #{to_s} "
|
|
539
|
+
|
|
540
|
+
unless @installed
|
|
541
|
+
Bundler.ui.debug " * Checking out revision: #{ref}"
|
|
542
|
+
checkout if allow_git_ops?
|
|
543
|
+
@installed = true
|
|
544
|
+
end
|
|
545
|
+
generate_bin(spec)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def load_spec_files
|
|
549
|
+
super
|
|
550
|
+
rescue PathError, GitError
|
|
551
|
+
raise GitError, "#{to_s} is not checked out. Please run `bundle install`"
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
private
|
|
555
|
+
|
|
556
|
+
def git(command)
|
|
557
|
+
if allow_git_ops?
|
|
558
|
+
out = %x{git #{command}}
|
|
559
|
+
|
|
560
|
+
if $?.exitstatus != 0
|
|
561
|
+
raise GitError, "An error has occurred in git when running `git #{command}`. Cannot complete bundling."
|
|
562
|
+
end
|
|
563
|
+
out
|
|
564
|
+
else
|
|
565
|
+
raise GitError, "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " \
|
|
566
|
+
"this error message could probably be more useful. Please submit a ticket at http://github.com/carlhuda/bundler/issues " \
|
|
567
|
+
"with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
def base_name
|
|
572
|
+
File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)},''), ".git")
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def shortref_for_display(ref)
|
|
576
|
+
ref[0..6]
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def shortref_for_path(ref)
|
|
580
|
+
ref[0..11]
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
def uri_hash
|
|
584
|
+
if uri.to_s =~ %r{^\w+://(\w+@)?}
|
|
585
|
+
# Downcase the domain component of the URI
|
|
586
|
+
# and strip off a trailing slash, if one is present
|
|
587
|
+
input = URI.parse(uri).normalize.to_s.sub(%r{/$},'')
|
|
588
|
+
else
|
|
589
|
+
# If there is no URI scheme, assume it is an ssh/git URI
|
|
590
|
+
input = uri.to_s
|
|
591
|
+
end
|
|
592
|
+
Digest::SHA1.hexdigest(input)
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def cache_path_scope
|
|
596
|
+
"#{base_name}-#{uri_hash}"
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def cache_path
|
|
600
|
+
@cache_path ||= begin
|
|
601
|
+
git_scope = cache_path_scope
|
|
602
|
+
|
|
603
|
+
if Bundler.requires_sudo?
|
|
604
|
+
Bundler.user_bundle_path.join("cache/git", git_scope)
|
|
605
|
+
else
|
|
606
|
+
Bundler.cache.join("git", git_scope)
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
def repository_cache
|
|
612
|
+
if cached?
|
|
613
|
+
return if has_revision_cached?
|
|
614
|
+
Bundler.ui.info "Updating #{uri}"
|
|
615
|
+
in_cache do
|
|
616
|
+
git %|fetch --force --quiet --tags "#{uri}" refs/heads/*:refs/heads/*|
|
|
617
|
+
end
|
|
618
|
+
else
|
|
619
|
+
Bundler.ui.info "Fetching #{uri}"
|
|
620
|
+
FileUtils.mkdir_p(cache_path.dirname)
|
|
621
|
+
git %|clone "#{uri}" "#{cache_path}" --bare --no-hardlinks|
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
def checkout
|
|
626
|
+
unless File.exist?(path.join(".git"))
|
|
627
|
+
FileUtils.mkdir_p(path.dirname)
|
|
628
|
+
FileUtils.rm_rf(path)
|
|
629
|
+
git %|clone --no-checkout "#{cache_path}" "#{path}"|
|
|
630
|
+
end
|
|
631
|
+
Dir.chdir(path) do
|
|
632
|
+
git %|fetch --force --quiet --tags "#{cache_path}"|
|
|
633
|
+
git "reset --hard #{revision}"
|
|
634
|
+
|
|
635
|
+
if @submodules
|
|
636
|
+
git "submodule init"
|
|
637
|
+
git "submodule update"
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
def has_revision_cached?
|
|
643
|
+
return unless @revision
|
|
644
|
+
in_cache { git %|cat-file -e #{@revision}| }
|
|
645
|
+
true
|
|
646
|
+
rescue GitError
|
|
647
|
+
false
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def allow_git_ops?
|
|
651
|
+
@allow_remote || @allow_cached
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
def revision
|
|
655
|
+
@revision ||= begin
|
|
656
|
+
if allow_git_ops?
|
|
657
|
+
in_cache { git("rev-parse #{ref}").strip }
|
|
658
|
+
else
|
|
659
|
+
raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
def cached?
|
|
665
|
+
cache_path.exist?
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
def in_cache(&blk)
|
|
669
|
+
cache unless cached?
|
|
670
|
+
Dir.chdir(cache_path, &blk)
|
|
671
|
+
end
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
end
|
|
675
|
+
end
|