bundler-prehistoric 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (284) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +100 -0
  5. data/CHANGELOG.md +1640 -0
  6. data/CONTRIBUTING.md +32 -0
  7. data/DEVELOPMENT.md +117 -0
  8. data/Gemfile +3 -0
  9. data/ISSUES.md +96 -0
  10. data/LICENSE.md +23 -0
  11. data/README.md +46 -0
  12. data/Rakefile +256 -0
  13. data/UPGRADING.md +103 -0
  14. data/bin/bundle +21 -0
  15. data/bin/bundle_ruby +56 -0
  16. data/bin/bundler +21 -0
  17. data/bundler.gemspec +33 -0
  18. data/lib/bundler.rb +442 -0
  19. data/lib/bundler/backports/time.rb +7 -0
  20. data/lib/bundler/capistrano.rb +16 -0
  21. data/lib/bundler/cli.rb +395 -0
  22. data/lib/bundler/cli/binstubs.rb +38 -0
  23. data/lib/bundler/cli/cache.rb +34 -0
  24. data/lib/bundler/cli/check.rb +35 -0
  25. data/lib/bundler/cli/clean.rb +19 -0
  26. data/lib/bundler/cli/common.rb +54 -0
  27. data/lib/bundler/cli/config.rb +84 -0
  28. data/lib/bundler/cli/console.rb +39 -0
  29. data/lib/bundler/cli/exec.rb +37 -0
  30. data/lib/bundler/cli/gem.rb +101 -0
  31. data/lib/bundler/cli/init.rb +33 -0
  32. data/lib/bundler/cli/inject.rb +33 -0
  33. data/lib/bundler/cli/install.rb +133 -0
  34. data/lib/bundler/cli/open.rb +23 -0
  35. data/lib/bundler/cli/outdated.rb +80 -0
  36. data/lib/bundler/cli/package.rb +36 -0
  37. data/lib/bundler/cli/platform.rb +43 -0
  38. data/lib/bundler/cli/show.rb +48 -0
  39. data/lib/bundler/cli/update.rb +73 -0
  40. data/lib/bundler/cli/viz.rb +27 -0
  41. data/lib/bundler/constants.rb +5 -0
  42. data/lib/bundler/current_ruby.rb +155 -0
  43. data/lib/bundler/definition.rb +604 -0
  44. data/lib/bundler/dep_proxy.rb +43 -0
  45. data/lib/bundler/dependency.rb +106 -0
  46. data/lib/bundler/deployment.rb +59 -0
  47. data/lib/bundler/deprecate.rb +15 -0
  48. data/lib/bundler/dsl.rb +305 -0
  49. data/lib/bundler/endpoint_specification.rb +76 -0
  50. data/lib/bundler/env.rb +56 -0
  51. data/lib/bundler/environment.rb +42 -0
  52. data/lib/bundler/fetcher.rb +396 -0
  53. data/lib/bundler/friendly_errors.rb +42 -0
  54. data/lib/bundler/gem_helper.rb +169 -0
  55. data/lib/bundler/gem_helpers.rb +25 -0
  56. data/lib/bundler/gem_installer.rb +9 -0
  57. data/lib/bundler/gem_path_manipulation.rb +8 -0
  58. data/lib/bundler/gem_tasks.rb +2 -0
  59. data/lib/bundler/graph.rb +169 -0
  60. data/lib/bundler/index.rb +184 -0
  61. data/lib/bundler/injector.rb +64 -0
  62. data/lib/bundler/installer.rb +332 -0
  63. data/lib/bundler/lazy_specification.rb +83 -0
  64. data/lib/bundler/lockfile_parser.rb +146 -0
  65. data/lib/bundler/match_platform.rb +13 -0
  66. data/lib/bundler/parallel_workers.rb +18 -0
  67. data/lib/bundler/parallel_workers/thread_worker.rb +30 -0
  68. data/lib/bundler/parallel_workers/unix_worker.rb +101 -0
  69. data/lib/bundler/parallel_workers/worker.rb +69 -0
  70. data/lib/bundler/psyched_yaml.rb +26 -0
  71. data/lib/bundler/remote_specification.rb +57 -0
  72. data/lib/bundler/resolver.rb +534 -0
  73. data/lib/bundler/retry.rb +60 -0
  74. data/lib/bundler/ruby_dsl.rb +11 -0
  75. data/lib/bundler/ruby_version.rb +117 -0
  76. data/lib/bundler/rubygems_ext.rb +171 -0
  77. data/lib/bundler/rubygems_integration.rb +578 -0
  78. data/lib/bundler/runtime.rb +310 -0
  79. data/lib/bundler/settings.rb +176 -0
  80. data/lib/bundler/setup.rb +23 -0
  81. data/lib/bundler/shared_helpers.rb +110 -0
  82. data/lib/bundler/similarity_detector.rb +63 -0
  83. data/lib/bundler/source.rb +29 -0
  84. data/lib/bundler/source/git.rb +289 -0
  85. data/lib/bundler/source/git/git_proxy.rb +158 -0
  86. data/lib/bundler/source/path.rb +225 -0
  87. data/lib/bundler/source/path/installer.rb +38 -0
  88. data/lib/bundler/source/rubygems.rb +334 -0
  89. data/lib/bundler/source/svn.rb +260 -0
  90. data/lib/bundler/source/svn/svn_proxy.rb +110 -0
  91. data/lib/bundler/spec_set.rb +154 -0
  92. data/lib/bundler/ssl_certs/.document +1 -0
  93. data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +14 -0
  94. data/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +23 -0
  95. data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +28 -0
  96. data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +20 -0
  97. data/lib/bundler/ssl_certs/certificate_manager.rb +41 -0
  98. data/lib/bundler/templates/Executable +16 -0
  99. data/lib/bundler/templates/Executable.standalone +12 -0
  100. data/lib/bundler/templates/Gemfile +4 -0
  101. data/lib/bundler/templates/newgem/.travis.yml.tt +3 -0
  102. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  103. data/lib/bundler/templates/newgem/LICENSE.txt.tt +22 -0
  104. data/lib/bundler/templates/newgem/README.md.tt +31 -0
  105. data/lib/bundler/templates/newgem/Rakefile.tt +26 -0
  106. data/lib/bundler/templates/newgem/bin/newgem.tt +3 -0
  107. data/lib/bundler/templates/newgem/consolerc.tt +3 -0
  108. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
  109. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  110. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  111. data/lib/bundler/templates/newgem/gitignore.tt +16 -0
  112. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +12 -0
  113. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  114. data/lib/bundler/templates/newgem/newgem.gemspec.tt +38 -0
  115. data/lib/bundler/templates/newgem/rspec.tt +2 -0
  116. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +11 -0
  117. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -0
  118. data/lib/bundler/templates/newgem/test/minitest_helper.rb.tt +4 -0
  119. data/lib/bundler/templates/newgem/test/test_newgem.rb.tt +11 -0
  120. data/lib/bundler/ui.rb +7 -0
  121. data/lib/bundler/ui/rg_proxy.rb +21 -0
  122. data/lib/bundler/ui/shell.rb +98 -0
  123. data/lib/bundler/ui/silent.rb +44 -0
  124. data/lib/bundler/vendor/.document +0 -0
  125. data/lib/bundler/vendor/net/http/faster.rb +26 -0
  126. data/lib/bundler/vendor/net/http/persistent.rb +1230 -0
  127. data/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb +128 -0
  128. data/lib/bundler/vendor/thor.rb +480 -0
  129. data/lib/bundler/vendor/thor/actions.rb +319 -0
  130. data/lib/bundler/vendor/thor/actions/create_file.rb +103 -0
  131. data/lib/bundler/vendor/thor/actions/create_link.rb +59 -0
  132. data/lib/bundler/vendor/thor/actions/directory.rb +118 -0
  133. data/lib/bundler/vendor/thor/actions/empty_directory.rb +135 -0
  134. data/lib/bundler/vendor/thor/actions/file_manipulation.rb +316 -0
  135. data/lib/bundler/vendor/thor/actions/inject_into_file.rb +107 -0
  136. data/lib/bundler/vendor/thor/base.rb +656 -0
  137. data/lib/bundler/vendor/thor/command.rb +133 -0
  138. data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +77 -0
  139. data/lib/bundler/vendor/thor/core_ext/io_binary_read.rb +10 -0
  140. data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +98 -0
  141. data/lib/bundler/vendor/thor/error.rb +32 -0
  142. data/lib/bundler/vendor/thor/group.rb +281 -0
  143. data/lib/bundler/vendor/thor/invocation.rb +173 -0
  144. data/lib/bundler/vendor/thor/line_editor.rb +17 -0
  145. data/lib/bundler/vendor/thor/line_editor/basic.rb +35 -0
  146. data/lib/bundler/vendor/thor/line_editor/readline.rb +88 -0
  147. data/lib/bundler/vendor/thor/parser.rb +4 -0
  148. data/lib/bundler/vendor/thor/parser/argument.rb +73 -0
  149. data/lib/bundler/vendor/thor/parser/arguments.rb +175 -0
  150. data/lib/bundler/vendor/thor/parser/option.rb +121 -0
  151. data/lib/bundler/vendor/thor/parser/options.rb +218 -0
  152. data/lib/bundler/vendor/thor/rake_compat.rb +71 -0
  153. data/lib/bundler/vendor/thor/runner.rb +322 -0
  154. data/lib/bundler/vendor/thor/shell.rb +81 -0
  155. data/lib/bundler/vendor/thor/shell/basic.rb +420 -0
  156. data/lib/bundler/vendor/thor/shell/color.rb +149 -0
  157. data/lib/bundler/vendor/thor/shell/html.rb +126 -0
  158. data/lib/bundler/vendor/thor/util.rb +267 -0
  159. data/lib/bundler/vendor/thor/version.rb +3 -0
  160. data/lib/bundler/vendored_persistent.rb +3 -0
  161. data/lib/bundler/vendored_thor.rb +8 -0
  162. data/lib/bundler/version.rb +6 -0
  163. data/lib/bundler/vlad.rb +11 -0
  164. data/man/bundle-config.ronn +155 -0
  165. data/man/bundle-exec.ronn +136 -0
  166. data/man/bundle-install.ronn +372 -0
  167. data/man/bundle-package.ronn +59 -0
  168. data/man/bundle-platform.ronn +42 -0
  169. data/man/bundle-update.ronn +179 -0
  170. data/man/bundle.ronn +92 -0
  171. data/man/gemfile.5.ronn +369 -0
  172. data/man/index.txt +7 -0
  173. data/spec/bundler/bundler_spec.rb +74 -0
  174. data/spec/bundler/cli_spec.rb +16 -0
  175. data/spec/bundler/definition_spec.rb +21 -0
  176. data/spec/bundler/dsl_spec.rb +108 -0
  177. data/spec/bundler/friendly_errors_spec.rb +13 -0
  178. data/spec/bundler/gem_helper_spec.rb +225 -0
  179. data/spec/bundler/psyched_yaml_spec.rb +8 -0
  180. data/spec/bundler/retry_spec.rb +59 -0
  181. data/spec/bundler/settings_spec.rb +13 -0
  182. data/spec/bundler/source_spec.rb +25 -0
  183. data/spec/cache/gems_spec.rb +316 -0
  184. data/spec/cache/git_spec.rb +188 -0
  185. data/spec/cache/path_spec.rb +121 -0
  186. data/spec/cache/platform_spec.rb +53 -0
  187. data/spec/cache/svn_spec.rb +82 -0
  188. data/spec/commands/binstubs_spec.rb +246 -0
  189. data/spec/commands/check_spec.rb +278 -0
  190. data/spec/commands/clean_spec.rb +652 -0
  191. data/spec/commands/config_spec.rb +227 -0
  192. data/spec/commands/console_spec.rb +102 -0
  193. data/spec/commands/exec_spec.rb +367 -0
  194. data/spec/commands/help_spec.rb +39 -0
  195. data/spec/commands/init_spec.rb +39 -0
  196. data/spec/commands/inject_spec.rb +78 -0
  197. data/spec/commands/licenses_spec.rb +31 -0
  198. data/spec/commands/newgem_spec.rb +451 -0
  199. data/spec/commands/open_spec.rb +80 -0
  200. data/spec/commands/outdated_spec.rb +168 -0
  201. data/spec/commands/package_spec.rb +128 -0
  202. data/spec/commands/show_spec.rb +152 -0
  203. data/spec/install/binstubs_spec.rb +24 -0
  204. data/spec/install/bundler_spec.rb +146 -0
  205. data/spec/install/deploy_spec.rb +237 -0
  206. data/spec/install/gemfile/gemspec_spec.rb +170 -0
  207. data/spec/install/gemfile/git_spec.rb +967 -0
  208. data/spec/install/gemfile/path_spec.rb +480 -0
  209. data/spec/install/gemfile/svn_spec.rb +582 -0
  210. data/spec/install/gemfile_spec.rb +44 -0
  211. data/spec/install/gems/c_ext_spec.rb +48 -0
  212. data/spec/install/gems/dependency_api_spec.rb +580 -0
  213. data/spec/install/gems/env_spec.rb +107 -0
  214. data/spec/install/gems/flex_spec.rb +314 -0
  215. data/spec/install/gems/groups_spec.rb +308 -0
  216. data/spec/install/gems/mirror_spec.rb +39 -0
  217. data/spec/install/gems/platform_spec.rb +221 -0
  218. data/spec/install/gems/post_install_spec.rb +121 -0
  219. data/spec/install/gems/resolving_spec.rb +124 -0
  220. data/spec/install/gems/simple_case_spec.rb +386 -0
  221. data/spec/install/gems/standalone_spec.rb +260 -0
  222. data/spec/install/gems/sudo_spec.rb +136 -0
  223. data/spec/install/gems/win32_spec.rb +26 -0
  224. data/spec/install/gemspecs_spec.rb +50 -0
  225. data/spec/install/path_spec.rb +150 -0
  226. data/spec/install/post_bundle_message_spec.rb +142 -0
  227. data/spec/install/prereleases_spec.rb +43 -0
  228. data/spec/install/security_policy_spec.rb +77 -0
  229. data/spec/install/upgrade_spec.rb +26 -0
  230. data/spec/lock/git_spec.rb +34 -0
  231. data/spec/lock/lockfile_spec.rb +912 -0
  232. data/spec/lock/svn_spec.rb +35 -0
  233. data/spec/other/bundle_ruby_spec.rb +142 -0
  234. data/spec/other/cli_dispatch_spec.rb +21 -0
  235. data/spec/other/ext_spec.rb +60 -0
  236. data/spec/other/platform_spec.rb +1285 -0
  237. data/spec/other/ssl_cert_spec.rb +10 -0
  238. data/spec/quality_spec.rb +88 -0
  239. data/spec/realworld/dependency_api_spec.rb +60 -0
  240. data/spec/realworld/edgecases_spec.rb +177 -0
  241. data/spec/realworld/parallel_spec.rb +69 -0
  242. data/spec/resolver/basic_spec.rb +66 -0
  243. data/spec/resolver/platform_spec.rb +88 -0
  244. data/spec/runtime/executable_spec.rb +149 -0
  245. data/spec/runtime/load_spec.rb +107 -0
  246. data/spec/runtime/platform_spec.rb +90 -0
  247. data/spec/runtime/require_spec.rb +332 -0
  248. data/spec/runtime/setup_spec.rb +856 -0
  249. data/spec/runtime/with_clean_env_spec.rb +91 -0
  250. data/spec/spec_helper.rb +114 -0
  251. data/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb +13 -0
  252. data/spec/support/artifice/endpoint.rb +71 -0
  253. data/spec/support/artifice/endpoint_500.rb +37 -0
  254. data/spec/support/artifice/endpoint_api_missing.rb +16 -0
  255. data/spec/support/artifice/endpoint_basic_authentication.rb +13 -0
  256. data/spec/support/artifice/endpoint_creds_diff_host.rb +38 -0
  257. data/spec/support/artifice/endpoint_extra.rb +31 -0
  258. data/spec/support/artifice/endpoint_extra_missing.rb +15 -0
  259. data/spec/support/artifice/endpoint_fallback.rb +17 -0
  260. data/spec/support/artifice/endpoint_host_redirect.rb +15 -0
  261. data/spec/support/artifice/endpoint_marshal_fail.rb +11 -0
  262. data/spec/support/artifice/endpoint_redirect.rb +15 -0
  263. data/spec/support/artifice/endpoint_strict_basic_authentication.rb +18 -0
  264. data/spec/support/artifice/endpoint_timeout.rb +13 -0
  265. data/spec/support/builders.rb +748 -0
  266. data/spec/support/fakeweb/rack-1.0.0.marshal +2 -0
  267. data/spec/support/fakeweb/windows.rb +23 -0
  268. data/spec/support/hax.rb +22 -0
  269. data/spec/support/helpers.rb +348 -0
  270. data/spec/support/indexes.rb +280 -0
  271. data/spec/support/less_than_proc.rb +14 -0
  272. data/spec/support/matchers.rb +77 -0
  273. data/spec/support/path.rb +81 -0
  274. data/spec/support/permissions.rb +10 -0
  275. data/spec/support/platforms.rb +94 -0
  276. data/spec/support/ruby_ext.rb +20 -0
  277. data/spec/support/rubygems_ext.rb +39 -0
  278. data/spec/support/streams.rb +13 -0
  279. data/spec/support/sudo.rb +16 -0
  280. data/spec/update/gems_spec.rb +201 -0
  281. data/spec/update/git_spec.rb +236 -0
  282. data/spec/update/source_spec.rb +63 -0
  283. data/spec/update/svn_spec.rb +100 -0
  284. metadata +486 -0
@@ -0,0 +1,534 @@
1
+ require 'set'
2
+ # This is the latest iteration of the gem dependency resolving algorithm. As of now,
3
+ # it can resolve (as a success or failure) any set of gem dependencies we throw at it
4
+ # in a reasonable amount of time. The most iterations I've seen it take is about 150.
5
+ # The actual implementation of the algorithm is not as good as it could be yet, but that
6
+ # can come later.
7
+
8
+ # Extending Gem classes to add necessary tracking information
9
+ module Gem
10
+ class Specification
11
+ def required_by
12
+ @required_by ||= []
13
+ end
14
+ end
15
+ class Dependency
16
+ def required_by
17
+ @required_by ||= []
18
+ end
19
+ end
20
+ end
21
+
22
+ module Bundler
23
+ class Resolver
24
+
25
+ ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
26
+
27
+ class SpecGroup < Array
28
+ include GemHelpers
29
+
30
+ attr_reader :activated, :required_by
31
+
32
+ def initialize(a)
33
+ super
34
+ @required_by = []
35
+ @activated = []
36
+ @dependencies = nil
37
+ @specs = {}
38
+
39
+ ALL.each do |p|
40
+ @specs[p] = reverse.find { |s| s.match_platform(p) }
41
+ end
42
+ end
43
+
44
+ def initialize_copy(o)
45
+ super
46
+ @required_by = o.required_by.dup
47
+ @activated = o.activated.dup
48
+ end
49
+
50
+ def to_specs
51
+ specs = {}
52
+
53
+ @activated.each do |p|
54
+ if s = @specs[p]
55
+ platform = generic(Gem::Platform.new(s.platform))
56
+ next if specs[platform]
57
+
58
+ lazy_spec = LazySpecification.new(name, version, platform, source)
59
+ lazy_spec.dependencies.replace s.dependencies
60
+ specs[platform] = lazy_spec
61
+ end
62
+ end
63
+ specs.values
64
+ end
65
+
66
+ def activate_platform(platform)
67
+ unless @activated.include?(platform)
68
+ @activated << platform
69
+ return __dependencies[platform] || []
70
+ end
71
+ []
72
+ end
73
+
74
+ def name
75
+ @name ||= first.name
76
+ end
77
+
78
+ def version
79
+ @version ||= first.version
80
+ end
81
+
82
+ def source
83
+ @source ||= first.source
84
+ end
85
+
86
+ def for?(platform)
87
+ @specs[platform]
88
+ end
89
+
90
+ def to_s
91
+ "#{name} (#{version})"
92
+ end
93
+
94
+ private
95
+
96
+ def __dependencies
97
+ @dependencies ||= begin
98
+ dependencies = {}
99
+ ALL.each do |p|
100
+ if spec = @specs[p]
101
+ dependencies[p] = []
102
+ spec.dependencies.each do |dep|
103
+ next if dep.type == :development
104
+ dependencies[p] << DepProxy.new(dep, p)
105
+ end
106
+ end
107
+ end
108
+ dependencies
109
+ end
110
+ end
111
+ end
112
+
113
+ attr_reader :errors, :started_at, :iteration_rate, :iteration_counter
114
+
115
+ # Figures out the best possible configuration of gems that satisfies
116
+ # the list of passed dependencies and any child dependencies without
117
+ # causing any gem activation errors.
118
+ #
119
+ # ==== Parameters
120
+ # *dependencies<Gem::Dependency>:: The list of dependencies to resolve
121
+ #
122
+ # ==== Returns
123
+ # <GemBundle>,nil:: If the list of dependencies can be resolved, a
124
+ # collection of gemspecs is returned. Otherwise, nil is returned.
125
+ def self.resolve(requirements, index, source_requirements = {}, base = [])
126
+ Bundler.ui.info "Resolving dependencies...", false
127
+ base = SpecSet.new(base) unless base.is_a?(SpecSet)
128
+ resolver = new(index, source_requirements, base)
129
+ result = resolver.start(requirements)
130
+ Bundler.ui.info "" # new line now that dots are done
131
+ SpecSet.new(result)
132
+ rescue => e
133
+ Bundler.ui.info "" # new line before the error
134
+ raise e
135
+ end
136
+
137
+ def initialize(index, source_requirements, base)
138
+ @errors = {}
139
+ @base = base
140
+ @index = index
141
+ @deps_for = {}
142
+ @missing_gems = Hash.new(0)
143
+ @source_requirements = source_requirements
144
+ @iteration_counter = 0
145
+ @started_at = Time.now
146
+ end
147
+
148
+ def debug
149
+ if ENV['DEBUG_RESOLVER']
150
+ debug_info = yield
151
+ debug_info = debug_info.inspect unless debug_info.is_a?(String)
152
+ $stderr.puts debug_info
153
+ end
154
+ end
155
+
156
+ def successify(activated)
157
+ activated.values.map { |s| s.to_specs }.flatten.compact
158
+ end
159
+
160
+ def start(reqs)
161
+ activated = {}
162
+ @gems_size = Hash[reqs.map { |r| [r, gems_size(r)] }]
163
+
164
+ resolve(reqs, activated)
165
+ end
166
+
167
+ class State < Struct.new(:reqs, :activated, :requirement, :possibles, :depth, :conflicts)
168
+ def name
169
+ requirement.name
170
+ end
171
+ end
172
+
173
+ def handle_conflict(current, states, existing=nil)
174
+ until current.nil? && existing.nil?
175
+ current_state = find_state(current, states)
176
+ existing_state = find_state(existing, states)
177
+ return current if state_any?(current_state)
178
+ return existing if state_any?(existing_state)
179
+ existing = existing.required_by.last if existing
180
+ current = current.required_by.last if current
181
+ end
182
+ end
183
+
184
+ def state_any?(state)
185
+ state && state.possibles.any?
186
+ end
187
+
188
+ def find_state(current, states)
189
+ states.detect { |i| current && current.name == i.name }
190
+ end
191
+
192
+ def other_possible?(conflict, states)
193
+ return unless conflict
194
+ state = states.detect { |i| i.name == conflict.name }
195
+ state && state.possibles.any?
196
+ end
197
+
198
+ def find_conflict_state(conflict, states)
199
+ return unless conflict
200
+ until states.empty? do
201
+ state = states.pop
202
+ return state if conflict.name == state.name
203
+ end
204
+ end
205
+
206
+ def activate_gem(reqs, activated, requirement, current)
207
+ requirement.required_by.replace current.required_by
208
+ requirement.required_by << current
209
+ activated[requirement.name] = requirement
210
+
211
+ debug { " Activating: #{requirement.name} (#{requirement.version})" }
212
+ debug { requirement.required_by.map { |d| " * #{d.name} (#{d.requirement})" }.join("\n") }
213
+
214
+ dependencies = requirement.activate_platform(current.__platform)
215
+
216
+ debug { " Dependencies"}
217
+ dependencies.each do |dep|
218
+ next if dep.type == :development
219
+ dep.required_by.replace(current.required_by)
220
+ dep.required_by << current
221
+ @gems_size[dep] ||= gems_size(dep)
222
+ reqs << dep
223
+ end
224
+ end
225
+
226
+ def resolve_for_conflict(state)
227
+ raise version_conflict if state.nil? || state.possibles.empty?
228
+ reqs, activated, depth, conflicts = state.reqs.dup, state.activated.dup, state.depth, state.conflicts.dup
229
+ requirement = state.requirement
230
+ possible = state.possibles.pop
231
+
232
+ activate_gem(reqs, activated, possible, requirement)
233
+
234
+ return reqs, activated, depth, conflicts
235
+ end
236
+
237
+ def resolve_conflict(current, states)
238
+ # Find the state where the conflict has occurred
239
+ state = find_conflict_state(current, states)
240
+
241
+ debug { " -> Going to: #{current.name} state" } if current
242
+
243
+ # Resolve the conflicts by rewinding the state
244
+ # when the conflicted gem was activated
245
+ reqs, activated, depth, conflicts = resolve_for_conflict(state)
246
+
247
+ # Keep the state around if it still has other possibilities
248
+ states << state unless state.possibles.empty?
249
+ clear_search_cache
250
+
251
+ return reqs, activated, depth, conflicts
252
+ end
253
+
254
+ def resolve(reqs, activated)
255
+ states = []
256
+ depth = 0
257
+ conflicts = Set.new
258
+
259
+ until reqs.empty?
260
+
261
+ indicate_progress
262
+
263
+ debug { print "\e[2J\e[f" ; "==== Iterating ====\n\n" }
264
+
265
+ reqs = reqs.sort_by do |a|
266
+ [ activated[a.name] ? 0 : 1,
267
+ a.requirement.prerelease? ? 0 : 1,
268
+ @errors[a.name] ? 0 : 1,
269
+ activated[a.name] ? 0 : @gems_size[a] ]
270
+ end
271
+
272
+ debug { "Activated:\n" + activated.values.map {|a| " #{a}" }.join("\n") }
273
+ debug { "Requirements:\n" + reqs.map {|r| " #{r}"}.join("\n") }
274
+
275
+ current = reqs.shift
276
+
277
+ $stderr.puts "#{' ' * depth}#{current}" if ENV['DEBUG_RESOLVER_TREE']
278
+
279
+ debug { "Attempting:\n #{current}"}
280
+
281
+ existing = activated[current.name]
282
+
283
+
284
+ if existing || current.name == 'bundler'
285
+ # Force the current
286
+ if current.name == 'bundler' && !existing
287
+ existing = search(DepProxy.new(Gem::Dependency.new('bundler', VERSION), Gem::Platform::RUBY)).first
288
+ raise GemNotFound, %Q{Bundler could not find gem "bundler" (#{VERSION})} unless existing
289
+ existing.required_by << existing
290
+ activated['bundler'] = existing
291
+ end
292
+
293
+ if current.requirement.satisfied_by?(existing.version)
294
+ debug { " * [SUCCESS] Already activated" }
295
+ @errors.delete(existing.name)
296
+ dependencies = existing.activate_platform(current.__platform)
297
+ reqs.concat dependencies
298
+
299
+ dependencies.each do |dep|
300
+ next if dep.type == :development
301
+ @gems_size[dep] ||= gems_size(dep)
302
+ end
303
+
304
+ depth += 1
305
+ next
306
+ else
307
+ debug { " * [FAIL] Already activated" }
308
+ @errors[existing.name] = [existing, current]
309
+
310
+ conflicts << current.name
311
+
312
+ parent = current.required_by.last
313
+ if existing.respond_to?(:required_by)
314
+ parent = handle_conflict(current, states, existing.required_by[-2]) unless other_possible?(parent, states)
315
+ else
316
+ parent = handle_conflict(current, states) unless other_possible?(parent, states)
317
+ end
318
+
319
+ if parent.nil? && !conflicts.empty?
320
+ parent = states.reverse.detect { |i| conflicts.include?(i.name) && state_any?(i)}
321
+ end
322
+
323
+ raise version_conflict if parent.nil? || parent.name == 'bundler'
324
+
325
+ reqs, activated, depth, conflicts = resolve_conflict(parent, states)
326
+ end
327
+ else
328
+ matching_versions = search(current)
329
+
330
+ # If we found no versions that match the current requirement
331
+ if matching_versions.empty?
332
+ # If this is a top-level Gemfile requirement
333
+ if current.required_by.empty?
334
+ if base = @base[current.name] and !base.empty?
335
+ version = base.first.version
336
+ message = "You have requested:\n" \
337
+ " #{current.name} #{current.requirement}\n\n" \
338
+ "The bundle currently has #{current.name} locked at #{version}.\n" \
339
+ "Try running `bundle update #{current.name}`"
340
+ elsif current.source
341
+ name = current.name
342
+ versions = @source_requirements[name][name].map { |s| s.version }
343
+ message = "Could not find gem '#{current}' in #{current.source}.\n"
344
+ if versions.any?
345
+ message << "Source contains '#{name}' at: #{versions.join(', ')}"
346
+ else
347
+ message << "Source does not contain any versions of '#{current}'"
348
+ end
349
+ else
350
+ message = "Could not find gem '#{current}' "
351
+ if @index.source_types.include?(Bundler::Source::Rubygems)
352
+ message << "in any of the gem sources listed in your Gemfile."
353
+ else
354
+ message << "in the gems available on this machine."
355
+ end
356
+ end
357
+ raise GemNotFound, message
358
+ # This is not a top-level Gemfile requirement
359
+ else
360
+ @errors[current.name] = [nil, current]
361
+ parent = handle_conflict(current, states)
362
+ reqs, activated, depth = resolve_conflict(parent, states)
363
+ next
364
+ end
365
+ end
366
+
367
+ state = State.new(reqs.dup, activated.dup, current, matching_versions, depth, conflicts)
368
+ states << state
369
+ requirement = state.possibles.pop
370
+ activate_gem(reqs, activated, requirement, current)
371
+ end
372
+ end
373
+ successify(activated)
374
+ end
375
+
376
+ def gems_size(dep)
377
+ search(dep).size
378
+ end
379
+
380
+ def clear_search_cache
381
+ @deps_for = {}
382
+ end
383
+
384
+ def search(dep)
385
+ if base = @base[dep.name] and base.any?
386
+ reqs = [dep.requirement.as_list, base.first.version.to_s].flatten.compact
387
+ d = Gem::Dependency.new(base.first.name, *reqs)
388
+ else
389
+ d = dep.dep
390
+ end
391
+
392
+ @deps_for[d.hash] ||= begin
393
+ index = @source_requirements[d.name] || @index
394
+ results = index.search(d, @base[d.name])
395
+
396
+ if results.any?
397
+ version = results.first.version
398
+ nested = [[]]
399
+ results.each do |spec|
400
+ if spec.version != version
401
+ nested << []
402
+ version = spec.version
403
+ end
404
+ nested.last << spec
405
+ end
406
+ deps = nested.map{|a| SpecGroup.new(a) }.select{|sg| sg.for?(dep.__platform) }
407
+ else
408
+ deps = []
409
+ end
410
+ end
411
+ end
412
+
413
+ def clean_req(req)
414
+ if req.to_s.include?(">= 0")
415
+ req.to_s.gsub(/ \(.*?\)$/, '')
416
+ else
417
+ req.to_s.gsub(/\, (runtime|development)\)$/, ')')
418
+ end
419
+ end
420
+
421
+ def version_conflict
422
+ VersionConflict.new(errors.keys, error_message)
423
+ end
424
+
425
+ # For a given conflicted requirement, print out what exactly went wrong
426
+ def gem_message(requirement, required_by=[])
427
+ m = ""
428
+
429
+ # A requirement that is required by itself is actually in the Gemfile, and does
430
+ # not "depend on" itself
431
+ if requirement.required_by.first && requirement.required_by.first.name != requirement.name
432
+ dependency_tree(m, required_by)
433
+ m << "#{clean_req(requirement)}\n"
434
+ else
435
+ m << " #{clean_req(requirement)}\n"
436
+ end
437
+ m << "\n"
438
+ end
439
+
440
+ def dependency_tree(m, requirements)
441
+ requirements.each_with_index do |i, j|
442
+ m << " " << (" " * j)
443
+ m << "#{clean_req(i)}"
444
+ m << " depends on\n"
445
+ end
446
+ m << " " << (" " * requirements.size)
447
+ end
448
+
449
+ def error_message
450
+ errors.inject("") do |o, (conflict, (origin, requirement))|
451
+
452
+ # origin is the SpecSet of specs from the Gemfile that is conflicted with
453
+ if origin
454
+
455
+ o << %{Bundler could not find compatible versions for gem "#{origin.name}":\n}
456
+ o << " In Gemfile:\n"
457
+
458
+ required_by = requirement.required_by
459
+ o << gem_message(requirement, required_by)
460
+
461
+ # If the origin is "bundler", the conflict is us
462
+ if origin.name == "bundler"
463
+ o << " Current Bundler version:\n"
464
+ other_bundler_required = !requirement.requirement.satisfied_by?(origin.version)
465
+ # If the origin is a LockfileParser, it does not respond_to :required_by
466
+ elsif !origin.respond_to?(:required_by) || !(origin.required_by.first)
467
+ o << " In snapshot (Gemfile.lock):\n"
468
+ end
469
+
470
+ required_by = origin.required_by[0..-2]
471
+ o << gem_message(origin, required_by)
472
+
473
+ # If the bundle wants a newer bundler than the running bundler, explain
474
+ if origin.name == "bundler" && other_bundler_required
475
+ o << "This Gemfile requires a different version of Bundler.\n"
476
+ o << "Perhaps you need to update Bundler by running `gem install bundler`?"
477
+ end
478
+
479
+ # origin is nil if the required gem and version cannot be found in any of
480
+ # the specified sources
481
+ else
482
+
483
+ # if the gem cannot be found because of a version conflict between lockfile and gemfile,
484
+ # print a useful error that suggests running `bundle update`, which may fix things
485
+ #
486
+ # @base is a SpecSet of the gems in the lockfile
487
+ # conflict is the name of the gem that could not be found
488
+ if locked = @base[conflict].first
489
+ o << "Bundler could not find compatible versions for gem #{conflict.inspect}:\n"
490
+ o << " In snapshot (Gemfile.lock):\n"
491
+ o << " #{clean_req(locked)}\n\n"
492
+
493
+ o << " In Gemfile:\n"
494
+
495
+ required_by = requirement.required_by
496
+ o << gem_message(requirement, required_by)
497
+ o << "Running `bundle update` will rebuild your snapshot from scratch, using only\n"
498
+ o << "the gems in your Gemfile, which may resolve the conflict.\n"
499
+
500
+ # the rest of the time, the gem cannot be found because it does not exist in the known sources
501
+ else
502
+ if requirement.required_by.first
503
+ o << "Could not find gem '#{clean_req(requirement)}', which is required by "
504
+ o << "gem '#{clean_req(requirement.required_by.first)}', in any of the sources."
505
+ else
506
+ o << "Could not find gem '#{clean_req(requirement)} in any of the sources\n"
507
+ end
508
+ end
509
+
510
+ end
511
+ o
512
+ end
513
+ end
514
+
515
+ private
516
+
517
+ # Indicates progress by writing a '.' every iteration_rate time which is
518
+ # approximately every second. iteration_rate is calculated in the first
519
+ # second of resolve running.
520
+ def indicate_progress
521
+ @iteration_counter += 1
522
+
523
+ if iteration_rate.nil?
524
+ if ((Time.now - started_at) % 3600).round >= 1
525
+ @iteration_rate = iteration_counter
526
+ end
527
+ else
528
+ if ((iteration_counter % iteration_rate) == 0)
529
+ Bundler.ui.info ".", false
530
+ end
531
+ end
532
+ end
533
+ end
534
+ end