shopify-bundler 1.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +96 -0
  5. data/.rubocop_todo.yml +177 -0
  6. data/.travis.yml +104 -0
  7. data/CHANGELOG.md +2131 -0
  8. data/CODE_OF_CONDUCT.md +42 -0
  9. data/CONTRIBUTING.md +32 -0
  10. data/DEVELOPMENT.md +118 -0
  11. data/ISSUES.md +96 -0
  12. data/LICENSE.md +23 -0
  13. data/README.md +40 -0
  14. data/Rakefile +309 -0
  15. data/bin/rake +14 -0
  16. data/bin/rspec +10 -0
  17. data/bin/rubocop +11 -0
  18. data/bundler.gemspec +34 -0
  19. data/exe/bundle +21 -0
  20. data/exe/bundle_ruby +60 -0
  21. data/exe/bundler +21 -0
  22. data/lib/bundler.rb +499 -0
  23. data/lib/bundler/capistrano.rb +16 -0
  24. data/lib/bundler/cli.rb +435 -0
  25. data/lib/bundler/cli/binstubs.rb +37 -0
  26. data/lib/bundler/cli/cache.rb +34 -0
  27. data/lib/bundler/cli/check.rb +37 -0
  28. data/lib/bundler/cli/clean.rb +25 -0
  29. data/lib/bundler/cli/common.rb +56 -0
  30. data/lib/bundler/cli/config.rb +88 -0
  31. data/lib/bundler/cli/console.rb +37 -0
  32. data/lib/bundler/cli/exec.rb +51 -0
  33. data/lib/bundler/cli/gem.rb +208 -0
  34. data/lib/bundler/cli/init.rb +32 -0
  35. data/lib/bundler/cli/inject.rb +32 -0
  36. data/lib/bundler/cli/install.rb +188 -0
  37. data/lib/bundler/cli/lock.rb +35 -0
  38. data/lib/bundler/cli/open.rb +22 -0
  39. data/lib/bundler/cli/outdated.rb +86 -0
  40. data/lib/bundler/cli/package.rb +45 -0
  41. data/lib/bundler/cli/platform.rb +42 -0
  42. data/lib/bundler/cli/show.rb +74 -0
  43. data/lib/bundler/cli/update.rb +72 -0
  44. data/lib/bundler/cli/viz.rb +26 -0
  45. data/lib/bundler/constants.rb +5 -0
  46. data/lib/bundler/current_ruby.rb +218 -0
  47. data/lib/bundler/definition.rb +675 -0
  48. data/lib/bundler/dep_proxy.rb +45 -0
  49. data/lib/bundler/dependency.rb +119 -0
  50. data/lib/bundler/deployment.rb +62 -0
  51. data/lib/bundler/deprecate.rb +17 -0
  52. data/lib/bundler/dsl.rb +478 -0
  53. data/lib/bundler/endpoint_specification.rb +100 -0
  54. data/lib/bundler/env.rb +82 -0
  55. data/lib/bundler/environment.rb +41 -0
  56. data/lib/bundler/fetcher.rb +288 -0
  57. data/lib/bundler/fetcher/base.rb +26 -0
  58. data/lib/bundler/fetcher/dependency.rb +88 -0
  59. data/lib/bundler/fetcher/downloader.rb +60 -0
  60. data/lib/bundler/fetcher/index.rb +32 -0
  61. data/lib/bundler/friendly_errors.rb +92 -0
  62. data/lib/bundler/gem_helper.rb +191 -0
  63. data/lib/bundler/gem_helpers.rb +26 -0
  64. data/lib/bundler/gem_installer.rb +9 -0
  65. data/lib/bundler/gem_path_manipulation.rb +8 -0
  66. data/lib/bundler/gem_tasks.rb +5 -0
  67. data/lib/bundler/graph.rb +173 -0
  68. data/lib/bundler/index.rb +199 -0
  69. data/lib/bundler/injector.rb +62 -0
  70. data/lib/bundler/inline.rb +58 -0
  71. data/lib/bundler/installer.rb +242 -0
  72. data/lib/bundler/installer/parallel_installer.rb +122 -0
  73. data/lib/bundler/installer/standalone.rb +48 -0
  74. data/lib/bundler/lazy_specification.rb +82 -0
  75. data/lib/bundler/lockfile_parser.rb +199 -0
  76. data/lib/bundler/match_platform.rb +13 -0
  77. data/lib/bundler/psyched_yaml.rb +26 -0
  78. data/lib/bundler/remote_specification.rb +82 -0
  79. data/lib/bundler/resolver.rb +350 -0
  80. data/lib/bundler/retry.rb +60 -0
  81. data/lib/bundler/ruby_dsl.rb +11 -0
  82. data/lib/bundler/ruby_version.rb +116 -0
  83. data/lib/bundler/rubygems_ext.rb +175 -0
  84. data/lib/bundler/rubygems_integration.rb +674 -0
  85. data/lib/bundler/runtime.rb +285 -0
  86. data/lib/bundler/settings.rb +263 -0
  87. data/lib/bundler/setup.rb +26 -0
  88. data/lib/bundler/shared_helpers.rb +176 -0
  89. data/lib/bundler/similarity_detector.rb +61 -0
  90. data/lib/bundler/source.rb +35 -0
  91. data/lib/bundler/source/git.rb +286 -0
  92. data/lib/bundler/source/git/git_proxy.rb +190 -0
  93. data/lib/bundler/source/path.rb +224 -0
  94. data/lib/bundler/source/path/installer.rb +43 -0
  95. data/lib/bundler/source/rubygems.rb +436 -0
  96. data/lib/bundler/source/rubygems/remote.rb +38 -0
  97. data/lib/bundler/source_list.rb +101 -0
  98. data/lib/bundler/spec_set.rb +156 -0
  99. data/lib/bundler/ssl_certs/.document +1 -0
  100. data/lib/bundler/ssl_certs/AddTrustExternalCARoot-2048.pem +25 -0
  101. data/lib/bundler/ssl_certs/AddTrustExternalCARoot.pem +32 -0
  102. data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +14 -0
  103. data/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +23 -0
  104. data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +28 -0
  105. data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +20 -0
  106. data/lib/bundler/ssl_certs/certificate_manager.rb +64 -0
  107. data/lib/bundler/stub_specification.rb +23 -0
  108. data/lib/bundler/templates/Executable +16 -0
  109. data/lib/bundler/templates/Executable.standalone +12 -0
  110. data/lib/bundler/templates/Gemfile +4 -0
  111. data/lib/bundler/templates/newgem/.travis.yml.tt +4 -0
  112. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +22 -0
  113. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  114. data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
  115. data/lib/bundler/templates/newgem/README.md.tt +41 -0
  116. data/lib/bundler/templates/newgem/Rakefile.tt +29 -0
  117. data/lib/bundler/templates/newgem/bin/console.tt +14 -0
  118. data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
  119. data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
  120. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
  121. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  122. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  123. data/lib/bundler/templates/newgem/gitignore.tt +16 -0
  124. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +12 -0
  125. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  126. data/lib/bundler/templates/newgem/newgem.gemspec.tt +43 -0
  127. data/lib/bundler/templates/newgem/rspec.tt +2 -0
  128. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +11 -0
  129. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -0
  130. data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +11 -0
  131. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +4 -0
  132. data/lib/bundler/ui.rb +7 -0
  133. data/lib/bundler/ui/rg_proxy.rb +17 -0
  134. data/lib/bundler/ui/shell.rb +108 -0
  135. data/lib/bundler/ui/silent.rb +44 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +5 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +277 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +69 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +3 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +99 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +63 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +434 -0
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +43 -0
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +51 -0
  145. data/lib/bundler/vendor/net/http/faster.rb +26 -0
  146. data/lib/bundler/vendor/net/http/persistent.rb +1230 -0
  147. data/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb +128 -0
  148. data/lib/bundler/vendor/thor/lib/thor.rb +484 -0
  149. data/lib/bundler/vendor/thor/lib/thor/actions.rb +319 -0
  150. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  151. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +59 -0
  152. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +118 -0
  153. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +135 -0
  154. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +316 -0
  155. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +107 -0
  156. data/lib/bundler/vendor/thor/lib/thor/base.rb +656 -0
  157. data/lib/bundler/vendor/thor/lib/thor/command.rb +133 -0
  158. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +77 -0
  159. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +10 -0
  160. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +98 -0
  161. data/lib/bundler/vendor/thor/lib/thor/error.rb +32 -0
  162. data/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
  163. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +178 -0
  164. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
  165. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +35 -0
  166. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  167. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  168. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +73 -0
  169. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +175 -0
  170. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +125 -0
  171. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +218 -0
  172. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +71 -0
  173. data/lib/bundler/vendor/thor/lib/thor/runner.rb +322 -0
  174. data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
  175. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +421 -0
  176. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +149 -0
  177. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +126 -0
  178. data/lib/bundler/vendor/thor/lib/thor/util.rb +267 -0
  179. data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
  180. data/lib/bundler/vendored_molinillo.rb +2 -0
  181. data/lib/bundler/vendored_persistent.rb +11 -0
  182. data/lib/bundler/vendored_thor.rb +3 -0
  183. data/lib/bundler/version.rb +6 -0
  184. data/lib/bundler/vlad.rb +11 -0
  185. data/lib/bundler/worker.rb +72 -0
  186. data/man/bundle-config.ronn +187 -0
  187. data/man/bundle-exec.ronn +136 -0
  188. data/man/bundle-gem.ronn +77 -0
  189. data/man/bundle-install.ronn +398 -0
  190. data/man/bundle-package.ronn +66 -0
  191. data/man/bundle-platform.ronn +42 -0
  192. data/man/bundle-update.ronn +188 -0
  193. data/man/bundle.ronn +98 -0
  194. data/man/gemfile.5.ronn +495 -0
  195. data/man/index.txt +8 -0
  196. metadata +346 -0
@@ -0,0 +1,45 @@
1
+ module Bundler
2
+ class DepProxy
3
+ attr_reader :__platform, :dep
4
+
5
+ def initialize(dep, platform)
6
+ @dep = dep
7
+ @__platform = platform
8
+ end
9
+
10
+ def hash
11
+ @hash ||= dep.hash
12
+ end
13
+
14
+ def ==(other)
15
+ dep == other.dep && __platform == other.__platform
16
+ end
17
+
18
+ alias_method :eql?, :==
19
+
20
+ def type
21
+ @dep.type
22
+ end
23
+
24
+ def name
25
+ @dep.name
26
+ end
27
+
28
+ def requirement
29
+ @dep.requirement
30
+ end
31
+
32
+ def to_s
33
+ s = name.dup
34
+ s << " (#{requirement})" unless requirement == Gem::Requirement.default
35
+ s << " #{__platform}" unless __platform == Gem::Platform::RUBY
36
+ s
37
+ end
38
+
39
+ private
40
+
41
+ def method_missing(*args, &blk)
42
+ @dep.send(*args, &blk)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,119 @@
1
+ require "rubygems/dependency"
2
+ require "bundler/shared_helpers"
3
+ require "bundler/rubygems_ext"
4
+
5
+ module Bundler
6
+ class Dependency < Gem::Dependency
7
+ attr_reader :autorequire
8
+ attr_reader :groups
9
+ attr_reader :platforms
10
+
11
+ PLATFORM_MAP = {
12
+ :ruby => Gem::Platform::RUBY,
13
+ :ruby_18 => Gem::Platform::RUBY,
14
+ :ruby_19 => Gem::Platform::RUBY,
15
+ :ruby_20 => Gem::Platform::RUBY,
16
+ :ruby_21 => Gem::Platform::RUBY,
17
+ :ruby_22 => Gem::Platform::RUBY,
18
+ :ruby_23 => Gem::Platform::RUBY,
19
+ :mri => Gem::Platform::RUBY,
20
+ :mri_18 => Gem::Platform::RUBY,
21
+ :mri_19 => Gem::Platform::RUBY,
22
+ :mri_20 => Gem::Platform::RUBY,
23
+ :mri_21 => Gem::Platform::RUBY,
24
+ :mri_22 => Gem::Platform::RUBY,
25
+ :mri_23 => Gem::Platform::RUBY,
26
+ :rbx => Gem::Platform::RUBY,
27
+ :jruby => Gem::Platform::JAVA,
28
+ :jruby_18 => Gem::Platform::JAVA,
29
+ :jruby_19 => Gem::Platform::JAVA,
30
+ :mswin => Gem::Platform::MSWIN,
31
+ :mswin_18 => Gem::Platform::MSWIN,
32
+ :mswin_19 => Gem::Platform::MSWIN,
33
+ :mswin_20 => Gem::Platform::MSWIN,
34
+ :mswin_21 => Gem::Platform::MSWIN,
35
+ :mswin_22 => Gem::Platform::MSWIN,
36
+ :mswin_23 => Gem::Platform::MSWIN,
37
+ :mswin64 => Gem::Platform::MSWIN64,
38
+ :mswin64_19 => Gem::Platform::MSWIN64,
39
+ :mswin64_20 => Gem::Platform::MSWIN64,
40
+ :mswin64_21 => Gem::Platform::MSWIN64,
41
+ :mswin64_22 => Gem::Platform::MSWIN64,
42
+ :mswin64_23 => Gem::Platform::MSWIN64,
43
+ :mingw => Gem::Platform::MINGW,
44
+ :mingw_18 => Gem::Platform::MINGW,
45
+ :mingw_19 => Gem::Platform::MINGW,
46
+ :mingw_20 => Gem::Platform::MINGW,
47
+ :mingw_21 => Gem::Platform::MINGW,
48
+ :mingw_22 => Gem::Platform::MINGW,
49
+ :mingw_23 => Gem::Platform::MINGW,
50
+ :x64_mingw => Gem::Platform::X64_MINGW,
51
+ :x64_mingw_20 => Gem::Platform::X64_MINGW,
52
+ :x64_mingw_21 => Gem::Platform::X64_MINGW,
53
+ :x64_mingw_22 => Gem::Platform::X64_MINGW,
54
+ :x64_mingw_23 => Gem::Platform::X64_MINGW
55
+ }.freeze
56
+
57
+ def initialize(name, version, options = {}, &blk)
58
+ type = options["type"] || :runtime
59
+ super(name, version, type)
60
+
61
+ @autorequire = nil
62
+ @groups = Array(options["group"] || :default).map(&:to_sym)
63
+ @source = options["source"]
64
+ @platforms = Array(options["platforms"])
65
+ @env = options["env"]
66
+ @should_include = options.fetch("should_include", true)
67
+
68
+ if options.key?("require")
69
+ @autorequire = Array(options["require"] || [])
70
+ end
71
+ end
72
+
73
+ def gem_platforms(valid_platforms)
74
+ return valid_platforms if @platforms.empty?
75
+
76
+ platforms = []
77
+ @platforms.each do |p|
78
+ platform = PLATFORM_MAP[p]
79
+ next unless valid_platforms.include?(platform)
80
+ platforms |= [platform]
81
+ end
82
+ platforms
83
+ end
84
+
85
+ def should_include?
86
+ @should_include && current_env? && current_platform?
87
+ end
88
+
89
+ def current_env?
90
+ return true unless @env
91
+ if @env.is_a?(Hash)
92
+ @env.all? do |key, val|
93
+ ENV[key.to_s] && (val.is_a?(String) ? ENV[key.to_s] == val : ENV[key.to_s] =~ val)
94
+ end
95
+ else
96
+ ENV[@env.to_s]
97
+ end
98
+ end
99
+
100
+ def current_platform?
101
+ return true if @platforms.empty?
102
+ @platforms.any? { |p|
103
+ Bundler.current_ruby.send("#{p}?")
104
+ }
105
+ end
106
+
107
+ def to_lock
108
+ out = super
109
+ out << "!" if source
110
+ out << "\n"
111
+ end
112
+
113
+ def specific?
114
+ super
115
+ rescue NoMethodError
116
+ requirement != ">= 0"
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,62 @@
1
+ module Bundler
2
+ class Deployment
3
+ def self.define_task(context, task_method = :task, opts = {})
4
+ if defined?(Capistrano) && context.is_a?(Capistrano::Configuration)
5
+ context_name = "capistrano"
6
+ role_default = "{:except => {:no_release => true}}"
7
+ error_type = ::Capistrano::CommandError
8
+ else
9
+ context_name = "vlad"
10
+ role_default = "[:app]"
11
+ error_type = ::Rake::CommandFailedError
12
+ end
13
+
14
+ roles = context.fetch(:bundle_roles, false)
15
+ opts[:roles] = roles if roles
16
+
17
+ context.send :namespace, :bundle do
18
+ send :desc, <<-DESC
19
+ Install the current Bundler environment. By default, gems will be \
20
+ installed to the shared/bundle path. Gems in the development and \
21
+ test group will not be installed. The install command is executed \
22
+ with the --deployment and --quiet flags. If the bundle cmd cannot \
23
+ be found then you can override the bundle_cmd variable to specify \
24
+ which one it should use. The base path to the app is fetched from \
25
+ the :latest_release variable. Set it for custom deploy layouts.
26
+
27
+ You can override any of these defaults by setting the variables shown below.
28
+
29
+ N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \
30
+ in your deploy.rb file.
31
+
32
+ set :bundle_gemfile, "Gemfile"
33
+ set :bundle_dir, File.join(fetch(:shared_path), 'bundle')
34
+ set :bundle_flags, "--deployment --quiet"
35
+ set :bundle_without, [:development, :test]
36
+ set :bundle_with, [:mysql]
37
+ set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle"
38
+ set :bundle_roles, #{role_default} # e.g. [:app, :batch]
39
+ DESC
40
+ send task_method, :install, opts do
41
+ bundle_cmd = context.fetch(:bundle_cmd, "bundle")
42
+ bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet")
43
+ bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), "bundle"))
44
+ bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile")
45
+ bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact
46
+ bundle_with = [*context.fetch(:bundle_with, [])].compact
47
+ app_path = context.fetch(:latest_release)
48
+ if app_path.to_s.empty?
49
+ raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.")
50
+ end
51
+ args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"]
52
+ args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty?
53
+ args << bundle_flags.to_s
54
+ args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty?
55
+ args << "--with #{bundle_with.join(" ")}" unless bundle_with.empty?
56
+
57
+ run "cd #{app_path} && #{bundle_cmd} install #{args.join(" ")}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,17 @@
1
+ module Bundler
2
+
3
+ if defined? ::Deprecate
4
+ Deprecate = ::Deprecate
5
+ elsif defined? Gem::Deprecate
6
+ Deprecate = Gem::Deprecate
7
+ else
8
+ class Deprecate; end
9
+ end
10
+
11
+ unless Deprecate.respond_to?(:skip_during)
12
+ def Deprecate.skip_during
13
+ yield
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,478 @@
1
+ require "bundler/dependency"
2
+ require "bundler/ruby_dsl"
3
+
4
+ module Bundler
5
+ class Dsl
6
+ include RubyDsl
7
+
8
+ def self.evaluate(gemfile, lockfile, unlock)
9
+ builder = new
10
+ builder.eval_gemfile(gemfile)
11
+ builder.to_definition(lockfile, unlock)
12
+ end
13
+
14
+ VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
15
+
16
+ attr_reader :gemspecs
17
+ attr_accessor :dependencies
18
+
19
+ def initialize
20
+ @source = nil
21
+ @sources = SourceList.new
22
+ @git_sources = {}
23
+ @dependencies = []
24
+ @groups = []
25
+ @install_conditionals = []
26
+ @optional_groups = []
27
+ @platforms = []
28
+ @env = nil
29
+ @ruby_version = nil
30
+ @gemspecs = []
31
+ add_git_sources
32
+ end
33
+
34
+ def eval_gemfile(gemfile, contents = nil)
35
+ contents ||= Bundler.read_file(gemfile.to_s)
36
+ instance_eval(contents, gemfile.to_s, 1)
37
+ rescue Exception => e
38
+ message = "There was an error " \
39
+ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
40
+ "`#{File.basename gemfile.to_s}`: #{e.message}"
41
+
42
+ raise DSLError.new(message, gemfile, e.backtrace, contents)
43
+ end
44
+
45
+ def gemspec(opts = nil)
46
+ path = opts && opts[:path] || "."
47
+ glob = opts && opts[:glob]
48
+ name = opts && opts[:name] || "{,*}"
49
+ development_group = opts && opts[:development_group] || :development
50
+ expanded_path = File.expand_path(path, Bundler.default_gemfile.dirname)
51
+
52
+ gemspecs = Dir[File.join(expanded_path, "#{name}.gemspec")]
53
+
54
+ case gemspecs.size
55
+ when 1
56
+ spec = Bundler.load_gemspec(gemspecs.first)
57
+
58
+ unless spec
59
+ raise InvalidOption, "There was an error loading the gemspec at " \
60
+ "#{file}. Make sure you can build the gem, then try again."
61
+ end
62
+
63
+ gem spec.name, :path => path, :glob => glob
64
+
65
+ group(development_group) do
66
+ spec.development_dependencies.each do |dep|
67
+ gem dep.name, *(dep.requirement.as_list + [:type => :development])
68
+ end
69
+ end
70
+
71
+ @gemspecs << gemspecs.first
72
+ when 0
73
+ raise InvalidOption, "There are no gemspecs at #{expanded_path}."
74
+ else
75
+ raise InvalidOption, "There are multiple gemspecs at #{expanded_path}. " \
76
+ "Please use the :name option to specify which one should be used."
77
+ end
78
+ end
79
+
80
+ def gem(name, *args)
81
+ options = args.last.is_a?(Hash) ? args.pop.dup : {}
82
+ version = args || [">= 0"]
83
+
84
+ normalize_options(name, version, options)
85
+
86
+ dep = Dependency.new(name, version, options)
87
+
88
+ # if there's already a dependency with this name we try to prefer one
89
+ if current = @dependencies.find {|d| d.name == dep.name }
90
+ if current.requirement != dep.requirement
91
+ if current.type == :development
92
+ @dependencies.delete current
93
+ elsif dep.type == :development
94
+ return
95
+ else
96
+ raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
97
+ "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})"
98
+ end
99
+
100
+ else
101
+ Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
102
+ "You should probably keep only one of them.\n" \
103
+ "While it's not a problem now, it could cause errors if you change the version of just one of them later."
104
+ end
105
+
106
+ if current.source != dep.source
107
+ if current.type == :development
108
+ @dependencies.delete current
109
+ elsif dep.type == :development
110
+ return
111
+ else
112
+ raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
113
+ "You specified that #{dep.name} (#{dep.requirement}) should come from " \
114
+ "#{current.source || "an unspecified source"} and #{dep.source}\n"
115
+ end
116
+ end
117
+ end
118
+
119
+ @dependencies << dep
120
+ end
121
+
122
+ def source(source, &blk)
123
+ source = normalize_source(source)
124
+ if block_given?
125
+ with_source(@sources.add_rubygems_source("remotes" => source), &blk)
126
+ else
127
+ check_primary_source_safety(@sources)
128
+ @sources.add_rubygems_remote(source)
129
+ end
130
+ end
131
+
132
+ def git_source(name, &block)
133
+ unless block_given?
134
+ raise InvalidOption, "You need to pass a block to #git_source"
135
+ end
136
+
137
+ if valid_keys.include?(name.to_s)
138
+ raise InvalidOption, "You cannot use #{name} as a git source. It " \
139
+ "is a reserved key. Reserved keys are: #{valid_keys.join(", ")}"
140
+ end
141
+
142
+ @git_sources[name.to_s] = block
143
+ end
144
+
145
+ def path(path, options = {}, &blk)
146
+ with_source(@sources.add_path_source(normalize_hash(options).merge("path" => Pathname.new(path))), &blk)
147
+ end
148
+
149
+ def git(uri, options = {}, &blk)
150
+ unless block_given?
151
+ msg = "You can no longer specify a git source by itself. Instead, \n" \
152
+ "either use the :git option on a gem, or specify the gems that \n" \
153
+ "bundler should find in the git source by passing a block to \n" \
154
+ "the git method, like: \n\n" \
155
+ " git 'git://github.com/rails/rails.git' do\n" \
156
+ " gem 'rails'\n" \
157
+ " end"
158
+ raise DeprecatedError, msg
159
+ end
160
+
161
+ with_source(@sources.add_git_source(normalize_hash(options).merge("uri" => uri)), &blk)
162
+ end
163
+
164
+ def github(repo, options = {})
165
+ raise ArgumentError, "Github sources require a block" unless block_given?
166
+ github_uri = @git_sources["github"].call(repo)
167
+ git_options = normalize_hash(options).merge("uri" => github_uri)
168
+ git_source = @sources.add_git_source(git_options)
169
+ with_source(git_source) { yield }
170
+ end
171
+
172
+ def to_definition(lockfile, unlock)
173
+ Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups)
174
+ end
175
+
176
+ def group(*args, &blk)
177
+ opts = Hash === args.last ? args.pop.dup : {}
178
+ normalize_group_options(opts, args)
179
+
180
+ @groups.concat args
181
+
182
+ if opts["optional"]
183
+ optional_groups = args - @optional_groups
184
+ @optional_groups.concat optional_groups
185
+ end
186
+
187
+ yield
188
+ ensure
189
+ args.each { @groups.pop }
190
+ end
191
+
192
+ def install_if(*args, &blk)
193
+ @install_conditionals.concat args
194
+ blk.call
195
+ ensure
196
+ args.each { @install_conditionals.pop }
197
+ end
198
+
199
+ def platforms(*platforms)
200
+ @platforms.concat platforms
201
+ yield
202
+ ensure
203
+ platforms.each { @platforms.pop }
204
+ end
205
+ alias_method :platform, :platforms
206
+
207
+ def env(name)
208
+ @env, old = name, @env
209
+ yield
210
+ ensure
211
+ @env = old
212
+ end
213
+
214
+ def method_missing(name, *args)
215
+ raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
216
+ end
217
+
218
+ private
219
+
220
+ def add_git_sources
221
+ git_source(:github) do |repo_name|
222
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
223
+ "git://github.com/#{repo_name}.git"
224
+ end
225
+
226
+ git_source(:gist) {|repo_name| "https://gist.github.com/#{repo_name}.git" }
227
+
228
+ git_source(:bitbucket) do |repo_name|
229
+ user_name, repo_name = repo_name.split "/"
230
+ repo_name ||= user_name
231
+ "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
232
+ end
233
+ end
234
+
235
+ def with_source(source)
236
+ old_source = @source
237
+ if block_given?
238
+ @source = source
239
+ yield
240
+ end
241
+ source
242
+ ensure
243
+ @source = old_source
244
+ end
245
+
246
+ def normalize_hash(opts)
247
+ opts.keys.each do |k|
248
+ opts[k.to_s] = opts.delete(k) unless k.is_a?(String)
249
+ end
250
+ opts
251
+ end
252
+
253
+ def valid_keys
254
+ @valid_keys ||= %w(group groups git path glob name branch ref tag require submodules platform platforms type source install_if)
255
+ end
256
+
257
+ def normalize_options(name, version, opts)
258
+ if name.is_a?(Symbol)
259
+ raise GemfileError, %{You need to specify gem names as Strings. Use 'gem "#{name}"' instead.}
260
+ end
261
+ if name =~ /\s/
262
+ raise GemfileError, %{'#{name}' is not a valid gem name because it contains whitespace.}
263
+ end
264
+
265
+ normalize_hash(opts)
266
+
267
+ git_names = @git_sources.keys.map(&:to_s)
268
+ validate_keys("gem '#{name}'", opts, valid_keys + git_names)
269
+
270
+ groups = @groups.dup
271
+ opts["group"] = opts.delete("groups") || opts["group"]
272
+ groups.concat Array(opts.delete("group"))
273
+ groups = [:default] if groups.empty?
274
+
275
+ install_if = @install_conditionals.dup
276
+ install_if.concat Array(opts.delete("install_if"))
277
+ install_if = install_if.reduce(true) do |memo, val|
278
+ memo && (val.respond_to?(:call) ? val.call : val)
279
+ end
280
+
281
+ platforms = @platforms.dup
282
+ opts["platforms"] = opts["platform"] || opts["platforms"]
283
+ platforms.concat Array(opts.delete("platforms"))
284
+ platforms.map!(&:to_sym)
285
+ platforms.each do |p|
286
+ next if VALID_PLATFORMS.include?(p)
287
+ raise GemfileError, "`#{p}` is not a valid platform. The available options are: #{VALID_PLATFORMS.inspect}"
288
+ end
289
+
290
+ # Save sources passed in a key
291
+ if opts.key?("source")
292
+ source = normalize_source(opts["source"])
293
+ opts["source"] = @sources.add_rubygems_source("remotes" => source)
294
+ end
295
+
296
+ git_name = (git_names & opts.keys).last
297
+ if @git_sources[git_name]
298
+ opts["git"] = @git_sources[git_name].call(opts[git_name])
299
+ end
300
+
301
+ %w[git path].each do |type|
302
+ if param = opts[type]
303
+ if version.first && version.first =~ /^\s*=?\s*(\d[^\s]*)\s*$/
304
+ options = opts.merge("name" => name, "version" => $1)
305
+ else
306
+ options = opts.dup
307
+ end
308
+ source = send(type, param, options) {}
309
+ opts["source"] = source
310
+ end
311
+ end
312
+
313
+ opts["source"] ||= @source
314
+ opts["env"] ||= @env
315
+ opts["platforms"] = platforms.dup
316
+ opts["group"] = groups
317
+ opts["should_include"] = install_if
318
+ end
319
+
320
+ def normalize_group_options(opts, groups)
321
+ normalize_hash(opts)
322
+
323
+ groups = groups.map {|group| ":#{group}" }.join(", ")
324
+ validate_keys("group #{groups}", opts, %w(optional))
325
+
326
+ opts["optional"] ||= false
327
+ end
328
+
329
+ def validate_keys(command, opts, valid_keys)
330
+ invalid_keys = opts.keys - valid_keys
331
+ if invalid_keys.any?
332
+ message = "You passed #{invalid_keys.map {|k| ":" + k }.join(", ")} "
333
+ message << if invalid_keys.size > 1
334
+ "as options for #{command}, but they are invalid."
335
+ else
336
+ "as an option for #{command}, but it is invalid."
337
+ end
338
+
339
+ message << " Valid options are: #{valid_keys.join(", ")}"
340
+ raise InvalidOption, message
341
+ end
342
+ end
343
+
344
+ def normalize_source(source)
345
+ case source
346
+ when :gemcutter, :rubygems, :rubyforge
347
+ Bundler.ui.warn "The source :#{source} is deprecated because HTTP " \
348
+ "requests are insecure.\nPlease change your source to 'https://" \
349
+ "rubygems.org' if possible, or 'http://rubygems.org' if not."
350
+ "http://rubygems.org"
351
+ when String
352
+ source
353
+ else
354
+ raise GemfileError, "Unknown source '#{source}'"
355
+ end
356
+ end
357
+
358
+ def check_primary_source_safety(source)
359
+ return unless source.rubygems_primary_remotes.any?
360
+
361
+ if Bundler.settings[:disable_multisource]
362
+ raise GemspecError, "Warning: this Gemfile contains multiple primary sources. " \
363
+ "Each source after the first must include a block to indicate which gems " \
364
+ "should come from that source. To downgrade this error to a warning, run " \
365
+ "`bundle config --delete disable_multisource`."
366
+ else
367
+ Bundler.ui.warn "Warning: this Gemfile contains multiple primary sources. " \
368
+ "Using `source` more than once without a block is a security risk, and " \
369
+ "may result in installing unexpected gems. To resolve this warning, use " \
370
+ "a block to indicate which gems should come from the secondary source. " \
371
+ "To upgrade this warning to an error, run `bundle config " \
372
+ "disable_multisource true`."
373
+ end
374
+ end
375
+
376
+ class DSLError < GemfileError
377
+ # @return [String] the description that should be presented to the user.
378
+ #
379
+ attr_reader :description
380
+
381
+ # @return [String] the path of the dsl file that raised the exception.
382
+ #
383
+ attr_reader :dsl_path
384
+
385
+ # @return [Exception] the backtrace of the exception raised by the
386
+ # evaluation of the dsl file.
387
+ #
388
+ attr_reader :backtrace
389
+
390
+ # @param [Exception] backtrace @see backtrace
391
+ # @param [String] dsl_path @see dsl_path
392
+ #
393
+ def initialize(description, dsl_path, backtrace, contents = nil)
394
+ @status_code = $!.respond_to?(:status_code) && $!.status_code
395
+
396
+ @description = description
397
+ @dsl_path = dsl_path
398
+ @backtrace = backtrace
399
+ @contents = contents
400
+ end
401
+
402
+ def status_code
403
+ @status_code || super
404
+ end
405
+
406
+ # @return [String] the contents of the DSL that cause the exception to
407
+ # be raised.
408
+ #
409
+ def contents
410
+ @contents ||= begin
411
+ dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
412
+ end
413
+ end
414
+
415
+ # The message of the exception reports the content of podspec for the
416
+ # line that generated the original exception.
417
+ #
418
+ # @example Output
419
+ #
420
+ # Invalid podspec at `RestKit.podspec` - undefined method
421
+ # `exclude_header_search_paths=' for #<Pod::Specification for
422
+ # `RestKit/Network (0.9.3)`>
423
+ #
424
+ # from spec-repos/master/RestKit/0.9.3/RestKit.podspec:36
425
+ # -------------------------------------------
426
+ # # because it would break: #import <CoreData/CoreData.h>
427
+ # > ns.exclude_header_search_paths = 'Code/RestKit.h'
428
+ # end
429
+ # -------------------------------------------
430
+ #
431
+ # @return [String] the message of the exception.
432
+ #
433
+ def to_s
434
+ @to_s ||= begin
435
+ trace_line, description = parse_line_number_from_description
436
+
437
+ m = "\n[!] "
438
+ m << description
439
+ m << ". Bundler cannot continue.\n"
440
+
441
+ return m unless backtrace && dsl_path && contents
442
+
443
+ trace_line = backtrace.find {|l| l.include?(dsl_path.to_s) } || trace_line
444
+ return m unless trace_line
445
+ line_numer = trace_line.split(":")[1].to_i - 1
446
+ return m unless line_numer
447
+
448
+ lines = contents.lines.to_a
449
+ indent = " # "
450
+ indicator = indent.tr('#', ">")
451
+ first_line = (line_numer.zero?)
452
+ last_line = (line_numer == (lines.count - 1))
453
+
454
+ m << "\n"
455
+ m << "#{indent}from #{trace_line.gsub(/:in.*$/, "")}\n"
456
+ m << "#{indent}-------------------------------------------\n"
457
+ m << "#{indent}#{lines[line_numer - 1]}" unless first_line
458
+ m << "#{indicator}#{lines[line_numer]}"
459
+ m << "#{indent}#{lines[line_numer + 1]}" unless last_line
460
+ m << "\n" unless m.end_with?("\n")
461
+ m << "#{indent}-------------------------------------------\n"
462
+ end
463
+ end
464
+
465
+ private
466
+
467
+ def parse_line_number_from_description
468
+ description = self.description
469
+ if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/
470
+ trace_line = Regexp.last_match[1]
471
+ description = description.sub(/#{Regexp.quote trace_line}:\s*/, "").sub("\n", " - ")
472
+ end
473
+ [trace_line, description]
474
+ end
475
+ end
476
+ end
477
+
478
+ end