@@ -27,9 +27,12 @@ def self.evaluate(gemfile, lockfile, unlock)
2727 def initialize
2828 @source = nil
2929 @sources = SourceList . new
30+ @plugin_sources = SourceList . new
31+ @current_sources = @sources
3032 @git_sources = { }
3133 @dependencies = [ ]
32- @plugins = [ ]
34+ @plugin_dependencies = [ ]
35+ @current_dependencies = @dependencies
3336 @groups = [ ]
3437 @install_conditionals = [ ]
3538 @optional_groups = [ ]
@@ -98,12 +101,12 @@ def gem(name, *args)
98101 options [ "gemfile" ] = @gemfile
99102 version = args || [ ">= 0" ]
100103
101- normalize_options ( name , version , true , options )
104+ normalize_options ( name , version , options )
102105
103106 dep = Dependency . new ( name , version , options )
104107
105108 # if there's already a dependency with this name we try to prefer one
106- if current = @dependencies . find { |d | d . name == dep . name }
109+ if current = @current_dependencies . find { |d | d . name == dep . name }
107110 if current . requirement != dep . requirement
108111 current_requirement_open = current . requirements_list . include? ( ">= 0" )
109112
@@ -136,7 +139,7 @@ def gem(name, *args)
136139
137140 # Always prefer the dependency from the Gemfile
138141 if current . gemspec_dev_dep?
139- @dependencies . delete ( current )
142+ @current_dependencies . delete ( current )
140143 elsif dep . gemspec_dev_dep?
141144 return
142145 elsif current . source != dep . source
@@ -151,7 +154,7 @@ def gem(name, *args)
151154 end
152155 end
153156
154- @dependencies << dep
157+ @current_dependencies << dep
155158 end
156159
157160 def source ( source , *args , &blk )
@@ -161,20 +164,22 @@ def source(source, *args, &blk)
161164
162165 if options . key? ( "type" )
163166 options [ "type" ] = options [ "type" ] . to_s
164- unless Plugin . source? ( options [ "type" ] )
167+ unless ( source_plugin = Plugin . source_plugin ( options [ "type" ] ) )
165168 raise InvalidOption , "No plugin sources available for #{ options [ "type" ] } "
166169 end
167170
168171 unless block_given?
169172 raise InvalidOption , "You need to pass a block to #source with :type option"
170173 end
171174
175+ plugin ( source_plugin ) unless @plugin_dependencies . any? { |d | d . name == source_plugin }
176+
172177 source_opts = options . merge ( "uri" => source )
173- with_source ( @sources . add_plugin_source ( options [ "type" ] , source_opts ) , &blk )
178+ with_source ( add_source ( :add_plugin_source , options [ "type" ] , source_opts ) , &blk )
174179 elsif block_given?
175- with_source ( @sources . add_rubygems_source ( "remotes" => source ) , &blk )
180+ with_source ( add_source ( :add_rubygems_source , "remotes" => source ) , &blk )
176181 else
177- @sources . add_global_rubygems_remote ( source )
182+ add_source ( :add_global_rubygems_remote , source )
178183 end
179184 end
180185
@@ -200,8 +205,7 @@ def path(path, options = {}, &blk)
200205
201206 source_options [ "global" ] = true unless block_given?
202207
203- source = @sources . add_path_source ( source_options )
204- with_source ( source , &blk )
208+ with_source ( add_source ( :add_path_source , source_options ) , &blk )
205209 end
206210
207211 def git ( uri , options = { } , &blk )
@@ -216,20 +220,29 @@ def git(uri, options = {}, &blk)
216220 raise DeprecatedError , msg
217221 end
218222
219- with_source ( @sources . add_git_source ( normalize_hash ( options ) . merge ( "uri" => uri ) ) , &blk )
223+ options = normalize_hash ( options ) . merge ( "uri" => uri )
224+ with_source ( add_source ( :add_git_source , options ) , &blk )
220225 end
221226
222- def github ( repo , options = { } )
227+ def github ( repo , options = { } , & blk )
223228 raise ArgumentError , "GitHub sources require a block" unless block_given?
224- github_uri = @git_sources [ "github" ] . call ( repo )
225- git_options = normalize_hash ( options ) . merge ( "uri" => github_uri )
226- git_source = @sources . add_git_source ( git_options )
227- with_source ( git_source ) { yield }
229+ github_uri = @git_sources [ "github" ] . call ( repo )
230+ options = normalize_hash ( options ) . merge ( "uri" => github_uri )
231+ with_source ( add_source ( :add_git_source , options ) , &blk )
228232 end
229233
230234 def to_definition ( lockfile , unlock , lockfile_contents : nil )
231235 check_primary_source_safety
232- Definition . new ( lockfile , @dependencies , @sources , unlock , @ruby_version , @optional_groups , @gemfiles , lockfile_contents , @plugins )
236+ Definition . new ( lockfile ,
237+ @dependencies ,
238+ @sources ,
239+ unlock ,
240+ @ruby_version ,
241+ @optional_groups ,
242+ @gemfiles ,
243+ lockfile_contents ,
244+ @plugin_dependencies ,
245+ @plugin_sources )
233246 end
234247
235248 def group ( *args , &blk )
@@ -272,41 +285,12 @@ def env(name)
272285 end
273286
274287 def plugin ( name , *args )
275- options = args . last . is_a? ( Hash ) ? args . pop . dup : { }
276- options [ "gemfile" ] = @gemfile
277- version = args || [ ">= 0" ]
278-
279- # We don't care to add sources for plugins in this pass over the gemfile
280- # since we're not installing plugins here (they should already be
281- # installed), only keeping track of them so that we can verify they
282- # are currently installed. This is important because otherwise sources
283- # unique to the plugin (like a git source) would end up in the lockfile,
284- # which we don't want.
285- normalize_options ( name , version , false , options )
286-
287- dep = Dependency . new ( name , version , options )
288-
289- # if there's already a plugin with this name we try to prefer one
290- if current = @plugins . find { |d | d . name == dep . name }
291- if current . requirement != dep . requirement
292- raise GemfileError , "You cannot specify the same plugin twice with different version requirements.\n " \
293- "You specified: #{ current . name } (#{ current . requirement } ) and #{ dep . name } (#{ dep . requirement } )" \
294- "#{ update_prompt } "
295- end
296-
297- if current . source != dep . source
298- raise GemfileError , "You cannot specify the same plugin twice coming from different sources.\n " \
299- "You specified that #{ dep . name } (#{ dep . requirement } ) should come from " \
300- "#{ current . source || "an unspecified source" } and #{ dep . source } \n "
301- else
302- Bundler . ui . warn "Your Gemfile lists the plugin #{ current . name } (#{ current . requirement } ) more than once.\n " \
303- "You should keep only one of them.\n " \
304- "Remove any duplicate entries and specify the plugin only once." \
305- "While it's not a problem now, it could cause errors if you change the version of one of them later."
306- end
307- end
308-
309- @plugins << dep
288+ @current_sources = @plugin_sources
289+ @current_dependencies = @plugin_dependencies
290+ gem ( name , *args )
291+ ensure
292+ @current_sources = @sources
293+ @current_dependencies = @dependencies
310294 end
311295
312296 def method_missing ( name , *args )
@@ -320,6 +304,11 @@ def check_primary_source_safety
320304
321305 private
322306
307+ def add_source ( method , *args )
308+ @plugin_sources . send ( method , *args ) unless @plugin_sources . equal? ( @current_sources )
309+ @current_sources . send ( method , *args )
310+ end
311+
323312 def add_git_sources
324313 git_source ( :github ) do |repo_name |
325314 if repo_name =~ GITHUB_PULL_REQUEST_URL
@@ -382,7 +371,7 @@ def valid_keys
382371 @valid_keys ||= VALID_KEYS
383372 end
384373
385- def normalize_options ( name , version , add_to_sources , opts )
374+ def normalize_options ( name , version , opts )
386375 if name . is_a? ( Symbol )
387376 raise GemfileError , %(You need to specify gem names as Strings. Use 'gem "#{ name } "' instead)
388377 end
@@ -417,9 +406,9 @@ def normalize_options(name, version, add_to_sources, opts)
417406 end
418407
419408 # Save sources passed in a key
420- if opts . key? ( "source" ) && add_to_sources
409+ if opts . key? ( "source" )
421410 source = normalize_source ( opts [ "source" ] )
422- opts [ "source" ] = @sources . add_rubygems_source ( "remotes" => source )
411+ opts [ "source" ] = @current_sources . add_rubygems_source ( "remotes" => source )
423412 end
424413
425414 git_name = ( git_names & opts . keys ) . last
@@ -438,10 +427,8 @@ def normalize_options(name, version, add_to_sources, opts)
438427 else
439428 options = opts . dup
440429 end
441- if add_to_sources
442- source = send ( type , param , options ) { }
443- opts [ "source" ] = source
444- end
430+ source = send ( type , param , options ) { }
431+ opts [ "source" ] = source
445432 end
446433
447434 opts [ "source" ] ||= @source
0 commit comments