rubygems-update 3.5.9 → 3.5.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -1
  3. data/CODE_OF_CONDUCT.md +79 -28
  4. data/CONTRIBUTING.md +2 -2
  5. data/Manifest.txt +1 -0
  6. data/POLICIES.md +75 -6
  7. data/bundler/CHANGELOG.md +52 -0
  8. data/bundler/lib/bundler/build_metadata.rb +2 -2
  9. data/bundler/lib/bundler/cli/install.rb +1 -1
  10. data/bundler/lib/bundler/cli.rb +5 -22
  11. data/bundler/lib/bundler/compact_index_client/cache.rb +16 -7
  12. data/bundler/lib/bundler/constants.rb +8 -1
  13. data/bundler/lib/bundler/definition.rb +70 -50
  14. data/bundler/lib/bundler/dependency.rb +2 -1
  15. data/bundler/lib/bundler/environment_preserver.rb +2 -20
  16. data/bundler/lib/bundler/errors.rb +14 -0
  17. data/bundler/lib/bundler/gem_helper.rb +1 -1
  18. data/bundler/lib/bundler/injector.rb +2 -1
  19. data/bundler/lib/bundler/installer.rb +8 -8
  20. data/bundler/lib/bundler/man/bundle-add.1 +1 -1
  21. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  22. data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
  23. data/bundler/lib/bundler/man/bundle-check.1 +3 -1
  24. data/bundler/lib/bundler/man/bundle-check.1.ronn +3 -0
  25. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  26. data/bundler/lib/bundler/man/bundle-config.1 +1 -3
  27. data/bundler/lib/bundler/man/bundle-config.1.ronn +0 -3
  28. data/bundler/lib/bundler/man/bundle-console.1 +1 -1
  29. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  30. data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
  31. data/bundler/lib/bundler/man/bundle-gem.1 +1 -1
  32. data/bundler/lib/bundler/man/bundle-help.1 +1 -1
  33. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  34. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  35. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  36. data/bundler/lib/bundler/man/bundle-install.1 +1 -1
  37. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  38. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  39. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  40. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  41. data/bundler/lib/bundler/man/bundle-platform.1 +1 -1
  42. data/bundler/lib/bundler/man/bundle-plugin.1 +1 -1
  43. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  44. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  45. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  46. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  47. data/bundler/lib/bundler/man/bundle-version.1 +1 -1
  48. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  49. data/bundler/lib/bundler/man/bundle.1 +1 -1
  50. data/bundler/lib/bundler/man/gemfile.5 +1 -1
  51. data/bundler/lib/bundler/rubygems_ext.rb +29 -9
  52. data/bundler/lib/bundler/self_manager.rb +1 -1
  53. data/bundler/lib/bundler/settings.rb +0 -1
  54. data/bundler/lib/bundler/setup.rb +3 -0
  55. data/bundler/lib/bundler/shared_helpers.rb +6 -4
  56. data/bundler/lib/bundler/source/git/git_proxy.rb +8 -0
  57. data/bundler/lib/bundler/source/metadata.rb +2 -0
  58. data/bundler/lib/bundler/source/rubygems.rb +6 -18
  59. data/bundler/lib/bundler/source_list.rb +28 -4
  60. data/bundler/lib/bundler/spec_set.rb +1 -1
  61. data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +77 -29
  62. data/bundler/lib/bundler/version.rb +1 -1
  63. data/bundler/lib/bundler.rb +20 -0
  64. data/exe/update_rubygems +1 -1
  65. data/lib/rubygems/commands/pristine_command.rb +9 -6
  66. data/lib/rubygems/commands/setup_command.rb +2 -0
  67. data/lib/rubygems/commands/uninstall_command.rb +1 -1
  68. data/lib/rubygems/commands/update_command.rb +8 -9
  69. data/lib/rubygems/dependency.rb +1 -13
  70. data/lib/rubygems/deprecate.rb +79 -77
  71. data/lib/rubygems/ext/cargo_builder.rb +1 -16
  72. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +3 -1
  73. data/lib/rubygems/installer.rb +1 -1
  74. data/lib/rubygems/package/tar_header.rb +20 -4
  75. data/lib/rubygems/package.rb +11 -6
  76. data/lib/rubygems/platform.rb +1 -0
  77. data/lib/rubygems/specification.rb +35 -117
  78. data/lib/rubygems/specification_policy.rb +3 -1
  79. data/lib/rubygems/specification_record.rb +213 -0
  80. data/lib/rubygems/uninstaller.rb +15 -9
  81. data/lib/rubygems/util/licenses.rb +25 -0
  82. data/lib/rubygems.rb +8 -1
  83. data/rubygems-update.gemspec +1 -1
  84. metadata +4 -3
@@ -11,6 +11,7 @@ require_relative "deprecate"
11
11
  require_relative "basic_specification"
12
12
  require_relative "stub_specification"
13
13
  require_relative "platform"
14
+ require_relative "specification_record"
14
15
  require_relative "util/list"
15
16
 
16
17
  require "rbconfig"
@@ -179,22 +180,12 @@ class Gem::Specification < Gem::BasicSpecification
179
180
  @@default_value[k].nil?
180
181
  end
181
182
 
182
- def self.clear_specs # :nodoc:
183
- @@all = nil
184
- @@stubs = nil
185
- @@stubs_by_name = {}
186
- @@spec_with_requirable_file = {}
187
- @@active_stub_with_requirable_file = {}
188
- end
189
- private_class_method :clear_specs
190
-
191
- clear_specs
192
-
193
183
  # Sentinel object to represent "not found" stubs
194
184
  NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
185
+ deprecate_constant :NOT_FOUND
195
186
 
196
187
  # Tracking removed method calls to warn users during build time.
197
- REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc:
188
+ REMOVED_METHODS = [:rubyforge_project=, :mark_version].freeze # :nodoc:
198
189
  def removed_method_calls
199
190
  @removed_method_calls ||= []
200
191
  end
@@ -770,7 +761,7 @@ class Gem::Specification < Gem::BasicSpecification
770
761
  attr_accessor :specification_version
771
762
 
772
763
  def self._all # :nodoc:
773
- @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec)
764
+ specification_record.all
774
765
  end
775
766
 
776
767
  def self.clear_load_cache # :nodoc:
@@ -788,26 +779,9 @@ class Gem::Specification < Gem::BasicSpecification
788
779
  end
789
780
  end
790
781
 
791
- def self.gemspec_stubs_in(dir, pattern)
782
+ def self.gemspec_stubs_in(dir, pattern) # :nodoc:
792
783
  Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?)
793
784
  end
794
- private_class_method :gemspec_stubs_in
795
-
796
- def self.installed_stubs(dirs, pattern)
797
- map_stubs(dirs, pattern) do |path, base_dir, gems_dir|
798
- Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
799
- end
800
- end
801
- private_class_method :installed_stubs
802
-
803
- def self.map_stubs(dirs, pattern) # :nodoc:
804
- dirs.flat_map do |dir|
805
- base_dir = File.dirname dir
806
- gems_dir = File.join base_dir, "gems"
807
- gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
808
- end
809
- end
810
- private_class_method :map_stubs
811
785
 
812
786
  def self.each_spec(dirs) # :nodoc:
813
787
  each_gemspec(dirs) do |path|
@@ -820,13 +794,7 @@ class Gem::Specification < Gem::BasicSpecification
820
794
  # Returns a Gem::StubSpecification for every installed gem
821
795
 
822
796
  def self.stubs
823
- @@stubs ||= begin
824
- pattern = "*.gemspec"
825
- stubs = stubs_for_pattern(pattern, false)
826
-
827
- @@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
828
- stubs
829
- end
797
+ specification_record.stubs
830
798
  end
831
799
 
832
800
  ##
@@ -845,13 +813,7 @@ class Gem::Specification < Gem::BasicSpecification
845
813
  # only returns stubs that match Gem.platforms
846
814
 
847
815
  def self.stubs_for(name)
848
- if @@stubs
849
- @@stubs_by_name[name] || []
850
- else
851
- @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
852
- s.name == name
853
- end
854
- end
816
+ specification_record.stubs_for(name)
855
817
  end
856
818
 
857
819
  ##
@@ -859,12 +821,7 @@ class Gem::Specification < Gem::BasicSpecification
859
821
  # optionally filtering out specs not matching the current platform
860
822
  #
861
823
  def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
862
- installed_stubs = installed_stubs(Gem::Specification.dirs, pattern)
863
- installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
864
- stubs = installed_stubs + default_stubs(pattern)
865
- stubs = stubs.uniq(&:full_name)
866
- _resort!(stubs)
867
- stubs
824
+ specification_record.stubs_for_pattern(pattern, match_platform)
868
825
  end
869
826
 
870
827
  def self._resort!(specs) # :nodoc:
@@ -893,23 +850,14 @@ class Gem::Specification < Gem::BasicSpecification
893
850
  # properly sorted.
894
851
 
895
852
  def self.add_spec(spec)
896
- return if _all.include? spec
897
-
898
- _all << spec
899
- stubs << spec
900
- (@@stubs_by_name[spec.name] ||= []) << spec
901
-
902
- _resort!(@@stubs_by_name[spec.name])
903
- _resort!(stubs)
853
+ specification_record.add_spec(spec)
904
854
  end
905
855
 
906
856
  ##
907
857
  # Removes +spec+ from the known specs.
908
858
 
909
859
  def self.remove_spec(spec)
910
- _all.delete spec.to_spec
911
- stubs.delete spec
912
- (@@stubs_by_name[spec.name] || []).delete spec
860
+ specification_record.remove_spec(spec)
913
861
  end
914
862
 
915
863
  ##
@@ -923,27 +871,17 @@ class Gem::Specification < Gem::BasicSpecification
923
871
  end
924
872
 
925
873
  ##
926
- # Sets the known specs to +specs+. Not guaranteed to work for you in
927
- # the future. Use at your own risk. Caveat emptor. Doomy doom doom.
928
- # Etc etc.
929
- #
930
- #--
931
- # Makes +specs+ the known specs
932
- # Listen, time is a river
933
- # Winter comes, code breaks
934
- #
935
- # -- wilsonb
874
+ # Sets the known specs to +specs+.
936
875
 
937
876
  def self.all=(specs)
938
- @@stubs_by_name = specs.group_by(&:name)
939
- @@all = @@stubs = specs
877
+ specification_record.all = specs
940
878
  end
941
879
 
942
880
  ##
943
881
  # Return full names of all specs in sorted order.
944
882
 
945
883
  def self.all_names
946
- _all.map(&:full_name)
884
+ specification_record.all_names
947
885
  end
948
886
 
949
887
  ##
@@ -968,9 +906,7 @@ class Gem::Specification < Gem::BasicSpecification
968
906
  # Return the directories that Specification uses to find specs.
969
907
 
970
908
  def self.dirs
971
- @@dirs ||= Gem.path.collect do |dir|
972
- File.join dir, "specifications"
973
- end
909
+ @@dirs ||= Gem::SpecificationRecord.dirs_from(Gem.path)
974
910
  end
975
911
 
976
912
  ##
@@ -980,7 +916,7 @@ class Gem::Specification < Gem::BasicSpecification
980
916
  def self.dirs=(dirs)
981
917
  reset
982
918
 
983
- @@dirs = Array(dirs).map {|dir| File.join dir, "specifications" }
919
+ @@dirs = Gem::SpecificationRecord.dirs_from(Array(dirs))
984
920
  end
985
921
 
986
922
  extend Enumerable
@@ -989,21 +925,15 @@ class Gem::Specification < Gem::BasicSpecification
989
925
  # Enumerate every known spec. See ::dirs= and ::add_spec to set the list of
990
926
  # specs.
991
927
 
992
- def self.each
993
- return enum_for(:each) unless block_given?
994
-
995
- _all.each do |x|
996
- yield x
997
- end
928
+ def self.each(&block)
929
+ specification_record.each(&block)
998
930
  end
999
931
 
1000
932
  ##
1001
933
  # Returns every spec that matches +name+ and optional +requirements+.
1002
934
 
1003
935
  def self.find_all_by_name(name, *requirements)
1004
- requirements = Gem::Requirement.default if requirements.empty?
1005
-
1006
- Gem::Dependency.new(name, *requirements).matching_specs
936
+ specification_record.find_all_by_name(name, *requirements)
1007
937
  end
1008
938
 
1009
939
  ##
@@ -1033,12 +963,7 @@ class Gem::Specification < Gem::BasicSpecification
1033
963
  # Return the best specification that contains the file matching +path+.
1034
964
 
1035
965
  def self.find_by_path(path)
1036
- path = path.dup.freeze
1037
- spec = @@spec_with_requirable_file[path] ||= stubs.find do |s|
1038
- s.contains_requirable_file? path
1039
- end || NOT_FOUND
1040
-
1041
- spec.to_spec
966
+ specification_record.find_by_path(path)
1042
967
  end
1043
968
 
1044
969
  ##
@@ -1046,19 +971,15 @@ class Gem::Specification < Gem::BasicSpecification
1046
971
  # amongst the specs that are not activated.
1047
972
 
1048
973
  def self.find_inactive_by_path(path)
1049
- stub = stubs.find do |s|
1050
- next if s.activated?
1051
- s.contains_requirable_file? path
1052
- end
1053
- stub&.to_spec
974
+ specification_record.find_inactive_by_path(path)
1054
975
  end
1055
976
 
1056
- def self.find_active_stub_by_path(path)
1057
- stub = @@active_stub_with_requirable_file[path] ||= stubs.find do |s|
1058
- s.activated? && s.contains_requirable_file?(path)
1059
- end || NOT_FOUND
977
+ ##
978
+ # Return the best specification that contains the file matching +path+, among
979
+ # those already activated.
1060
980
 
1061
- stub.this
981
+ def self.find_active_stub_by_path(path)
982
+ specification_record.find_active_stub_by_path(path)
1062
983
  end
1063
984
 
1064
985
  ##
@@ -1125,14 +1046,14 @@ class Gem::Specification < Gem::BasicSpecification
1125
1046
  # +prerelease+ is true.
1126
1047
 
1127
1048
  def self.latest_specs(prerelease = false)
1128
- _latest_specs Gem::Specification.stubs, prerelease
1049
+ specification_record.latest_specs(prerelease)
1129
1050
  end
1130
1051
 
1131
1052
  ##
1132
1053
  # Return the latest installed spec for gem +name+.
1133
1054
 
1134
1055
  def self.latest_spec_for(name)
1135
- latest_specs(true).find {|installed_spec| installed_spec.name == name }
1056
+ specification_record.latest_spec_for(name)
1136
1057
  end
1137
1058
 
1138
1059
  def self._latest_specs(specs, prerelease = false) # :nodoc:
@@ -1270,7 +1191,7 @@ class Gem::Specification < Gem::BasicSpecification
1270
1191
  def self.reset
1271
1192
  @@dirs = nil
1272
1193
  Gem.pre_reset_hooks.each(&:call)
1273
- clear_specs
1194
+ @specification_record = nil
1274
1195
  clear_load_cache
1275
1196
  unresolved = unresolved_deps
1276
1197
  unless unresolved.empty?
@@ -1291,6 +1212,13 @@ class Gem::Specification < Gem::BasicSpecification
1291
1212
  Gem.post_reset_hooks.each(&:call)
1292
1213
  end
1293
1214
 
1215
+ ##
1216
+ # Keeps track of all currently known specifications
1217
+
1218
+ def self.specification_record
1219
+ @specification_record ||= Gem::SpecificationRecord.new(dirs)
1220
+ end
1221
+
1294
1222
  # DOC: This method needs documented or nodoc'd
1295
1223
  def self.unresolved_deps
1296
1224
  @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n }
@@ -1874,8 +1802,6 @@ class Gem::Specification < Gem::BasicSpecification
1874
1802
  end
1875
1803
 
1876
1804
  def encode_with(coder) # :nodoc:
1877
- mark_version
1878
-
1879
1805
  coder.add "name", @name
1880
1806
  coder.add "version", @version
1881
1807
  platform = case @original_platform
@@ -2169,13 +2095,6 @@ class Gem::Specification < Gem::BasicSpecification
2169
2095
  @spec_file = nil
2170
2096
  end
2171
2097
 
2172
- ##
2173
- # Sets the rubygems_version to the current RubyGems version.
2174
-
2175
- def mark_version
2176
- @rubygems_version = Gem::VERSION
2177
- end
2178
-
2179
2098
  ##
2180
2099
  # Track removed method calls to warn about during build time.
2181
2100
  # Warn about unknown attributes while loading a spec.
@@ -2493,7 +2412,6 @@ class Gem::Specification < Gem::BasicSpecification
2493
2412
  # still have their default values are omitted.
2494
2413
 
2495
2414
  def to_ruby
2496
- mark_version
2497
2415
  result = []
2498
2416
  result << "# -*- encoding: utf-8 -*-"
2499
2417
  result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{raw_require_paths.join("\0")}"
@@ -274,7 +274,9 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
274
274
 
275
275
  return if rubygems_version == Gem::VERSION
276
276
 
277
- error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
277
+ warning "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
278
+
279
+ @specification.rubygems_version = Gem::VERSION
278
280
  end
279
281
 
280
282
  def validate_required_attributes
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gem
4
+ class SpecificationRecord
5
+ def self.dirs_from(paths)
6
+ paths.map do |path|
7
+ File.join(path, "specifications")
8
+ end
9
+ end
10
+
11
+ def self.from_path(path)
12
+ new(dirs_from([path]))
13
+ end
14
+
15
+ def initialize(dirs)
16
+ @all = nil
17
+ @stubs = nil
18
+ @stubs_by_name = {}
19
+ @spec_with_requirable_file = {}
20
+ @active_stub_with_requirable_file = {}
21
+
22
+ @dirs = dirs
23
+ end
24
+
25
+ # Sentinel object to represent "not found" stubs
26
+ NOT_FOUND = Struct.new(:to_spec, :this).new
27
+ private_constant :NOT_FOUND
28
+
29
+ ##
30
+ # Returns the list of all specifications in the record
31
+
32
+ def all
33
+ @all ||= Gem.loaded_specs.values | stubs.map(&:to_spec)
34
+ end
35
+
36
+ ##
37
+ # Returns a Gem::StubSpecification for every specification in the record
38
+
39
+ def stubs
40
+ @stubs ||= begin
41
+ pattern = "*.gemspec"
42
+ stubs = stubs_for_pattern(pattern, false)
43
+
44
+ @stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
45
+ stubs
46
+ end
47
+ end
48
+
49
+ ##
50
+ # Returns a Gem::StubSpecification for every specification in the record
51
+ # named +name+ only returns stubs that match Gem.platforms
52
+
53
+ def stubs_for(name)
54
+ if @stubs
55
+ @stubs_by_name[name] || []
56
+ else
57
+ @stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
58
+ s.name == name
59
+ end
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Finds stub specifications matching a pattern in the record, optionally
65
+ # filtering out specs not matching the current platform
66
+
67
+ def stubs_for_pattern(pattern, match_platform = true)
68
+ installed_stubs = installed_stubs(pattern)
69
+ installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
70
+ stubs = installed_stubs + Gem::Specification.default_stubs(pattern)
71
+ stubs = stubs.uniq(&:full_name)
72
+ Gem::Specification._resort!(stubs)
73
+ stubs
74
+ end
75
+
76
+ ##
77
+ # Adds +spec+ to the the record, keeping the collection properly sorted.
78
+
79
+ def add_spec(spec)
80
+ return if all.include? spec
81
+
82
+ all << spec
83
+ stubs << spec
84
+ (@stubs_by_name[spec.name] ||= []) << spec
85
+
86
+ Gem::Specification._resort!(@stubs_by_name[spec.name])
87
+ Gem::Specification._resort!(stubs)
88
+ end
89
+
90
+ ##
91
+ # Removes +spec+ from the record.
92
+
93
+ def remove_spec(spec)
94
+ all.delete spec.to_spec
95
+ stubs.delete spec
96
+ (@stubs_by_name[spec.name] || []).delete spec
97
+ end
98
+
99
+ ##
100
+ # Sets the specs known by the record to +specs+.
101
+
102
+ def all=(specs)
103
+ @stubs_by_name = specs.group_by(&:name)
104
+ @all = @stubs = specs
105
+ end
106
+
107
+ ##
108
+ # Return full names of all specs in the record in sorted order.
109
+
110
+ def all_names
111
+ all.map(&:full_name)
112
+ end
113
+
114
+ include Enumerable
115
+
116
+ ##
117
+ # Enumerate every known spec.
118
+
119
+ def each
120
+ return enum_for(:each) unless block_given?
121
+
122
+ all.each do |x|
123
+ yield x
124
+ end
125
+ end
126
+
127
+ ##
128
+ # Returns every spec in the record that matches +name+ and optional +requirements+.
129
+
130
+ def find_all_by_name(name, *requirements)
131
+ req = Gem::Requirement.create(*requirements)
132
+ env_req = Gem.env_requirement(name)
133
+
134
+ matches = stubs_for(name).find_all do |spec|
135
+ req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
136
+ end.map(&:to_spec)
137
+
138
+ if name == "bundler" && !req.specific?
139
+ require_relative "bundler_version_finder"
140
+ Gem::BundlerVersionFinder.prioritize!(matches)
141
+ end
142
+
143
+ matches
144
+ end
145
+
146
+ ##
147
+ # Return the best specification in the record that contains the file matching +path+.
148
+
149
+ def find_by_path(path)
150
+ path = path.dup.freeze
151
+ spec = @spec_with_requirable_file[path] ||= stubs.find do |s|
152
+ s.contains_requirable_file? path
153
+ end || NOT_FOUND
154
+
155
+ spec.to_spec
156
+ end
157
+
158
+ ##
159
+ # Return the best specification in the record that contains the file
160
+ # matching +path+ amongst the specs that are not activated.
161
+
162
+ def find_inactive_by_path(path)
163
+ stub = stubs.find do |s|
164
+ next if s.activated?
165
+ s.contains_requirable_file? path
166
+ end
167
+ stub&.to_spec
168
+ end
169
+
170
+ ##
171
+ # Return the best specification in the record that contains the file
172
+ # matching +path+, among those already activated.
173
+
174
+ def find_active_stub_by_path(path)
175
+ stub = @active_stub_with_requirable_file[path] ||= stubs.find do |s|
176
+ s.activated? && s.contains_requirable_file?(path)
177
+ end || NOT_FOUND
178
+
179
+ stub.this
180
+ end
181
+
182
+ ##
183
+ # Return the latest specs in the record, optionally including prerelease
184
+ # specs if +prerelease+ is true.
185
+
186
+ def latest_specs(prerelease)
187
+ Gem::Specification._latest_specs stubs, prerelease
188
+ end
189
+
190
+ ##
191
+ # Return the latest installed spec in the record for gem +name+.
192
+
193
+ def latest_spec_for(name)
194
+ latest_specs(true).find {|installed_spec| installed_spec.name == name }
195
+ end
196
+
197
+ private
198
+
199
+ def installed_stubs(pattern)
200
+ map_stubs(pattern) do |path, base_dir, gems_dir|
201
+ Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
202
+ end
203
+ end
204
+
205
+ def map_stubs(pattern)
206
+ @dirs.flat_map do |dir|
207
+ base_dir = File.dirname dir
208
+ gems_dir = File.join base_dir, "gems"
209
+ Gem::Specification.gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
210
+ end
211
+ end
212
+ end
213
+ end
@@ -32,7 +32,7 @@ class Gem::Uninstaller
32
32
  attr_reader :bin_dir
33
33
 
34
34
  ##
35
- # The gem repository the gem will be installed into
35
+ # The gem repository the gem will be uninstalled from
36
36
 
37
37
  attr_reader :gem_home
38
38
 
@@ -49,8 +49,9 @@ class Gem::Uninstaller
49
49
  # TODO: document the valid options
50
50
  @gem = gem
51
51
  @version = options[:version] || Gem::Requirement.default
52
- @gem_home = File.realpath(options[:install_dir] || Gem.dir)
53
- @plugins_dir = Gem.plugindir(@gem_home)
52
+ @install_dir = options[:install_dir]
53
+ @gem_home = File.realpath(@install_dir || Gem.dir)
54
+ @user_dir = File.exist?(Gem.user_dir) ? File.realpath(Gem.user_dir) : Gem.user_dir
54
55
  @force_executables = options[:executables]
55
56
  @force_all = options[:all]
56
57
  @force_ignore = options[:ignore]
@@ -70,7 +71,7 @@ class Gem::Uninstaller
70
71
 
71
72
  # only add user directory if install_dir is not set
72
73
  @user_install = false
73
- @user_install = options[:user_install] unless options[:install_dir]
74
+ @user_install = options[:user_install] unless @install_dir
74
75
 
75
76
  # Optimization: populated during #uninstall
76
77
  @default_specs_matching_uninstall_params = []
@@ -105,7 +106,7 @@ class Gem::Uninstaller
105
106
 
106
107
  list, other_repo_specs = list.partition do |spec|
107
108
  @gem_home == spec.base_dir ||
108
- (@user_install && spec.base_dir == Gem.user_dir)
109
+ (@user_install && spec.base_dir == @user_dir)
109
110
  end
110
111
 
111
112
  list.sort!
@@ -239,7 +240,7 @@ class Gem::Uninstaller
239
240
 
240
241
  def remove(spec)
241
242
  unless path_ok?(@gem_home, spec) ||
242
- (@user_install && path_ok?(Gem.user_dir, spec))
243
+ (@user_install && path_ok?(@user_dir, spec))
243
244
  e = Gem::GemNotInHomeException.new \
244
245
  "Gem '#{spec.full_name}' is not installed in directory #{@gem_home}"
245
246
  e.spec = spec
@@ -284,17 +285,18 @@ class Gem::Uninstaller
284
285
  def remove_plugins(spec) # :nodoc:
285
286
  return if spec.plugins.empty?
286
287
 
287
- remove_plugins_for(spec, @plugins_dir)
288
+ remove_plugins_for(spec, plugin_dir_for(spec))
288
289
  end
289
290
 
290
291
  ##
291
292
  # Regenerates plugin wrappers after removal.
292
293
 
293
294
  def regenerate_plugins
294
- latest = Gem::Specification.latest_spec_for(@spec.name)
295
+ specification_record = @install_dir ? Gem::SpecificationRecord.from_path(@install_dir) : Gem::Specification.specification_record
296
+ latest = specification_record.latest_spec_for(@spec.name)
295
297
  return if latest.nil?
296
298
 
297
- regenerate_plugins_for(latest, @plugins_dir)
299
+ regenerate_plugins_for(latest, plugin_dir_for(@spec))
298
300
  end
299
301
 
300
302
  ##
@@ -406,4 +408,8 @@ class Gem::Uninstaller
406
408
  say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem"
407
409
  end
408
410
  end
411
+
412
+ def plugin_dir_for(spec)
413
+ Gem.plugindir(spec.base_dir)
414
+ end
409
415
  end