@@ -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 } #{ 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 }   \
300-                           "#{ current . source  || "an unspecified source" } #{ dep . source } \n " 
301-         else 
302-           Bundler . ui . warn  "Your Gemfile lists the plugin #{ current . name } #{ current . requirement } \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 }  
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