bowline-bundler 0.0.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.
Files changed (43) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +291 -0
  3. data/Rakefile +45 -0
  4. data/VERSION +1 -0
  5. data/bin/bowline-bundle +59 -0
  6. data/lib/bowline/bundler/bundle.rb +323 -0
  7. data/lib/bowline/bundler/cli.rb +87 -0
  8. data/lib/bowline/bundler/dependency.rb +62 -0
  9. data/lib/bowline/bundler/dsl.rb +182 -0
  10. data/lib/bowline/bundler/environment.rb +87 -0
  11. data/lib/bowline/bundler/finder.rb +51 -0
  12. data/lib/bowline/bundler/gem_bundle.rb +11 -0
  13. data/lib/bowline/bundler/gem_ext.rb +34 -0
  14. data/lib/bowline/bundler/remote_specification.rb +53 -0
  15. data/lib/bowline/bundler/resolver.rb +250 -0
  16. data/lib/bowline/bundler/runtime.rb +2 -0
  17. data/lib/bowline/bundler/source.rb +361 -0
  18. data/lib/bowline/bundler/templates/app_script.erb +3 -0
  19. data/lib/bowline/bundler/templates/environment.erb +156 -0
  20. data/lib/bowline/bundler/templates/environment_picker.erb +4 -0
  21. data/lib/bowline/bundler.rb +35 -0
  22. data/spec/bundler/cli_spec.rb +558 -0
  23. data/spec/bundler/directory_spec.rb +255 -0
  24. data/spec/bundler/dsl_spec.rb +126 -0
  25. data/spec/bundler/fetcher_spec.rb +138 -0
  26. data/spec/bundler/git_spec.rb +266 -0
  27. data/spec/bundler/installer_spec.rb +155 -0
  28. data/spec/bundler/manifest_file_spec.rb +105 -0
  29. data/spec/bundler/manifest_spec.rb +257 -0
  30. data/spec/bundler/runtime_spec.rb +141 -0
  31. data/spec/bundler/system_gems_spec.rb +42 -0
  32. data/spec/quality_spec.rb +57 -0
  33. data/spec/resolver/engine_spec.rb +112 -0
  34. data/spec/resolver/error_spec.rb +50 -0
  35. data/spec/resolver/fake_source_index_spec.rb +43 -0
  36. data/spec/resolver/prerelease_spec.rb +113 -0
  37. data/spec/spec_helper.rb +46 -0
  38. data/spec/support/builders.rb +257 -0
  39. data/spec/support/core_ext.rb +18 -0
  40. data/spec/support/helpers.rb +126 -0
  41. data/spec/support/matchers.rb +201 -0
  42. data/spec/support/path_utils.rb +63 -0
  43. metadata +126 -0
@@ -0,0 +1,558 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Bundler::CLI" do
4
+
5
+ describe "it compiles gems that take options" do
6
+ before(:each) do
7
+ build_manifest <<-Gemfile
8
+ clear_sources
9
+ source "file://#{gem_repo1}"
10
+ gem "very_simple_binary"
11
+ Gemfile
12
+
13
+ File.open("#{bundled_app}/build.yml", "w+") do |file|
14
+ file.puts <<-build_options.gsub(/^ /, '')
15
+ very_simple_binary:
16
+ simple: wot
17
+ build_options
18
+ end
19
+ end
20
+
21
+ it "fails if the option is not provided" do
22
+ Dir.chdir(bundled_app) do
23
+ @output = gem_command :bundle, "2>&1"
24
+ end
25
+
26
+ @output.should =~ /Failed to build gem native extension/
27
+ end
28
+
29
+ it "passes if a yaml is specified that contains the necessary options" do
30
+ Dir.chdir(bundled_app) do
31
+ @output = gem_command :bundle, "--build-options=build.yml 2>&1"
32
+ end
33
+
34
+ @output.should_not =~ /Failed to build gem native extension/
35
+
36
+ out = run_in_context <<-RUBY
37
+ require 'very_simple_binary_c'
38
+ puts VerySimpleBinaryInC
39
+ RUBY
40
+
41
+ out.should == "VerySimpleBinaryInC"
42
+ end
43
+
44
+ it "does not skip the binary gem if compiling failed in a previous bundle" do
45
+ Dir.chdir(bundled_app)
46
+
47
+ gem_command :bundle, "--backtrace 2>&1" # will fail
48
+ gem_command :bundle, "--build-options=build.yml 2>&1"
49
+
50
+ out = run_in_context <<-RUBY
51
+ require "very_simple_binary_c"
52
+ puts VerySimpleBinaryInC
53
+ RUBY
54
+ out.should == "VerySimpleBinaryInC"
55
+ end
56
+ end
57
+
58
+ describe "it working" do
59
+ before :each do
60
+ @manifest = build_manifest <<-Gemfile
61
+ clear_sources
62
+ source "file://#{gem_repo1}"
63
+ gem "rake"
64
+ gem "activesupport"
65
+ gem "rack", :only => :web
66
+ Gemfile
67
+
68
+ Dir.chdir(bundled_app) do
69
+ @output = gem_command :bundle
70
+ end
71
+ end
72
+
73
+ it "caches and installs rake" do
74
+ gems = %w(rake-0.8.7 activesupport-2.3.2 rack-1.0.0)
75
+ @manifest.gem_path.should have_cached_gems(*gems)
76
+ @manifest.gem_path.should have_installed_gems(*gems)
77
+ end
78
+
79
+ it "creates a default environment file with the appropriate load paths" do
80
+ out = run_in_context <<-RUBY
81
+ require "rake"
82
+ require "activesupport"
83
+ require "rack"
84
+ puts "\#{RAKE} - \#{ACTIVESUPPORT} - \#{RACK}"
85
+ RUBY
86
+
87
+ out.should == "0.8.7 - 2.3.2 - 1.0.0"
88
+ end
89
+
90
+ it "creates a platform-independent environment picker" do
91
+ @manifest.gem_path.join('../../environment.rb').file?.should == true
92
+ end
93
+
94
+ it "creates valid executables in ./bin" do
95
+ app_root do
96
+ `bin/rake`.should == "0.8.7\n"
97
+ end
98
+ end
99
+
100
+ it "runs exec correctly" do
101
+ app_root do
102
+ out = gem_command :exec, %[ruby -e 'require "rake" ; puts RAKE']
103
+ out.should == "0.8.7"
104
+ end
105
+ end
106
+
107
+ it "runs exec with options correctly" do
108
+ Dir.chdir(bundled_app) do
109
+ out = gem_command :exec, %[ruby -e 'puts "hello"'], :no_quote => true
110
+ out.should == "hello"
111
+ end
112
+ end
113
+
114
+ it "maintains the correct environment when shelling out" do
115
+ out = run_in_context "exec %{#{Gem.ruby} -e 'require %{rake} ; puts RAKE'}"
116
+ out.should == "0.8.7"
117
+ end
118
+
119
+ it "logs the correct information messages" do
120
+ [ "Updating source: file:#{gem_repo1}",
121
+ "Calculating dependencies...",
122
+ "Downloading rake-0.8.7.gem",
123
+ "Downloading activesupport-2.3.2.gem",
124
+ "Downloading rack-1.0.0.gem",
125
+ "Installing rake (0.8.7)",
126
+ "Installing activesupport (2.3.2)",
127
+ "Installing rack (1.0.0)",
128
+ "Done." ].each do |message|
129
+ @output.should =~ /^#{Regexp.escape(message)}$/
130
+ end
131
+ end
132
+
133
+ it "already has gems in the loaded_specs" do
134
+ out = run_in_context "puts Gem.loaded_specs.key?('activesupport')"
135
+ out.should == "true"
136
+ end
137
+
138
+ it "does already has rubygems required" do
139
+ out = run_in_context "puts Gem.respond_to?(:sources)"
140
+ out.should == "true"
141
+ end
142
+
143
+ # TODO: Remove this when rubygems is fixed
144
+ it "adds the gem to Gem.source_index" do
145
+ out = run_in_context "puts Gem.source_index.find_name('activesupport').first.version"
146
+ out.should == "2.3.2"
147
+ end
148
+ end
149
+
150
+ describe "error cases" do
151
+ before :each do
152
+ bundled_app.mkdir_p
153
+ Dir.chdir(bundled_app)
154
+ end
155
+
156
+ it "displays a friendly error message when there is no Gemfile" do
157
+ out = gem_command :bundle
158
+ out.should == "Could not find a Gemfile to use"
159
+ end
160
+
161
+ it "fails when a root level gem does not exist" do
162
+ build_manifest <<-Gemfile
163
+ clear_sources
164
+ source "file://#{gem_repo1}"
165
+ gem "monk"
166
+ Gemfile
167
+
168
+ out = gem_command :bundle
169
+ out.should include("Could not find gem 'monk (>= 0, runtime)' in any of the sources")
170
+ end
171
+
172
+ it "outputs a warning when a child gem dependency is missing dependencies" do
173
+ build_manifest <<-Gemfile
174
+ clear_sources
175
+ source "file://#{gem_repo1}"
176
+ gem "missing_dep"
177
+ Gemfile
178
+
179
+ out = gem_command :bundle
180
+ out.should include("Could not find gem 'not_here (>= 0, runtime)' (required by 'missing_dep (>= 0, runtime)') in any of the sources")
181
+ end
182
+ end
183
+
184
+ it "raises when providing a bad manifest" do
185
+ out = gem_command :bundle, "-m manifest_not_here"
186
+ out.should =~ /Manifest file not found: \".*manifest_not_here\"/
187
+ end
188
+
189
+ describe "it working while specifying the manifest file name" do
190
+ it "works when the manifest is in the root directory" do
191
+ manifest = build_manifest bundled_app('manifest.rb'), <<-Gemfile
192
+ bundle_path "gems"
193
+ clear_sources
194
+ source "file://#{gem_repo1}"
195
+ gem "rake"
196
+ Gemfile
197
+
198
+ Dir.chdir(bundled_app) do
199
+ out = gem_command :bundle, "-m #{bundled_app('manifest.rb')}"
200
+ out.should include('Done.')
201
+ manifest.gem_path.should have_cached_gems("rake-0.8.7")
202
+ tmp_bindir('rake').should exist
203
+ end
204
+ end
205
+
206
+ it "works when the manifest is in a different directory" do
207
+ manifest = build_manifest bundled_app('config', 'manifest.rb'), <<-Gemfile
208
+ bundle_path "../gems"
209
+ clear_sources
210
+ source "file://#{gem_repo1}"
211
+ gem "rake"
212
+ Gemfile
213
+
214
+ Dir.chdir(bundled_app)
215
+ out = gem_command :bundle, "-m #{bundled_app('config', 'manifest.rb')}"
216
+ out.should include('Done.')
217
+ manifest.gem_path.should have_cached_gems("rake-0.8.7")
218
+ end
219
+
220
+ it "works when using a relative path to the manifest file" do
221
+ build_manifest_file bundled_app('manifest_file'), <<-Gemfile
222
+ clear_sources
223
+ source "file://#{gem_repo1}"
224
+ gem "rake"
225
+ Gemfile
226
+
227
+ Dir.chdir(bundled_app) do
228
+ out = gem_command :bundle, "-m manifest_file"
229
+ out.should include('Done.')
230
+ tmp_gem_path.should have_cached_gems("rake-0.8.7")
231
+ tmp_bindir('rake').should exist
232
+ end
233
+ end
234
+ end
235
+
236
+ describe "it working without rubygems" do
237
+ before(:each) do
238
+ @manifest = build_manifest <<-Gemfile
239
+ clear_sources
240
+ source "file://#{gem_repo1}"
241
+ gem "rake"
242
+ gem "rack", :only => :web
243
+
244
+ disable_rubygems
245
+ Gemfile
246
+
247
+ Dir.chdir(bundled_app) do
248
+ @output = gem_command :bundle
249
+ end
250
+ end
251
+
252
+ it "does not load rubygems when required" do
253
+ out = run_in_context 'require "rubygems" ; puts Gem.respond_to?(:sources)'
254
+ out.should == "false"
255
+ end
256
+
257
+ it "does not blow up if #gem is used" do
258
+ out = run_in_context 'gem("merb-core") ; puts "Win!"'
259
+ out.should == "Win!"
260
+ end
261
+
262
+ it "does not blow up if Gem errors are referred to" do
263
+ out = run_in_context 'Gem::LoadError ; Gem::Exception ; puts "Win!"'
264
+ out.should == "Win!"
265
+ end
266
+
267
+ it "stubs out Gem.ruby" do
268
+ out = run_in_context "puts Gem.ruby"
269
+ out.should == Gem.ruby
270
+ end
271
+
272
+ it "stubs out Gem.dir" do
273
+ out = run_in_context "puts Gem.dir"
274
+ out.should == @manifest.gem_path.to_s
275
+ end
276
+
277
+ it "stubs out Gem.default_dir" do
278
+ out = run_in_context "puts Gem.default_dir"
279
+ out.should == @manifest.gem_path.to_s
280
+ end
281
+
282
+ it "stubs out Gem.path" do
283
+ out = run_in_context "puts Gem.path"
284
+ out.should == @manifest.gem_path.to_s
285
+ end
286
+ end
287
+
288
+ describe "relative paths everywhere" do
289
+ it "still works when you move the app directory" do
290
+ install_manifest <<-Gemfile
291
+ clear_sources
292
+ source "file://#{gem_repo1}"
293
+ gem "rack"
294
+ Gemfile
295
+
296
+ FileUtils.mv bundled_app, tmp_path("bundled_app2")
297
+
298
+ Dir.chdir(tmp_path('bundled_app2')) do
299
+ out = gem_command :exec, "ruby -e 'Bundler.require_env :default ; puts RACK'"
300
+ out.should == "1.0.0"
301
+ `bin/rackup`.strip.should == "1.0.0"
302
+ end
303
+ end
304
+ end
305
+
306
+ describe "forcing an update" do
307
+ it "forces checking for remote updates if --update is used" do
308
+ m = build_manifest <<-Gemfile
309
+ clear_sources
310
+ source "file://#{gem_repo1}"
311
+ gem "rack", "0.9.1"
312
+ Gemfile
313
+ m.install
314
+
315
+ m = build_manifest <<-Gemfile
316
+ clear_sources
317
+ source "file://#{gem_repo1}"
318
+ gem "rack"
319
+ Gemfile
320
+
321
+ Dir.chdir(bundled_app) do
322
+ gem_command :bundle, "--update"
323
+ end
324
+ m.gem_path.should include_cached_gems("rack-1.0.0")
325
+ m.gem_path.should have_installed_gems("rack-1.0.0")
326
+ end
327
+ end
328
+
329
+ describe "bundling from the local cache" do
330
+ before(:each) do
331
+ install_manifest <<-Gemfile
332
+ clear_sources
333
+ source "file://#{gem_repo1}"
334
+ gem "rack", "0.9.1"
335
+ Gemfile
336
+
337
+ %w(doc environment.rb gems specifications).each do |f|
338
+ FileUtils.rm_rf(tmp_gem_path.join(f))
339
+ end
340
+ end
341
+
342
+ it "only uses the localy cached gems when bundling with --cache" do
343
+ build_manifest <<-Gemfile
344
+ clear_sources
345
+ source "file://#{gem_repo1}"
346
+ gem "rack"
347
+ Gemfile
348
+
349
+ Dir.chdir(bundled_app) do
350
+ gem_command :bundle, "--cached"
351
+ tmp_gem_path.should include_cached_gems("rack-0.9.1")
352
+ tmp_gem_path.should have_installed_gems("rack-0.9.1")
353
+ end
354
+ end
355
+
356
+ it "raises an exception when there are missing gems in the cache" do
357
+ Dir["#{tmp_gem_path}/cache/*"].each { |f| FileUtils.rm_rf(f) }
358
+
359
+ build_manifest <<-Gemfile
360
+ clear_sources
361
+ source "file://#{gem_repo1}"
362
+ gem "rack"
363
+ Gemfile
364
+
365
+ Dir.chdir(bundled_app) do
366
+ out = gem_command :bundle, "--cached"
367
+ out.should include("Could not find gem 'rack (>= 0, runtime)' in any of the sources")
368
+ tmp_gem_path.should_not include_cached_gems("rack-0.9.1", "rack-1.0.0")
369
+ tmp_gem_path.should_not include_installed_gems("rack-0.9.1", "rack-1.0.0")
370
+ end
371
+ end
372
+ end
373
+
374
+ describe "bundling only given environments" do
375
+ before(:each) do
376
+ build_manifest <<-Gemfile
377
+ clear_sources
378
+ source "file://#{gem_repo1}"
379
+ gem "activesupport"
380
+ gem "very-simple", :only => :server
381
+ gem "rack", :only => :test
382
+ Gemfile
383
+ end
384
+
385
+ it "install gems for environments specified in --only line" do
386
+ system_gems do
387
+ app_root do
388
+ gem_command :bundle, "--only test"
389
+ out = run_in_context "require 'activesupport' ; require 'rack' ; puts ACTIVESUPPORT"
390
+ out.should == "2.3.2"
391
+
392
+ out = run_in_context <<-RUBY
393
+ begin ;require 'very-simple'
394
+ rescue LoadError ; puts 'awesome' ; end
395
+ RUBY
396
+ out.should == 'awesome'
397
+ end
398
+ end
399
+ end
400
+ end
401
+
402
+ describe "caching gems to the bundle" do
403
+ before(:each) do
404
+ build_manifest <<-Gemfile
405
+ clear_sources
406
+ Gemfile
407
+ end
408
+
409
+ it "adds a single gem to the cache" do
410
+ build_manifest <<-Gemfile
411
+ clear_sources
412
+ gem "rack"
413
+ Gemfile
414
+
415
+ Dir.chdir(bundled_app) do
416
+ out = gem_command :bundle, "--cache #{gem_repo1}/gems/rack-0.9.1.gem"
417
+ gem_command :bundle, "--cached"
418
+ out.should include("Caching: rack-0.9.1.gem")
419
+ tmp_gem_path.should include_cached_gems("rack-0.9.1")
420
+ tmp_gem_path.should include_installed_gems("rack-0.9.1")
421
+ end
422
+ end
423
+
424
+ it "adds a gem directory to the cache" do
425
+ m = build_manifest <<-Gemfile
426
+ clear_sources
427
+ gem "rack"
428
+ gem "activesupport"
429
+ Gemfile
430
+
431
+ Dir.chdir(bundled_app) do
432
+ out = gem_command :bundle, "--cache #{gem_repo1}/gems"
433
+ gem_command :bundle, "--cached"
434
+
435
+ %w(actionmailer-2.3.2 activerecord-2.3.2 rake-0.8.7 rack-0.9.1 rack-1.0.0).each do |gemfile|
436
+ out.should include("Caching: #{gemfile}.gem")
437
+ end
438
+ m.gem_path.should include_cached_gems("rack-1.0.0", "activesupport-2.3.2")
439
+ m.gem_path.should have_installed_gems("rack-1.0.0", "activesupport-2.3.2")
440
+ end
441
+ end
442
+
443
+ it "adds a gem from the local repository" do
444
+ system_gems "rake-0.8.7" do
445
+ build_manifest <<-Gemfile
446
+ clear_sources
447
+ gem "rake"
448
+ disable_system_gems
449
+ Gemfile
450
+
451
+ Dir.chdir(bundled_app) do
452
+ # out = gem_command :bundle, "--cache rake"
453
+ gem_command :bundle
454
+ out = run_in_context "require 'rake' ; puts RAKE"
455
+ out.should == "0.8.7"
456
+ end
457
+ end
458
+ end
459
+
460
+ it "outputs an error when trying to cache a gem that doesn't exist." do
461
+ Dir.chdir(bundled_app) do
462
+ out = gem_command :bundle, "--cache foo/bar.gem"
463
+ out.should == "'foo/bar.gem' does not exist."
464
+ end
465
+ end
466
+
467
+ it "outputs an error when trying to cache a directory that doesn't exist." do
468
+ Dir.chdir(bundled_app) do
469
+ out = gem_command :bundle, "--cache foo/bar"
470
+ out.should == "'foo/bar' does not exist."
471
+ end
472
+ end
473
+
474
+ it "outputs an error when trying to cache a directory with no gems." do
475
+ Dir.chdir(bundled_app) do
476
+ FileUtils.mkdir_p("foo/bar")
477
+ out = gem_command :bundle, "--cache foo/bar"
478
+ out.should == "'foo/bar' contains no gemfiles"
479
+ end
480
+ end
481
+ end
482
+
483
+ describe "pruning the cache" do
484
+ it "works" do
485
+ manifest = install_manifest <<-Gemfile
486
+ clear_sources
487
+ source "file://#{gem_repo1}"
488
+ gem "rack", "0.9.1"
489
+ Gemfile
490
+
491
+ manifest.gem_path.should have_cached_gems("rack-0.9.1")
492
+
493
+ manifest = install_manifest <<-Gemfile
494
+ clear_sources
495
+ source "file://#{gem_repo1}"
496
+ Gemfile
497
+
498
+ manifest.gem_path.should have_cached_gems("rack-0.9.1")
499
+ Dir.chdir bundled_app
500
+ out = gem_command :bundle, "--prune-cache"
501
+ manifest.gem_path.should_not have_cached_gems("rack-0.9.1")
502
+ end
503
+ end
504
+
505
+ describe "listing gems" do
506
+ it "works" do
507
+ install_manifest <<-Gemfile
508
+ clear_sources
509
+ source "file://#{gem_repo1}"
510
+ gem "rack", "0.9.1"
511
+ Gemfile
512
+
513
+ Dir.chdir bundled_app
514
+ out = gem_command :bundle, "--list"
515
+ out.should =~ /rack/
516
+ end
517
+ end
518
+
519
+ describe "listing outdated gems" do
520
+ it "shows a message when there are no outdated gems" do
521
+ m = build_manifest <<-Gemfile
522
+ clear_sources
523
+ Gemfile
524
+ m.install
525
+
526
+ Dir.chdir(bundled_app) do
527
+ @output = gem_command :bundle, "--list-outdated"
528
+ end
529
+
530
+ @output.should =~ /All gems are up to date/
531
+ end
532
+
533
+ it "shows all the outdated gems" do
534
+ m = build_manifest <<-Gemfile
535
+ clear_sources
536
+ source "file://#{gem_repo1}"
537
+ gem "rack", "0.9.1"
538
+ gem "rails"
539
+ Gemfile
540
+ m.install
541
+
542
+ app_root do
543
+ @output = gem_command :bundle, "--list-outdated"
544
+ end
545
+
546
+ [ "Outdated gems:",
547
+ " * actionmailer",
548
+ " * actionpack",
549
+ " * activerecord",
550
+ " * activeresource",
551
+ " * activesupport",
552
+ " * rack",
553
+ " * rails"].each do |message|
554
+ @output.should =~ /^#{Regexp.escape(message)}$/
555
+ end
556
+ end
557
+ end
558
+ end