bundler08 0.8.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.
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), "runtime", "dsl")
2
+ require File.join(File.dirname(__FILE__), "runtime", "dependency")
@@ -0,0 +1,365 @@
1
+ module Bundler
2
+ class DirectorySourceError < StandardError; end
3
+ class GitSourceError < StandardError ; end
4
+ # Represents a source of rubygems. Initially, this is only gem repositories, but
5
+ # eventually, this will be git, svn, HTTP
6
+ class Source
7
+ attr_reader :bundle
8
+
9
+ def initialize(bundle, options)
10
+ @bundle = bundle
11
+ end
12
+
13
+ private
14
+
15
+ def process_source_gems(gems)
16
+ new_gems = Hash.new { |h,k| h[k] = [] }
17
+ gems.values.each do |spec|
18
+ spec.source = self
19
+ new_gems[spec.name] << spec
20
+ end
21
+ new_gems
22
+ end
23
+ end
24
+
25
+ class GemSource < Source
26
+ attr_reader :uri
27
+
28
+ def initialize(bundle, options)
29
+ super
30
+ @uri = options[:uri]
31
+ @uri = URI.parse(@uri) unless @uri.is_a?(URI)
32
+ raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute?
33
+ end
34
+
35
+ def local?
36
+ false
37
+ end
38
+
39
+ def gems
40
+ @specs ||= fetch_specs
41
+ end
42
+
43
+ def ==(other)
44
+ uri == other.uri
45
+ end
46
+
47
+ def to_s
48
+ @uri.to_s
49
+ end
50
+
51
+ class RubygemsRetardation < StandardError; end
52
+
53
+ def download(spec)
54
+ Bundler.logger.info "Downloading #{spec.full_name}.gem"
55
+
56
+ destination = bundle.gem_path
57
+
58
+ unless destination.writable?
59
+ raise RubygemsRetardation, "destination: #{destination} is not writable"
60
+ end
61
+
62
+ # Download the gem
63
+ Gem::RemoteFetcher.fetcher.download(spec, uri, destination)
64
+
65
+ # Re-read the gemspec from the downloaded gem to correct
66
+ # any errors that were present in the Rubyforge specification.
67
+ new_spec = Gem::Format.from_file_by_path(destination.join('cache', "#{spec.full_name}.gem")).spec
68
+ spec.__swap__(new_spec)
69
+ end
70
+
71
+ private
72
+
73
+ def fetch_specs
74
+ Bundler.logger.info "Updating source: #{to_s}"
75
+ build_gem_index(fetch_main_specs + fetch_prerelease_specs)
76
+ end
77
+
78
+ def build_gem_index(index)
79
+ gems = Hash.new { |h,k| h[k] = [] }
80
+ index.each do |name, version, platform|
81
+ spec = RemoteSpecification.new(name, version, platform, @uri)
82
+ spec.source = self
83
+ gems[spec.name] << spec if Gem::Platform.match(spec.platform)
84
+ end
85
+ gems
86
+ end
87
+
88
+ def fetch_main_specs
89
+ Marshal.load(Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/specs.4.8.gz"))
90
+ rescue Gem::RemoteFetcher::FetchError => e
91
+ raise ArgumentError, "#{to_s} is not a valid source: #{e.message}"
92
+ end
93
+
94
+ def fetch_prerelease_specs
95
+ Marshal.load(Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/prerelease_specs.4.8.gz"))
96
+ rescue Gem::RemoteFetcher::FetchError
97
+ Bundler.logger.warn "Source '#{uri}' does not support prerelease gems"
98
+ []
99
+ end
100
+ end
101
+
102
+ class SystemGemSource < Source
103
+
104
+ def self.instance
105
+ @instance
106
+ end
107
+
108
+ def self.new(*args)
109
+ @instance ||= super
110
+ end
111
+
112
+ def initialize(bundle, options = {})
113
+ super
114
+ @source = Gem::SourceIndex.from_installed_gems
115
+ end
116
+
117
+ def local?
118
+ false
119
+ end
120
+
121
+ def gems
122
+ @gems ||= process_source_gems(@source.gems)
123
+ end
124
+
125
+ def ==(other)
126
+ other.is_a?(SystemGemSource)
127
+ end
128
+
129
+ def to_s
130
+ "system"
131
+ end
132
+
133
+ def download(spec)
134
+ gemfile = Pathname.new(spec.loaded_from)
135
+ gemfile = gemfile.dirname.join('..', 'cache', "#{spec.full_name}.gem")
136
+ bundle.cache(gemfile)
137
+ end
138
+
139
+ private
140
+
141
+ end
142
+
143
+ class GemDirectorySource < Source
144
+ attr_reader :location
145
+
146
+ def initialize(bundle, options)
147
+ super
148
+ @location = options[:location]
149
+ end
150
+
151
+ def local?
152
+ true
153
+ end
154
+
155
+ def gems
156
+ @specs ||= fetch_specs
157
+ end
158
+
159
+ def ==(other)
160
+ location == other.location
161
+ end
162
+
163
+ def to_s
164
+ location.to_s
165
+ end
166
+
167
+ def download(spec)
168
+ # raise NotImplementedError
169
+ end
170
+
171
+ private
172
+
173
+ def fetch_specs
174
+ specs = Hash.new { |h,k| h[k] = [] }
175
+
176
+ Dir["#{@location}/*.gem"].each do |gemfile|
177
+ spec = Gem::Format.from_file_by_path(gemfile).spec
178
+ spec.source = self
179
+ specs[spec.name] << spec
180
+ end
181
+
182
+ specs
183
+ end
184
+ end
185
+
186
+ class DirectorySource < Source
187
+ attr_reader :location, :specs, :required_specs
188
+
189
+ def initialize(bundle, options)
190
+ super
191
+ if options[:location]
192
+ @location = Pathname.new(options[:location]).expand_path
193
+ end
194
+ @glob = options[:glob] || "**/*.gemspec"
195
+ @specs = {}
196
+ @required_specs = []
197
+ end
198
+
199
+ def add_spec(path, name, version, require_paths = %w(lib))
200
+ raise DirectorySourceError, "already have a gem defined for '#{path}'" if @specs[path.to_s]
201
+ @specs[path.to_s] = Gem::Specification.new do |s|
202
+ s.name = name
203
+ s.version = Gem::Version.new(version)
204
+ end
205
+ end
206
+
207
+ def local?
208
+ true
209
+ end
210
+
211
+ def gems
212
+ @gems ||= begin
213
+ # Locate all gemspecs from the directory
214
+ specs = locate_gemspecs
215
+ specs = merge_defined_specs(specs)
216
+
217
+ required_specs.each do |required|
218
+ unless specs.any? {|k,v| v.name == required }
219
+ raise DirectorySourceError, "No gemspec for '#{required}' was found in" \
220
+ " '#{location}'. Please explicitly specify a version."
221
+ end
222
+ end
223
+
224
+ process_source_gems(specs)
225
+ end
226
+ end
227
+
228
+ def locate_gemspecs
229
+ Dir["#{location}/#{@glob}"].inject({}) do |specs, file|
230
+ file = Pathname.new(file)
231
+ if spec = eval(File.read(file)) # and validate_gemspec(file.dirname, spec)
232
+ spec.location = file.dirname.expand_path
233
+ specs[spec.full_name] = spec
234
+ end
235
+ specs
236
+ end
237
+ end
238
+
239
+ def merge_defined_specs(specs)
240
+ @specs.each do |path, spec|
241
+ # Set the spec location
242
+ spec.location = "#{location}/#{path}"
243
+
244
+ if existing = specs.values.find { |s| s.name == spec.name }
245
+ if existing.version != spec.version
246
+ raise DirectorySourceError, "The version you specified for #{spec.name}" \
247
+ " is #{spec.version}. The gemspec is #{existing.version}."
248
+ # Not sure if this is needed
249
+ # ====
250
+ # elsif File.expand_path(existing.location) != File.expand_path(spec.location)
251
+ # raise DirectorySourceError, "The location you specified for #{spec.name}" \
252
+ # " is '#{spec.location}'. The gemspec was found at '#{existing.location}'."
253
+ end
254
+ # elsif !validate_gemspec(spec.location, spec)
255
+ # raise "Your gem definition is not valid: #{spec}"
256
+ else
257
+ specs[spec.full_name] = spec
258
+ end
259
+ end
260
+ specs
261
+ end
262
+
263
+ def validate_gemspec(path, spec)
264
+ path = Pathname.new(path)
265
+ msg = "Gemspec for #{spec.name} (#{spec.version}) is invalid:"
266
+ # Check the require_paths
267
+ (spec.require_paths || []).each do |require_path|
268
+ unless path.join(require_path).directory?
269
+ Bundler.logger.warn "#{msg} Missing require path: '#{require_path}'"
270
+ return false
271
+ end
272
+ end
273
+
274
+ # Check the executables
275
+ (spec.executables || []).each do |exec|
276
+ unless path.join(spec.bindir, exec).file?
277
+ Bundler.logger.warn "#{msg} Missing executable: '#{File.join(spec.bindir, exec)}'"
278
+ return false
279
+ end
280
+ end
281
+
282
+ true
283
+ end
284
+
285
+ def ==(other)
286
+ # TMP HAX
287
+ other.is_a?(DirectorySource)
288
+ end
289
+
290
+ def to_s
291
+ "directory: '#{location}'"
292
+ end
293
+
294
+ def download(spec)
295
+ # Nothing needed here
296
+ end
297
+ end
298
+
299
+ class GitSource < DirectorySource
300
+ attr_reader :ref, :uri, :branch
301
+
302
+ def initialize(bundle, options)
303
+ super
304
+ @uri = options[:uri]
305
+ @branch = options[:branch] || 'master'
306
+ @ref = options[:ref] || "origin/#{@branch}"
307
+ end
308
+
309
+ def local?
310
+ raise SourceNotCached, "Git repository '#{@uri}' has not been cloned yet" unless location.directory?
311
+ super
312
+ end
313
+
314
+ def location
315
+ # TMP HAX to get the *.gemspec reading to work
316
+ bundle.gem_path.join('dirs', File.basename(@uri, '.git'))
317
+ end
318
+
319
+ def gems
320
+ update if Bundler.remote?
321
+ checkout if Bundler.writable?
322
+ super
323
+ end
324
+
325
+ def download(spec)
326
+ # Nothing needed here
327
+ end
328
+
329
+ def to_s
330
+ "git: #{uri}"
331
+ end
332
+
333
+ private
334
+ def update
335
+ if location.directory?
336
+ fetch if current_revision != revision_for_ref
337
+ else
338
+ clone
339
+ end
340
+ end
341
+
342
+ def fetch
343
+ Bundler.logger.info "Fetching git repository at: #{@uri}"
344
+ Dir.chdir(location) { `git fetch origin` }
345
+ end
346
+
347
+ def clone
348
+ Bundler.logger.info "Cloning git repository at: #{@uri}"
349
+ FileUtils.mkdir_p(location.dirname)
350
+ `git clone #{@uri} #{location} --no-hardlinks`
351
+ end
352
+
353
+ def current_revision
354
+ Dir.chdir(location) { `git rev-parse HEAD`.strip }
355
+ end
356
+
357
+ def revision_for_ref
358
+ Dir.chdir(location) { `git rev-parse #{@ref}`.strip }
359
+ end
360
+
361
+ def checkout
362
+ Dir.chdir(location) { `git checkout --quiet #{@ref}` }
363
+ end
364
+ end
365
+ end
@@ -0,0 +1,72 @@
1
+ # Specify a dependency on rails. When the bundler downloads gems,
2
+ # it will download rails as well as all of rails' dependencies (such as
3
+ # activerecord, actionpack, etc...)
4
+ #
5
+ # At least one dependency must be specified
6
+ #gem "rails"
7
+
8
+ # Specify a dependency on rack v.1.0.0. The version is optional. If present,
9
+ # it can be specified the same way as with rubygems' #gem method.
10
+ #gem "rack", "1.0.0"
11
+
12
+ # Specify a dependency rspec, but only require that gem in the "testing"
13
+ # environment. :except is also a valid option to specify environment
14
+ # restrictions.
15
+ #gem "rspec", :only => :testing
16
+
17
+ # Specify a dependency, but specify that it is already present and expanded
18
+ # at vendor/rspec. Bundler will treat rspec as though it was the rspec gem
19
+ # for the purpose of gem resolution: if another gem depends on a version
20
+ # of rspec satisfied by "1.1.6", it will be used.
21
+ #
22
+ # If a gemspec is found in the directory, it will be used to specify load
23
+ # paths and supply additional dependencies.
24
+ #
25
+ # Bundler will also recursively search for *.gemspec, and assume that
26
+ # gemspecs it finds represent gems that are rooted in the same directory
27
+ # the gemspec is found in.
28
+ #gem "rspec", "1.1.6", :vendored_at => "vendor/rspec"
29
+
30
+ # You can also control what will happen when you run Bundler.require_env
31
+ # by using the :require_as option, as per the next two examples.
32
+
33
+ # Don't auto-require this gem.
34
+ #gem "rspec-rails", "1.2.9", :require_as => nil
35
+
36
+ # Require something other than the default.
37
+ #gem "yajl-ruby", "0.6.7", :require_as => "yajl/json_gem"
38
+
39
+ # Works exactly like :vendored_at, but first downloads the repo from
40
+ # git and handles stashing the files for you. As with :vendored_at,
41
+ # Bundler will automatically use *.gemspec files in the root or anywhere
42
+ # in the repository.
43
+ #gem "rails", "3.0.pre", :git => "git://github.com/rails/rails.git"
44
+
45
+ # Add http://gems.github.com as a source that the bundler will use
46
+ # to find gems listed in the manifest. By default,
47
+ # http://gems.rubyforge.org is already added to the list.
48
+ #
49
+ # This is an optional setting.
50
+ #source "http://gems.github.com"
51
+
52
+ # Specify where the bundled gems should be stashed. This directory will
53
+ # be a gem repository where all gems are downloaded to and installed to.
54
+ #
55
+ # This is an optional setting.
56
+ # The default is: vendor/gems
57
+ #bundle_path "my/bundled/gems"
58
+
59
+ # Specify where gem executables should be copied to.
60
+ #
61
+ # This is an optional setting.
62
+ # The default is: bin
63
+ #bin_path "my/executables"
64
+
65
+ # Specify that rubygems should be completely disabled. This means that it
66
+ # will be impossible to require it and that available gems will be
67
+ # limited exclusively to gems that have been bundled.
68
+ #
69
+ # The default is to automatically require rubygems. There is also a
70
+ # `disable_system_gems` option that will limit available rubygems to
71
+ # the ones that have been bundled.
72
+ #disable_rubygems
@@ -0,0 +1,3 @@
1
+ <%= shebang bin_file_name %>
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "<%= path.join("environment").relative_path_from(Pathname.new(bin_dir)) %>"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "<%= path.join("gems", @spec.full_name, @spec.bindir, bin_file_name).relative_path_from(Pathname.new(bin_dir)) %>"))
@@ -0,0 +1,156 @@
1
+ # DO NOT MODIFY THIS FILE
2
+ module Bundler
3
+ file = File.expand_path(__FILE__)
4
+ dir = File.dirname(file)
5
+
6
+ <% unless system_gems? -%>
7
+ ENV["GEM_HOME"] = dir
8
+ ENV["GEM_PATH"] = dir
9
+
10
+ # handle 1.9 where system gems are always on the load path
11
+ if defined?(::Gem)
12
+ $LOAD_PATH.reject! do |p|
13
+ p != File.dirname(__FILE__) &&
14
+ Gem.path.any? { |gp| p.include?(gp) }
15
+ end
16
+ end
17
+
18
+ <% end -%>
19
+ ENV["PATH"] = "#{dir}/<%= bindir %><%= File::PATH_SEPARATOR %>#{ENV["PATH"]}"
20
+ ENV["RUBYOPT"] = "-r#{file} #{ENV["RUBYOPT"]}"
21
+
22
+ <% load_paths.each do |load_path| -%>
23
+ $LOAD_PATH.unshift File.expand_path("#{dir}/<%= load_path %>")
24
+ <% end -%>
25
+
26
+ @gemfile = "#{dir}/<%= filename %>"
27
+
28
+ <% if rubygems? -%>
29
+ require "rubygems" unless respond_to?(:gem) # 1.9 already has RubyGems loaded
30
+
31
+ @bundled_specs = {}
32
+ <% specs.each do |spec| -%>
33
+ <% if spec.no_bundle? -%>
34
+ gem "<%= spec.name %>", "<%= spec.version %>"
35
+ <% else -%>
36
+ <% path = spec_file_for(spec) -%>
37
+ @bundled_specs["<%= spec.name %>"] = eval(File.read("#{dir}/<%= path %>"))
38
+ @bundled_specs["<%= spec.name %>"].loaded_from = "#{dir}/<%= path %>"
39
+ <% end -%>
40
+ <% end -%>
41
+
42
+ def self.add_specs_to_loaded_specs
43
+ Gem.loaded_specs.merge! @bundled_specs
44
+ end
45
+
46
+ def self.add_specs_to_index
47
+ @bundled_specs.each do |name, spec|
48
+ Gem.source_index.add_spec spec
49
+ end
50
+ end
51
+
52
+ add_specs_to_loaded_specs
53
+ add_specs_to_index
54
+ <% end -%>
55
+
56
+ def self.require_env(env = nil)
57
+ context = Class.new do
58
+ def initialize(env) @env = env && env.to_s ; end
59
+ def method_missing(*) ; yield if block_given? ; end
60
+ def only(*env)
61
+ old, @only = @only, _combine_only(env.flatten)
62
+ yield
63
+ @only = old
64
+ end
65
+ def except(*env)
66
+ old, @except = @except, _combine_except(env.flatten)
67
+ yield
68
+ @except = old
69
+ end
70
+ def gem(name, *args)
71
+ opt = args.last.is_a?(Hash) ? args.pop : {}
72
+ only = _combine_only(opt[:only] || opt["only"])
73
+ except = _combine_except(opt[:except] || opt["except"])
74
+ files = opt[:require_as] || opt["require_as"] || name
75
+ files = [files] unless files.respond_to?(:each)
76
+
77
+ return unless !only || only.any? {|e| e == @env }
78
+ return if except && except.any? {|e| e == @env }
79
+
80
+ if files = opt[:require_as] || opt["require_as"]
81
+ files = Array(files)
82
+ files.each { |f| require f }
83
+ else
84
+ begin
85
+ require name
86
+ rescue LoadError
87
+ # Do nothing
88
+ end
89
+ end
90
+ yield if block_given?
91
+ true
92
+ end
93
+ private
94
+ def _combine_only(only)
95
+ return @only unless only
96
+ only = [only].flatten.compact.uniq.map { |o| o.to_s }
97
+ only &= @only if @only
98
+ only
99
+ end
100
+ def _combine_except(except)
101
+ return @except unless except
102
+ except = [except].flatten.compact.uniq.map { |o| o.to_s }
103
+ except |= @except if @except
104
+ except
105
+ end
106
+ end
107
+ context.new(env && env.to_s).instance_eval(File.read(@gemfile), @gemfile, 1)
108
+ end
109
+ end
110
+
111
+ <% if rubygems? -%>
112
+ module Gem
113
+ @loaded_stacks = Hash.new { |h,k| h[k] = [] }
114
+
115
+ def source_index.refresh!
116
+ super
117
+ Bundler.add_specs_to_index
118
+ end
119
+ end
120
+ <% else -%>
121
+ $" << "rubygems.rb"
122
+
123
+ module Kernel
124
+ def gem(*)
125
+ # Silently ignore calls to gem, since, in theory, everything
126
+ # is activated correctly already.
127
+ end
128
+ end
129
+
130
+ # Define all the Gem errors for gems that reference them.
131
+ module Gem
132
+ def self.ruby ; <%= Gem.ruby.inspect %> ; end
133
+ def self.dir ; @dir ||= File.dirname(File.expand_path(__FILE__)) ; end
134
+ class << self ; alias default_dir dir; alias path dir ; end
135
+ class LoadError < ::LoadError; end
136
+ class Exception < RuntimeError; end
137
+ class CommandLineError < Exception; end
138
+ class DependencyError < Exception; end
139
+ class DependencyRemovalException < Exception; end
140
+ class GemNotInHomeException < Exception ; end
141
+ class DocumentError < Exception; end
142
+ class EndOfYAMLException < Exception; end
143
+ class FilePermissionError < Exception; end
144
+ class FormatException < Exception; end
145
+ class GemNotFoundException < Exception; end
146
+ class InstallError < Exception; end
147
+ class InvalidSpecificationException < Exception; end
148
+ class OperationNotSupportedError < Exception; end
149
+ class RemoteError < Exception; end
150
+ class RemoteInstallationCancelled < Exception; end
151
+ class RemoteInstallationSkipped < Exception; end
152
+ class RemoteSourceException < Exception; end
153
+ class VerificationError < Exception; end
154
+ class SystemExitException < SystemExit; end
155
+ end
156
+ <% end -%>