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,113 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Resolving specs with prerelease dependencies" do
4
+ def resolving(deps)
5
+ Bundler::Resolver.resolve(deps, [@index])
6
+ end
7
+
8
+ it "does not include prereleases by default" do
9
+ @index = build_index do
10
+ add_spec "bar", "3.0.pre"
11
+ add_spec "bar", "2.0"
12
+ end
13
+
14
+ deps = [build_dep("bar", ">= 2.0")]
15
+ resolving(deps).should match_gems "bar" => ["2.0"]
16
+ end
17
+
18
+ it "supports a single prerelease dependency" do
19
+ @index = build_index do
20
+ add_spec "bar", "2.0.0.rc2"
21
+ end
22
+
23
+ deps = [build_dep("bar", ">= 2.0.0.rc1")]
24
+
25
+ resolving(deps).should match_gems "bar" => ["2.0.0.rc2"]
26
+ end
27
+
28
+ it "child dependencies can require prerelease gems" do
29
+ @index = build_index do
30
+ add_spec "foo", "2.0" do
31
+ runtime "bar", ">= 3.0.pre"
32
+ end
33
+ add_spec "foo", "1.5" do
34
+ runtime "bar", ">= 2.0"
35
+ end
36
+ add_spec "bar", "3.0.pre"
37
+ add_spec "bar", "2.5"
38
+ add_spec "bar", "2.0"
39
+ end
40
+
41
+ deps = [build_dep("foo")]
42
+ resolving(deps).should match_gems "foo" => ["2.0"], "bar" => ["3.0.pre"]
43
+ end
44
+
45
+ it "doesn't blow up if there are only prerelease versions for a gem" do
46
+ @index = build_index do
47
+ add_spec "first", "1.0" do
48
+ runtime "second", ">= 0"
49
+ end
50
+ add_spec "second", "1.0.pre"
51
+ end
52
+
53
+ deps = [build_dep("first"), build_dep("second", "=1.0.pre")]
54
+ resolving(deps).should match_gems("first" => ["1.0"], "second" => ["1.0.pre"])
55
+ end
56
+
57
+ it "does backtracking" do
58
+ @index = build_index do
59
+ add_spec "first", "1.0" do
60
+ runtime "second", ">= 1.0"
61
+ end
62
+ add_spec "second", "1.0" do
63
+ runtime "third", ">= 1.0"
64
+ end
65
+ add_spec "third", "1.0"
66
+ add_spec "third", "2.0.pre"
67
+ end
68
+
69
+ deps = [build_dep("first"), build_dep("third", ">= 2.0.pre")]
70
+ resolving(deps).should match_gems("first" => ["1.0"], "second" => ["1.0"], "third" => ["2.0.pre"])
71
+ end
72
+
73
+ it "resolves well" do
74
+ @index = build_index do
75
+ add_spec "first", "1.0" do
76
+ runtime "second", ">= 1.0"
77
+ runtime "third", ">= 1.0"
78
+ end
79
+ add_spec "second", "1.0" do
80
+ runtime "fourth", ">= 1.0"
81
+ end
82
+ add_spec "third", "1.0" do
83
+ runtime "fourth", ">= 2.0.pre"
84
+ end
85
+ add_spec "fourth", "1.0"
86
+ add_spec "fourth", "2.0.pre"
87
+ end
88
+
89
+ deps = [build_dep("first")]
90
+ resolving(deps).should match_gems(
91
+ "first" => ["1.0"],
92
+ "second" => ["1.0"],
93
+ "third" => ["1.0"],
94
+ "fourth" => ["2.0.pre"]
95
+ )
96
+ end
97
+
98
+ it "is smart" do
99
+ @index = build_index do
100
+ add_spec "first", "1.0" do
101
+ runtime "second", ">= 1.0.pre"
102
+ end
103
+ add_spec "second", "1.0.pre" do
104
+ runtime "third", ">= 1.0"
105
+ end
106
+ add_spec "third", "1.0"
107
+ add_spec "third", "2.0.pre"
108
+ end
109
+
110
+ deps = [build_dep("first", "1.0")]
111
+ resolving(deps).should match_gems("first" => ["1.0"], "second" => ["1.0.pre"], "third" => ["1.0"])
112
+ end
113
+ end
@@ -0,0 +1,46 @@
1
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__)))
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require "pp"
5
+ require "rubygems"
6
+ require "bundler"
7
+ require "spec"
8
+ require "rbconfig"
9
+
10
+ Gem.clear_paths
11
+
12
+ root = File.expand_path("../..", __FILE__)
13
+ FileUtils.rm_rf("#{root}/tmp/repos")
14
+ `rake -f #{root}/Rakefile spec:setup`
15
+ ENV['GEM_HOME'], ENV['GEM_PATH'] = "#{root}/tmp/rg_deps", "#{root}/tmp/rg_deps"
16
+
17
+ Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each do |file|
18
+ require file
19
+ end
20
+
21
+ Spec::Runner.configure do |config|
22
+ config.include Spec::Builders
23
+ config.include Spec::Matchers
24
+ config.include Spec::Helpers
25
+ config.include Spec::PathUtils
26
+
27
+ original_wd = Dir.pwd
28
+
29
+ # No rubygems output messages
30
+ Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
31
+
32
+ config.before(:all) do
33
+ build_repo1
34
+ end
35
+
36
+ config.before(:each) do
37
+ @_build_path = nil
38
+ @log_output = StringIO.new
39
+ Bundler.logger.instance_variable_set("@logdev", Logger::LogDevice.new(@log_output))
40
+ reset!
41
+ end
42
+
43
+ config.after(:each) do
44
+ Dir.chdir(original_wd)
45
+ end
46
+ end
@@ -0,0 +1,257 @@
1
+ module Spec
2
+ module Builders
3
+
4
+ def build_repo1
5
+ build_repo gem_repo1 do
6
+ build_gem "rake", "0.8.7" do |s|
7
+ s.executables = "rake"
8
+ end
9
+ build_gem "rack", %w(0.9.1 1.0.0) do |s|
10
+ s.executables = "rackup"
11
+ end
12
+ build_gem "rails", "2.3.2" do |s|
13
+ s.executables = "rails"
14
+ s.add_dependency "rake"
15
+ s.add_dependency "actionpack", "2.3.2"
16
+ s.add_dependency "activerecord", "2.3.2"
17
+ s.add_dependency "actionmailer", "2.3.2"
18
+ s.add_dependency "activeresource", "2.3.2"
19
+ end
20
+ build_gem "actionpack", "2.3.2" do |s|
21
+ s.add_dependency "activesupport", "2.3.2"
22
+ end
23
+ build_gem "activerecord", "2.3.2" do |s|
24
+ s.add_dependency "activesupport", "2.3.2"
25
+ end
26
+ build_gem "actionmailer", "2.3.2" do |s|
27
+ s.add_dependency "activesupport", "2.3.2"
28
+ end
29
+ build_gem "activeresource", "2.3.2" do |s|
30
+ s.add_dependency "activesupport", "2.3.2"
31
+ end
32
+ build_gem "activesupport", "2.3.2"
33
+
34
+ build_gem "missing_dep" do |s|
35
+ s.add_dependency "not_here"
36
+ end
37
+
38
+ build_gem "rspec", "1.2.7", :no_default => true do |s|
39
+ s.write "lib/spec.rb", "SPEC = '1.2.7'"
40
+ end
41
+
42
+ build_gem "rack-test", :no_default => true do |s|
43
+ s.write "lib/rack/test.rb", "RACK_TEST = '1.0'"
44
+ end
45
+
46
+ build_gem "platform_specific" do |s|
47
+ s.platform = "java"
48
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 JAVA'"
49
+ end
50
+
51
+ build_gem "platform_specific" do |s|
52
+ s.platform = "ruby"
53
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
54
+ end
55
+
56
+ build_gem "only_java" do |s|
57
+ s.platform = "java"
58
+ end
59
+
60
+ build_gem "very-simple"
61
+
62
+ build_gem "very-simple-prerelease", "1.0.pre"
63
+
64
+ build_gem "very_simple_binary" do |s|
65
+ s.require_paths << 'ext'
66
+ s.extensions << "ext/extconf.rb"
67
+ s.write "ext/extconf.rb", <<-RUBY
68
+ require "mkmf"
69
+
70
+ exit 1 unless with_config("simple")
71
+
72
+ extension_name = "very_simple_binary_c"
73
+ dir_config extension_name
74
+ create_makefile extension_name
75
+ RUBY
76
+ s.write "ext/very_simple_binary.c", <<-C
77
+ #include "ruby.h"
78
+
79
+ void Init_very_simple_binary_c() {
80
+ rb_define_module("VerySimpleBinaryInC");
81
+ }
82
+ C
83
+ end
84
+ end
85
+ end
86
+
87
+ def build_repo2
88
+ FileUtils.rm_rf gem_repo2
89
+ FileUtils.cp_r gem_repo1, gem_repo2
90
+ end
91
+
92
+ def update_repo2
93
+ update_repo gem_repo2 do
94
+ build_gem "rack", "1.2" do |s|
95
+ s.executables = "rackup"
96
+ end
97
+ end
98
+ end
99
+
100
+ def build_repo(path, &blk)
101
+ return if File.directory?(path)
102
+ update_repo(path, &blk)
103
+ end
104
+
105
+ def update_repo(path)
106
+ @_build_path = "#{path}/gems"
107
+ yield
108
+ @_build_path = nil
109
+ Dir.chdir(path) { gem_command :generate_index }
110
+ end
111
+
112
+ def build_index(&block)
113
+ index = Gem::SourceIndex.new
114
+ IndexBuilder.run(index, &block) if block_given?
115
+ index
116
+ end
117
+
118
+ def build_spec(name, version, platform = nil, &block)
119
+ spec = Gem::Specification.new
120
+ spec.instance_variable_set(:@name, name)
121
+ spec.instance_variable_set(:@version, Gem::Version.new(version))
122
+ spec.platform = Gem::Platform.new(platform) if platform
123
+ DepBuilder.run(spec, &block) if block_given?
124
+ spec
125
+ end
126
+
127
+ def build_dep(name, requirements = Gem::Requirement.default, type = :runtime)
128
+ Bundler::Dependency.new(name, :version => requirements)
129
+ end
130
+
131
+ def build_lib(name, *args, &blk)
132
+ build_with(LibBuilder, name, args, &blk)
133
+ end
134
+
135
+ def build_gem(name, *args, &blk)
136
+ build_with(GemBuilder, name, args, &blk)
137
+ end
138
+
139
+ private
140
+
141
+ def build_with(builder, name, args, &blk)
142
+ options = args.last.is_a?(Hash) ? args.pop : {}
143
+ versions = args.last || "1.0"
144
+
145
+ options[:path] ||= @_build_path
146
+
147
+ Array(versions).each do |version|
148
+ spec = builder.new(self, name, version)
149
+ yield spec if block_given?
150
+ spec._build(options)
151
+ end
152
+ end
153
+
154
+ class IndexBuilder
155
+ include Builders
156
+
157
+ def self.run(index, &block)
158
+ new(index).run(&block)
159
+ end
160
+
161
+ def initialize(index)
162
+ @index = index
163
+ end
164
+
165
+ def run(&block)
166
+ instance_eval(&block)
167
+ end
168
+
169
+ def add_spec(*args, &block)
170
+ @index.add_spec(build_spec(*args, &block))
171
+ end
172
+ end
173
+
174
+ class DepBuilder
175
+ def self.run(spec, &block)
176
+ new(spec).run(&block)
177
+ end
178
+
179
+ def initialize(spec)
180
+ @spec = spec
181
+ end
182
+
183
+ def run(&block)
184
+ instance_eval(&block)
185
+ end
186
+
187
+ def runtime(name, requirements)
188
+ @spec.add_runtime_dependency(name, requirements)
189
+ end
190
+ end
191
+
192
+ class LibBuilder
193
+ def initialize(context, name, version)
194
+ @context = context
195
+ @name = name
196
+ @spec = Gem::Specification.new do |s|
197
+ s.name = name
198
+ s.version = version
199
+ s.summary = "This is just a fake gem for testing"
200
+ end
201
+ @files = {}
202
+ @default_files = { "lib/#{name}.rb" => "#{name.gsub('-', '').upcase} = '#{version}'" }
203
+ end
204
+
205
+ def method_missing(*args, &blk)
206
+ @spec.send(*args, &blk)
207
+ end
208
+
209
+ def write(file, source)
210
+ @files[file] = source
211
+ end
212
+
213
+ def executables=(val)
214
+ Array(val).each do |file|
215
+ write "bin/#{file}", "require '#{@name}' ; puts #{@name.upcase}"
216
+ end
217
+ @spec.executables = Array(val)
218
+ end
219
+
220
+ def _build(options)
221
+ path = options[:path] || _default_path
222
+ @files["#{name}.gemspec"] = @spec.to_ruby if options[:gemspec]
223
+ unless options[:no_default]
224
+ @files = @default_files.merge(@files)
225
+ end
226
+ @files.each do |file, source|
227
+ file = Pathname.new(path).join(file)
228
+ FileUtils.mkdir_p(file.dirname)
229
+ File.open(file, 'w') { |f| f.puts source }
230
+ end
231
+ @spec.files = @files.keys
232
+ path
233
+ end
234
+
235
+ def _default_path
236
+ @context.tmp_path('libs', @spec.full_name)
237
+ end
238
+ end
239
+
240
+ class GemBuilder < LibBuilder
241
+
242
+ def _build(opts)
243
+ lib_path = super(:path => @context.tmp_path(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default])
244
+ Dir.chdir(lib_path) do
245
+ destination = opts[:path] || _default_path
246
+ FileUtils.mkdir_p(destination)
247
+ Gem::Builder.new(@spec).build
248
+ FileUtils.mv("#{@spec.full_name}.gem", opts[:path] || _default_path)
249
+ end
250
+ end
251
+
252
+ def _default_path
253
+ @context.gem_repo1('gems')
254
+ end
255
+ end
256
+ end
257
+ end
@@ -0,0 +1,18 @@
1
+ class Pathname
2
+ def mkdir_p
3
+ FileUtils.mkdir_p(self)
4
+ end
5
+
6
+ def touch_p
7
+ dirname.mkdir_p
8
+ touch
9
+ end
10
+
11
+ def touch
12
+ FileUtils.touch(self)
13
+ end
14
+
15
+ def cp_r(dest)
16
+ FileUtils.cp_r(self, dest)
17
+ end
18
+ end
@@ -0,0 +1,126 @@
1
+ module Spec
2
+ module Helpers
3
+ def run_in_context(cmd)
4
+ env = bundled_path.join('environment.rb')
5
+ raise "Missing environment.rb" unless env.file?
6
+ ruby "-r #{env}", cmd
7
+ end
8
+
9
+ def ruby(opts, ruby = nil)
10
+ ruby, opts = opts, nil unless ruby
11
+ ruby.gsub!(/(?=")/, "\\")
12
+ ruby.gsub!('$', '\\$')
13
+ lib = File.join(File.dirname(__FILE__), '..', '..', 'lib')
14
+ %x{#{Gem.ruby} -I#{lib} #{opts} -e "#{ruby}"}.strip
15
+ end
16
+
17
+ def gem_command(command, args = "", options = {})
18
+ if command == :exec && !options[:no_quote]
19
+ args = args.gsub(/(?=")/, "\\")
20
+ args = %["#{args}"]
21
+ end
22
+ lib = File.join(File.dirname(__FILE__), '..', '..', 'lib')
23
+ %x{#{Gem.ruby} -I#{lib} -rubygems -S gem --backtrace #{command} #{args}}.strip
24
+ end
25
+
26
+ def build_manifest_file(*args)
27
+ path = bundled_app("Gemfile")
28
+ path = args.shift if args.first.is_a?(Pathname)
29
+ str = args.shift || ""
30
+ FileUtils.mkdir_p(path.dirname.to_s)
31
+ File.open(path.to_s, 'w') do |f|
32
+ f.puts str
33
+ end
34
+ end
35
+
36
+ def build_manifest(*args)
37
+ path = bundled_app("Gemfile")
38
+ path = args.shift if args.first.is_a?(Pathname)
39
+ str = args.shift || ""
40
+ FileUtils.mkdir_p(path.dirname)
41
+ Dir.chdir(path.dirname) do
42
+ build_manifest_file(path, str)
43
+ Bundler::Bundle.load(path)
44
+ end
45
+ end
46
+
47
+ def install_manifest(*args)
48
+ m = build_manifest(*args)
49
+ m.install
50
+ m
51
+ end
52
+
53
+ def build_git_repo(name, options = {})
54
+ name = name.to_s
55
+ with = options[:with] or raise "Omg, need to specify :with"
56
+ path = tmp_path.join("git", name)
57
+ path.parent.mkdir_p
58
+ with.cp_r(path)
59
+ if spec = options[:spec]
60
+ File.open(path.join("#{name}.gemspec"), 'w') do |file|
61
+ file.puts spec.to_ruby
62
+ end
63
+ end
64
+ Dir.chdir(path) do
65
+ `git init`
66
+ `git add *`
67
+ `git commit -m "OMG GITZ"`
68
+ `git checkout --quiet -b alt`
69
+ path.join("lib", name).mkdir_p
70
+ File.open(path.join("lib", name, "in_a_branch.rb"), 'w') do |file|
71
+ file.puts "OMG_IN_A_BRANCH = 'tagged'"
72
+ end
73
+ `git add *`
74
+ `git commit -m "OMG TAGGING"`
75
+ `git tag tagz`
76
+ File.open(path.join("lib", name, "in_a_branch.rb"), 'w') do |file|
77
+ file.puts "OMG_IN_A_BRANCH = 'branch'"
78
+ end
79
+ `git add *`
80
+ `git commit -m "OMG BRANCHING"`
81
+ `git checkout --quiet master`
82
+ File.open(path.join("lib", "#{name}.rb"), "w") do |file|
83
+ file.puts "VERYSIMPLE = '2.0'"
84
+ end
85
+ `git add *`
86
+ `git commit -m "OMG HEAD"`
87
+ end
88
+ path
89
+ end
90
+
91
+ def gitify(path)
92
+ Dir.chdir(path) do
93
+ `git init && git add * && git commit -m "OMG GITZ"`
94
+ end
95
+ end
96
+
97
+ def install_gems(*gems)
98
+ Dir["#{tmp_path}/repos/**/*.gem"].each do |path|
99
+ if gems.include?(File.basename(path, ".gem"))
100
+ gem_command :install, "--no-rdoc --no-ri --ignore-dependencies #{path}"
101
+ end
102
+ end
103
+ end
104
+
105
+ alias install_gem install_gems
106
+
107
+ def system_gems(*gems)
108
+ system_gem_path.mkdir_p
109
+
110
+ gem_home, gem_path = ENV['GEM_HOME'], ENV['GEM_PATH']
111
+ ENV['GEM_HOME'], ENV['GEM_PATH'] = system_gem_path.to_s, system_gem_path.to_s
112
+
113
+ install_gems(*gems)
114
+ yield
115
+ ENV['GEM_HOME'], ENV['GEM_PATH'] = gem_home, gem_path
116
+ end
117
+
118
+ def reset!
119
+ Dir["#{tmp_path}/*"].each do |file|
120
+ next if %w(repos rg_deps).include?(File.basename(file))
121
+ FileUtils.rm_rf(file)
122
+ end
123
+ FileUtils.mkdir_p(tmp_path)
124
+ end
125
+ end
126
+ end