@@ -29,6 +29,7 @@ def initialize
2929      @sources               =  SourceList . new 
3030      @git_sources           =  { } 
3131      @dependencies          =  [ ] 
32+       @plugins               =  [ ] 
3233      @groups                =  [ ] 
3334      @install_conditionals  =  [ ] 
3435      @optional_groups       =  [ ] 
@@ -97,7 +98,7 @@ def gem(name, *args)
9798      options [ "gemfile" ]  =  @gemfile 
9899      version  =  args  || [ ">= 0" ] 
99100
100-       normalize_options ( name ,  version ,  options ) 
101+       normalize_options ( name ,  version ,  true ,   options ) 
101102
102103      dep  =  Dependency . new ( name ,  version ,  options ) 
103104
@@ -228,7 +229,7 @@ def github(repo, options = {})
228229
229230    def  to_definition ( lockfile ,  unlock ,  lockfile_contents : nil ) 
230231      check_primary_source_safety 
231-       Definition . new ( lockfile ,  @dependencies ,  @sources ,  unlock ,  @ruby_version ,  @optional_groups ,  @gemfiles ,  lockfile_contents ) 
232+       Definition . new ( lockfile ,  @dependencies ,  @sources ,  unlock ,  @ruby_version ,  @optional_groups ,  @gemfiles ,  lockfile_contents ,   @plugins ) 
232233    end 
233234
234235    def  group ( *args ,  &blk ) 
@@ -270,8 +271,29 @@ def env(name)
270271      @env  =  old 
271272    end 
272273
273-     def  plugin ( *args ) 
274-       # Pass on 
274+     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 actually installing plugins here (they should already 
281+       # be installed), just keeping track of them so that we can verify they 
282+       # are actually 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 dependency with this name we try to prefer one 
290+       if  current  =  @plugins . find  { |d | d . name  == dep . name  } 
291+         Bundler . ui . warn  "Your Gemfile lists the plugin #{ current . name } #{ current . requirement } \n "  \
292+                         "You should keep only one of them.\n "  \
293+                         "Remove any duplicate entries and specify the plugin only once." 
294+       end 
295+ 
296+       @plugins  << dep 
275297    end 
276298
277299    def  method_missing ( name ,  *args ) 
@@ -347,7 +369,7 @@ def valid_keys
347369      @valid_keys  ||= VALID_KEYS 
348370    end 
349371
350-     def  normalize_options ( name ,  version ,  opts ) 
372+     def  normalize_options ( name ,  version ,  add_to_sources ,   opts ) 
351373      if  name . is_a? ( Symbol ) 
352374        raise  GemfileError ,  %(You need to specify gem names as Strings. Use 'gem "#{ name }  
353375      end 
@@ -382,7 +404,7 @@ def normalize_options(name, version, opts)
382404      end 
383405
384406      # Save sources passed in a key 
385-       if  opts . key? ( "source" ) 
407+       if  opts . key? ( "source" )  &&  add_to_sources 
386408        source  =  normalize_source ( opts [ "source" ] ) 
387409        opts [ "source" ]  =  @sources . add_rubygems_source ( "remotes"  =>  source ) 
388410      end 
@@ -403,8 +425,10 @@ def normalize_options(name, version, opts)
403425        else 
404426          options  =  opts . dup 
405427        end 
406-         source  =  send ( type ,  param ,  options )  { } 
407-         opts [ "source" ]  =  source 
428+         if  add_to_sources 
429+           source  =  send ( type ,  param ,  options )  { } 
430+           opts [ "source" ]  =  source 
431+         end 
408432      end 
409433
410434      opts [ "source" ]          ||= @source 
0 commit comments