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,266 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Getting gems from git" do
4
+
5
+ before :each do
6
+ build_lib "very-simple", :path => "#{tmp_path}/very-simple"
7
+ end
8
+
9
+ describe "a simple gem in git" do
10
+ before(:each) do
11
+ @path = build_git_repo "very-simple", :with => tmp_path.join("very-simple")
12
+ install_manifest <<-Gemfile
13
+ clear_sources
14
+ source "file://#{gem_repo1}"
15
+ gem "very-simple", "1.0", :git => "#{@path}"
16
+ Gemfile
17
+ end
18
+
19
+ it "does not download the gem" do
20
+ tmp_gem_path.should_not include_cached_gem("very-simple-1.0")
21
+ tmp_gem_path.should include_installed_gem("very-simple-1.0")
22
+ tmp_gem_path.should include_vendored_dir("very-simple")
23
+ end
24
+
25
+ it "has very-simple in the load path" do
26
+ out = run_in_context "require 'very-simple' ; puts VERYSIMPLE"
27
+ out.should == "2.0"
28
+ end
29
+
30
+ it "removes the directory during cleanup" do
31
+ install_manifest <<-Gemfile
32
+ clear_sources
33
+ source "file://#{gem_repo1}"
34
+ Gemfile
35
+
36
+ pending "Gotta figure out how to implement this" do
37
+ tmp_gem_path("dirs", "very-simple").should_not be_directory
38
+ end
39
+ end
40
+
41
+ it "logs that the repo is being cloned" do
42
+ @log_output.should have_log_message("Cloning git repository at: #{@path}")
43
+ end
44
+
45
+ it "can bundle --cached when the git repository has already been cloned" do
46
+ %w(doc gems specifications environment.rb).each do |file|
47
+ FileUtils.rm_rf(tmp_gem_path(file))
48
+ end
49
+ FileUtils.rm_rf(@path)
50
+
51
+ Dir.chdir(bundled_app) do
52
+ out = gem_command :bundle, "--cached"
53
+ out = run_in_context "require 'very-simple' ; puts VERYSIMPLE"
54
+ out.should == "2.0"
55
+ end
56
+ end
57
+ end
58
+
59
+ it "checks the root directory for a *.gemspec file" do
60
+ spec = Gem::Specification.new do |s|
61
+ s.name = %q{very-simple}
62
+ s.version = "1.0"
63
+ s.require_paths = ["lib"]
64
+ s.add_dependency "rack", ">= 0.9.1"
65
+ end
66
+ @path = build_git_repo "very-simple", :with => fixture_dir.join("very-simple"), :spec => spec
67
+
68
+ install_manifest <<-Gemfile
69
+ clear_sources
70
+ source "file://#{gem_repo1}"
71
+ gem "very-simple", "1.0", :git => "#{@path}"
72
+ Gemfile
73
+
74
+ tmp_gem_path.should_not include_cached_gem("very-simple-1.0")
75
+ tmp_gem_path.should include_cached_gem("rack-1.0.0")
76
+ tmp_gem_path.should include_installed_gem("rack-1.0.0")
77
+ end
78
+
79
+ it "recursively finds all gemspec files in a git repository" do
80
+ build_lib("first", "1.0", :path => tmp_path("gitz", "first"), :gemspec => true)
81
+ build_lib("second", "1.0", :path => tmp_path("gitz", "second"), :gemspec => true) do |s|
82
+ s.add_dependency "first", ">= 0"
83
+ s.write "lib/second.rb", "require 'first' ; SECOND = '1.0'"
84
+ end
85
+
86
+ gitify(tmp_path("gitz"))
87
+
88
+ install_manifest <<-Gemfile
89
+ clear_sources
90
+ gem "second", "1.0", :git => "#{tmp_path('gitz')}"
91
+ Gemfile
92
+
93
+ out = run_in_context <<-RUBY
94
+ Bundler.require_env
95
+ puts FIRST
96
+ puts SECOND
97
+ RUBY
98
+
99
+ out.should == "1.0\n1.0"
100
+ end
101
+
102
+ it "raises exception when git does not contain correct gem version" do
103
+ build_lib "omg", "1.0.2", :gemspec => true
104
+ gitify tmp_path("libs")
105
+
106
+ lambda do
107
+ install_manifest <<-Gemfile
108
+ clear_sources
109
+ gem "omg", "~> 1.1", :git => "#{tmp_path("libs")}"
110
+ Gemfile
111
+ end.should raise_error(Bundler::GemNotFound, /git/)
112
+ end
113
+
114
+ it "allows bundling a specific tag" do
115
+ path = build_git_repo "very-simple", :with => fixture_dir.join("very-simple")
116
+ install_manifest <<-Gemfile
117
+ clear_sources
118
+ source "file://#{gem_repo1}"
119
+ gem "very-simple", "1.0", :git => "#{path}", :tag => 'tagz'
120
+ Gemfile
121
+
122
+ out = run_in_context "require 'very-simple/in_a_branch' ; puts OMG_IN_A_BRANCH"
123
+ out.should == "tagged"
124
+ end
125
+
126
+ it "allows bundling a specific branch" do
127
+ path = build_git_repo "very-simple", :with => fixture_dir.join("very-simple")
128
+ install_manifest <<-Gemfile
129
+ clear_sources
130
+ source "file://#{gem_repo1}"
131
+ gem "very-simple", "1.0", :git => "#{path}", :branch => 'alt'
132
+ Gemfile
133
+
134
+ out = run_in_context "require 'very-simple/in_a_branch' ; puts OMG_IN_A_BRANCH"
135
+ out.should == "branch"
136
+ end
137
+
138
+ it "allows bundling a specific ref" do
139
+ path = build_git_repo "very-simple", :with => fixture_dir.join("very-simple")
140
+ install_manifest <<-Gemfile
141
+ clear_sources
142
+ source "file://#{gem_repo1}"
143
+ gem "very-simple", "1.0", :git => "#{path}", :ref => 'HEAD'
144
+ Gemfile
145
+
146
+ out = run_in_context "require 'very-simple' ; puts VERYSIMPLE"
147
+ out.should == "2.0"
148
+ end
149
+
150
+
151
+ it "raises an error if trying to run in --cached mode but the repository has not been cloned" do
152
+ @path = build_git_repo "very-simple", :with => fixture_dir.join("very-simple")
153
+ build_manifest <<-Gemfile
154
+ clear_sources
155
+ source "file://#{gem_repo1}"
156
+ gem "very-simple", "1.0", :git => "#{@path}"
157
+ Gemfile
158
+
159
+ Dir.chdir(bundled_app) do
160
+ out = gem_command :bundle, "--cached"
161
+ out.should include("Git repository '#{@path}' has not been cloned yet")
162
+
163
+ tmp_gem_path.should_not include_cached_gem("very-simple-1.0")
164
+ tmp_gem_path.should_not include_installed_gem("very-simple-1.0")
165
+ tmp_gem_path.should_not include_vendored_dir("very-simple")
166
+ end
167
+ end
168
+
169
+ describe "using a git block" do
170
+ it "loads the gems specified in the git block" do
171
+ build_lib "omg", "1.0", :gemspec => true, :path => "#{tmp_path}/dirs/omg"
172
+ gitify("#{tmp_path}/dirs/omg")
173
+
174
+ install_manifest <<-Gemfile
175
+ clear_sources
176
+ git "#{tmp_path}/dirs/omg" do
177
+ gem "omg"
178
+ end
179
+ Gemfile
180
+
181
+ :default.should have_const("OMG")
182
+ end
183
+
184
+ it "works when specifying a branch" do
185
+ build_lib "omg", "1.0", :gemspec => true, :path => "#{tmp_path}/dirs/omg"
186
+ gitify("#{tmp_path}/dirs/omg")
187
+
188
+ install_manifest <<-Gemfile
189
+ clear_sources
190
+ git "#{tmp_path}/dirs/omg", :branch => :master do
191
+ gem "omg"
192
+ end
193
+ Gemfile
194
+
195
+ :default.should have_const("OMG")
196
+ end
197
+
198
+ it "works when the gems don't have gemspecs" do
199
+ build_lib "omg", "1.0", :gemspec => false, :path => "#{tmp_path}/dirs/omg"
200
+ gitify("#{tmp_path}/dirs/omg")
201
+
202
+ install_manifest <<-Gemfile
203
+ clear_sources
204
+ git "#{tmp_path}/dirs/omg" do
205
+ gem "omg", "1.0"
206
+ end
207
+ Gemfile
208
+
209
+ :default.should have_const("OMG")
210
+ end
211
+
212
+ it "works when the gems are not at the root" do
213
+ build_lib "omg", "1.0", :gemspec => false, :path => "#{tmp_path}/dirs/omg"
214
+ gitify("#{tmp_path}/dirs")
215
+
216
+ install_manifest <<-Gemfile
217
+ clear_sources
218
+ git "#{tmp_path}/dirs" do
219
+ gem "omg", "1.0", :path => "omg"
220
+ end
221
+ Gemfile
222
+
223
+ :default.should have_const("OMG")
224
+ end
225
+
226
+ it "always pulls the dependency from git even if there is a newer gem available" do
227
+ build_lib "abstract", "0.5", :path => "#{tmp_path}/dirs/abstract", :gemspec => true
228
+ gitify("#{tmp_path}/dirs/abstract")
229
+
230
+ install_manifest <<-Gemfile
231
+ clear_sources
232
+ source "file://#{gem_repo1}"
233
+ gem "abstract", :git => "#{tmp_path}/dirs/abstract"
234
+ Gemfile
235
+
236
+ out = run_in_context <<-RUBY
237
+ Bundler.require_env
238
+ puts ABSTRACT
239
+ RUBY
240
+
241
+ out.should == '0.5'
242
+ end
243
+
244
+ it "raises an exception when nesting calls to git" do
245
+ lambda {
246
+ install_manifest <<-Gemfile
247
+ git "foo" do
248
+ git "bar" do
249
+ gem "omg"
250
+ end
251
+ end
252
+ Gemfile
253
+ }.should raise_error(Bundler::DirectorySourceError, /cannot nest calls to directory or git/)
254
+
255
+ lambda {
256
+ install_manifest <<-Gemfile
257
+ directory "foo" do
258
+ git "bar" do
259
+ gem "omg"
260
+ end
261
+ end
262
+ Gemfile
263
+ }.should raise_error(Bundler::DirectorySourceError, /cannot nest calls to directory or git/)
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,155 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Installing gems" do
4
+
5
+ describe "the bundle directory" do
6
+
7
+ before(:each) do
8
+ @gems = %w(
9
+ actionmailer-2.3.2 actionpack-2.3.2 activerecord-2.3.2
10
+ activeresource-2.3.2 activesupport-2.3.2 rails-2.3.2 rake-0.8.7)
11
+ end
12
+
13
+ def setup
14
+ @gems = %w(actionmailer-2.3.2 actionpack-2.3.2 activerecord-2.3.2
15
+ activeresource-2.3.2 activesupport-2.3.2 rails-2.3.2
16
+ rake-0.8.7)
17
+ @manifest = build_manifest <<-Gemfile
18
+ clear_sources
19
+ source "file://#{gem_repo1}"
20
+ gem "rails"
21
+ Gemfile
22
+ end
23
+
24
+ it "creates the bundle directory if it does not exist" do
25
+ setup
26
+ @manifest.install
27
+ @manifest.gem_path.should have_cached_gems(*@gems)
28
+ end
29
+
30
+ it "uses the bundle directory if it is empty" do
31
+ bundled_path.mkdir_p
32
+ setup
33
+ @manifest.install
34
+ @manifest.gem_path.should have_cached_gems(*@gems)
35
+ end
36
+
37
+ it "uses the bundle directory if it is a valid gem repo" do
38
+ %w(cache doc specifications).each { |dir| bundled_path.join(dir).mkdir_p }
39
+ bundled_path.join('gems').mkdir_p
40
+ bundled_path.join('environment.rb').touch
41
+ setup
42
+ @manifest.install
43
+ @manifest.gem_path.should have_cached_gems(*@gems)
44
+ end
45
+
46
+ it "does not use the bundle directory if it is not a valid gem repo" do
47
+ bundled_path.join('fail').touch_p
48
+ lambda {
49
+ setup
50
+ @manifest.install
51
+ }.should_not raise_error
52
+ end
53
+
54
+ it "installs the bins in the directory you specify" do
55
+ bundled_app("omgbinz").mkdir_p
56
+ m = build_manifest <<-Gemfile
57
+ clear_sources
58
+ source "file://#{gem_repo1}"
59
+ bin_path "#{bundled_app("omgbinz")}"
60
+ gem "rails"
61
+ Gemfile
62
+ m.install
63
+ bundled_app("omgbinz", "rails").should exist
64
+ end
65
+
66
+ it "does not remove any existing bin files" do
67
+ bundled_app("bin").mkdir_p
68
+ bundled_app("bin", "hello").touch
69
+ setup
70
+ @manifest.install
71
+ bundled_app("bin", "hello").should exist
72
+ end
73
+
74
+ it "does not modify any .gemspec files that are to be installed if a directory of the same name exists" do
75
+ dir = bundled_path.join("gems", "rails-2.3.2")
76
+ spec = bundled_path.join("specifications", "rails-2.3.2.gemspec")
77
+ bin = dir.join("bin", "rails")
78
+
79
+ dir.mkdir_p
80
+ spec.touch_p
81
+ bin.touch_p
82
+
83
+ setup
84
+ lambda { @manifest.install }.should_not change { [dir.mtime, spec.mtime, bin.mtime] }
85
+ end
86
+
87
+ it "keeps bin files for already installed gems" do
88
+ setup
89
+ bundled_app("bin", "rails").should_not exist
90
+ @manifest.install
91
+ @manifest.install
92
+ bundled_app("bin", "rails").should exist
93
+ end
94
+
95
+ it "does not remove bin files when updating gems" do
96
+ install_manifest <<-Gemfile
97
+ clear_sources
98
+ source "file://#{gem_repo1}"
99
+ gem "rack", "0.9.1"
100
+ Gemfile
101
+
102
+ tmp_bindir("rackup").should exist
103
+
104
+ install_manifest <<-Gemfile
105
+ clear_sources
106
+ source "file://#{gem_repo1}"
107
+ gem "rack", "1.0.0"
108
+ Gemfile
109
+
110
+ tmp_bindir("rackup").should exist
111
+ end
112
+
113
+ it "each thing in the bundle has a directory in gems" do
114
+ setup
115
+ @manifest.install
116
+ @gems.each do |name|
117
+ @manifest.gem_path.join('gems', name).should be_directory
118
+ end
119
+ end
120
+
121
+ it "creates a specification for each gem" do
122
+ setup
123
+ @manifest.install
124
+ @gems.each do |name|
125
+ @manifest.gem_path.join("specifications/#{name}.gemspec").should be_file
126
+ end
127
+ end
128
+
129
+ it "works with prerelease gems" do
130
+ m = build_manifest <<-Gemfile
131
+ clear_sources
132
+ source "file://#{gem_repo1}"
133
+ gem "very-simple-prerelease", "1.0.pre"
134
+ Gemfile
135
+ m.install
136
+ m.gem_path.should have_cached_gem("very-simple-prerelease-1.0.pre")
137
+ m.gem_path.should have_installed_gem("very-simple-prerelease-1.0.pre")
138
+ end
139
+
140
+ it "outputs a logger message for each gem that is installed" do
141
+ setup
142
+ @manifest.install
143
+ @gems.each do |name|
144
+ name, version = name.split("-")
145
+ @log_output.should have_log_message("Installing #{name} (#{version})")
146
+ end
147
+ end
148
+
149
+ it "copies gem executables to a specified path" do
150
+ setup
151
+ @manifest.install
152
+ bundled_app('bin', 'rails').should be_file
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,105 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Bundler::Environment" do
4
+
5
+ before :each do
6
+ @manifest = simple_manifest
7
+ end
8
+
9
+ def simple_manifest(extra = nil)
10
+ build_manifest <<-Gemfile
11
+ clear_sources
12
+ source "file://#{gem_repo1}"
13
+ gem "rack"
14
+ #{extra}
15
+ Gemfile
16
+ end
17
+
18
+ def goto(where)
19
+ if where == :app
20
+ where = bundled_app
21
+ else
22
+ where = "#{bundled_app}/#{where}"
23
+ end
24
+
25
+ FileUtils.mkdir_p(where)
26
+ Dir.chdir(where)
27
+ end
28
+
29
+ def bundle
30
+ gem_command :bundle
31
+ end
32
+
33
+ def works
34
+ run_in_context("Bundler.require_env ; puts RACK").should == "1.0.0"
35
+ end
36
+
37
+ it "finds the default manifest file when it's in a parent directory" do
38
+ goto "wot"
39
+ bundle
40
+ works
41
+ end
42
+
43
+ it "sets the default bundle path to vendor/gems" do
44
+ @manifest.gem_path.join('environment.rb').should_not exist
45
+ goto :app
46
+ bundle
47
+ @manifest.gem_path.join('environment.rb').should exist
48
+ end
49
+
50
+ it "allows setting the bundle path in the manifest file" do
51
+ simple_manifest %[bundle_path "#{bundled_app('gems')}"]
52
+ goto :app
53
+ bundle
54
+ bundled_app('gems').should exist
55
+ end
56
+
57
+ it "sets the ruby-specific path relative to the bundle_path" do
58
+ simple_manifest %[bundle_path File.join('..', 'cheezeburgerz')]
59
+ goto 'w0t'
60
+ bundle
61
+ tmp_path("cheezeburgerz", Gem.ruby_engine, Gem::ConfigMap[:ruby_version], "environment.rb").should exist
62
+ end
63
+
64
+ it "assumes the bundle_path is relative to the manifest file no matter what the current working dir is" do
65
+ simple_manifest %[bundle_path File.join('..', 'cheezeburgerz')]
66
+ goto 'w0t'
67
+ bundle
68
+ tmp_path('cheezeburgerz').should exist
69
+ end
70
+
71
+ it "sets the default bindir relative to the Gemfile" do
72
+ goto 'wot'
73
+ bundle
74
+ bundled_app("bin/rackup").should exist
75
+ end
76
+
77
+ it "allows setting the bindir in the manifest file" do
78
+ simple_manifest %[bin_path "#{bundled_app('binz')}"]
79
+ goto :app
80
+ bundle
81
+ bundled_app('binz/rackup').should exist
82
+ end
83
+
84
+ it "assumes the bindir is relative to the manifest file no matter what the current working dir is" do
85
+ simple_manifest %[bin_path File.join('..', 'cheezeburgerz')]
86
+ goto 'w0t'
87
+ bundle
88
+ tmp_path('cheezeburgerz/rackup').should exist
89
+ end
90
+
91
+ it "overwrites existing bin files" do
92
+ bundled_app("bin/rackup").touch_p
93
+ goto :app
94
+ bundle
95
+ `#{bundled_app}/bin/rackup`.should == "1.0.0\n"
96
+ end
97
+
98
+ it "recreates the bin files if they are missing" do
99
+ goto :app
100
+ bundle
101
+ bundled_app('bin/rackup').delete
102
+ bundle
103
+ bundled_app('bin/rackup').should exist
104
+ end
105
+ end