rubygems-update 3.1.0.pre3 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.bundle/config +2 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +8 -0
- data/Gemfile.lock +43 -0
- data/History.txt +97 -2
- data/Manifest.txt +21 -3
- data/README.md +4 -4
- data/Rakefile +11 -10
- data/bin/update_rubygems +1 -1
- data/bundler/CHANGELOG.md +56 -3
- data/bundler/lib/bundler.rb +0 -1
- data/bundler/lib/bundler/build_metadata.rb +2 -0
- data/bundler/lib/bundler/cli.rb +1 -1
- data/bundler/lib/bundler/cli/config.rb +1 -1
- data/bundler/lib/bundler/cli/install.rb +3 -2
- data/bundler/lib/bundler/cli/update.rb +1 -1
- data/bundler/lib/bundler/feature_flag.rb +1 -1
- data/bundler/lib/bundler/fetcher.rb +2 -2
- data/bundler/lib/bundler/fetcher/downloader.rb +1 -1
- data/bundler/lib/bundler/fetcher/index.rb +1 -1
- data/bundler/lib/bundler/friendly_errors.rb +1 -1
- data/bundler/lib/bundler/gem_helper.rb +13 -12
- data/bundler/lib/bundler/inline.rb +36 -31
- data/bundler/lib/bundler/lazy_specification.rb +0 -1
- data/bundler/lib/bundler/mirror.rb +3 -3
- data/bundler/lib/bundler/plugin/api/source.rb +2 -4
- data/bundler/lib/bundler/remote_specification.rb +0 -2
- data/bundler/lib/bundler/rubygems_integration.rb +15 -13
- data/bundler/lib/bundler/settings.rb +7 -4
- data/bundler/lib/bundler/setup.rb +5 -0
- data/bundler/lib/bundler/source/git.rb +5 -5
- data/bundler/lib/bundler/source/git/git_proxy.rb +3 -2
- data/bundler/lib/bundler/source/rubygems.rb +3 -3
- data/bundler/lib/bundler/source/rubygems/remote.rb +1 -1
- data/bundler/lib/bundler/uri_credentials_filter.rb +7 -3
- data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +3 -3
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +26 -48
- data/bundler/lib/bundler/vendor/thor/lib/thor.rb +7 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +10 -6
- data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +29 -19
- data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +13 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +8 -9
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +10 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +2 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +17 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/bundler/lib/bundler/vendor/uri/lib/uri.rb +104 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +744 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +94 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +267 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +1568 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +88 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +23 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +261 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +21 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +294 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +546 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +125 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +6 -0
- data/bundler/lib/bundler/vendored_uri.rb +4 -0
- data/bundler/lib/bundler/version.rb +1 -1
- data/bundler/man/bundle-add.1 +1 -1
- data/bundler/man/bundle-add.1.txt +1 -1
- data/bundler/man/bundle-binstubs.1 +1 -1
- data/bundler/man/bundle-binstubs.1.txt +1 -1
- data/bundler/man/bundle-cache.1 +1 -1
- data/bundler/man/bundle-cache.1.txt +1 -1
- data/bundler/man/bundle-check.1 +1 -1
- data/bundler/man/bundle-check.1.txt +1 -1
- data/bundler/man/bundle-clean.1 +1 -1
- data/bundler/man/bundle-clean.1.txt +1 -1
- data/bundler/man/bundle-config.1 +1 -1
- data/bundler/man/bundle-config.1.txt +1 -1
- data/bundler/man/bundle-doctor.1 +1 -1
- data/bundler/man/bundle-doctor.1.txt +1 -1
- data/bundler/man/bundle-exec.1 +1 -1
- data/bundler/man/bundle-exec.1.txt +1 -1
- data/bundler/man/bundle-gem.1 +1 -1
- data/bundler/man/bundle-gem.1.txt +1 -1
- data/bundler/man/bundle-info.1 +1 -1
- data/bundler/man/bundle-info.1.txt +1 -1
- data/bundler/man/bundle-init.1 +1 -1
- data/bundler/man/bundle-init.1.txt +1 -1
- data/bundler/man/bundle-inject.1 +1 -1
- data/bundler/man/bundle-inject.1.txt +1 -1
- data/bundler/man/bundle-install.1 +1 -1
- data/bundler/man/bundle-install.1.txt +1 -1
- data/bundler/man/bundle-list.1 +1 -1
- data/bundler/man/bundle-list.1.txt +1 -1
- data/bundler/man/bundle-lock.1 +1 -1
- data/bundler/man/bundle-lock.1.txt +1 -1
- data/bundler/man/bundle-open.1 +1 -1
- data/bundler/man/bundle-open.1.txt +1 -1
- data/bundler/man/bundle-outdated.1 +1 -1
- data/bundler/man/bundle-outdated.1.txt +1 -1
- data/bundler/man/bundle-platform.1 +1 -1
- data/bundler/man/bundle-platform.1.txt +1 -1
- data/bundler/man/bundle-pristine.1 +1 -1
- data/bundler/man/bundle-pristine.1.txt +1 -1
- data/bundler/man/bundle-remove.1 +1 -1
- data/bundler/man/bundle-remove.1.txt +1 -1
- data/bundler/man/bundle-show.1 +1 -1
- data/bundler/man/bundle-show.1.txt +1 -1
- data/bundler/man/bundle-update.1 +1 -1
- data/bundler/man/bundle-update.1.txt +1 -1
- data/bundler/man/bundle-viz.1 +1 -1
- data/bundler/man/bundle-viz.1.txt +1 -1
- data/bundler/man/bundle.1 +1 -1
- data/bundler/man/bundle.1.txt +1 -1
- data/bundler/man/gemfile.5 +1 -1
- data/bundler/man/gemfile.5.txt +1 -1
- data/lib/rubygems.rb +64 -47
- data/lib/rubygems/basic_specification.rb +1 -1
- data/lib/rubygems/command.rb +29 -7
- data/lib/rubygems/commands/generate_index_command.rb +3 -0
- data/lib/rubygems/commands/help_command.rb +1 -1
- data/lib/rubygems/commands/setup_command.rb +30 -15
- data/lib/rubygems/commands/sources_command.rb +17 -3
- data/lib/rubygems/commands/uninstall_command.rb +1 -1
- data/lib/rubygems/core_ext/kernel_require.rb +1 -1
- data/lib/rubygems/core_ext/kernel_warn.rb +8 -4
- data/lib/rubygems/ext/builder.rb +4 -2
- data/lib/rubygems/remote_fetcher.rb +20 -31
- data/lib/rubygems/request.rb +2 -0
- data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
- data/lib/rubygems/resolver/api_set.rb +1 -1
- data/lib/rubygems/resolver/api_specification.rb +1 -1
- data/lib/rubygems/server.rb +1 -1
- data/lib/rubygems/source.rb +7 -1
- data/lib/rubygems/source_list.rb +2 -0
- data/lib/rubygems/specification.rb +12 -8
- data/lib/rubygems/specification_policy.rb +53 -30
- data/lib/rubygems/test_case.rb +60 -0
- data/lib/rubygems/uri_formatter.rb +0 -1
- data/lib/rubygems/uri_parser.rb +36 -0
- data/lib/rubygems/uri_parsing.rb +23 -0
- data/lib/rubygems/util.rb +7 -1
- data/lib/rubygems/version.rb +1 -1
- data/rubygems-update.gemspec +1 -8
- data/test/rubygems/specifications/rubyforge-0.0.1.gemspec +14 -0
- data/test/rubygems/test_gem.rb +90 -46
- data/test/rubygems/test_gem_command.rb +38 -9
- data/test/rubygems/test_gem_commands_build_command.rb +18 -1
- data/test/rubygems/test_gem_commands_generate_index_command.rb +37 -1
- data/test/rubygems/test_gem_commands_help_command.rb +1 -6
- data/test/rubygems/test_gem_commands_server_command.rb +6 -2
- data/test/rubygems/test_gem_commands_setup_command.rb +56 -10
- data/test/rubygems/test_gem_commands_sources_command.rb +113 -1
- data/test/rubygems/test_gem_commands_uninstall_command.rb +1 -0
- data/test/rubygems/test_gem_gem_runner.rb +3 -1
- data/test/rubygems/test_gem_indexer.rb +1 -1
- data/test/rubygems/test_gem_installer.rb +10 -23
- data/test/rubygems/test_gem_package.rb +3 -8
- data/test/rubygems/test_gem_package_tar_writer.rb +5 -0
- data/test/rubygems/test_gem_request_set.rb +52 -0
- data/test/rubygems/test_gem_source.rb +14 -0
- data/test/rubygems/test_gem_specification.rb +74 -54
- data/test/rubygems/test_gem_stub_specification.rb +0 -1
- data/test/rubygems/test_project_sanity.rb +0 -43
- data/test/rubygems/test_remote_fetch_error.rb +1 -1
- data/test/rubygems/test_require.rb +41 -42
- data/util/bisect +0 -21
- data/util/ci.sh +1 -1
- data/util/update_changelog.rb +7 -10
- metadata +27 -93
- data/bundler/lib/bundler/gem_remote_fetcher.rb +0 -43
- data/bundler/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +0 -5
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +0 -12
@@ -43,6 +43,8 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|
43
43
|
|
44
44
|
source = Gem::Source.new source_uri
|
45
45
|
|
46
|
+
check_typo_squatting(source)
|
47
|
+
|
46
48
|
begin
|
47
49
|
if Gem.sources.include? source
|
48
50
|
say "source #{source_uri} already present in the cache"
|
@@ -62,6 +64,18 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
67
|
+
def check_typo_squatting(source)
|
68
|
+
if source.typo_squatting?("rubygems.org")
|
69
|
+
question = <<-QUESTION.chomp
|
70
|
+
#{source.uri.to_s} is too similar to https://rubygems.org
|
71
|
+
|
72
|
+
Do you want to add this source?
|
73
|
+
QUESTION
|
74
|
+
|
75
|
+
terminate_interaction 1 unless ask_yes_no question
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
65
79
|
def check_rubygems_https(source_uri) # :nodoc:
|
66
80
|
uri = URI source_uri
|
67
81
|
|
@@ -122,7 +136,7 @@ RubyGems has been configured to serve gems via the following URLs through
|
|
122
136
|
its history:
|
123
137
|
|
124
138
|
* http://gems.rubyforge.org (RubyGems 1.3.6 and earlier)
|
125
|
-
*
|
139
|
+
* https://rubygems.org/ (RubyGems 1.3.7 through 1.8.25)
|
126
140
|
* https://rubygems.org (RubyGems 2.0.1 and newer)
|
127
141
|
|
128
142
|
Since all of these sources point to the same set of gems you only need one
|
@@ -139,8 +153,8 @@ before it is added.
|
|
139
153
|
|
140
154
|
To remove a source use the --remove argument:
|
141
155
|
|
142
|
-
$ gem sources --remove
|
143
|
-
|
156
|
+
$ gem sources --remove https://rubygems.org/
|
157
|
+
https://rubygems.org/ removed from sources
|
144
158
|
|
145
159
|
EOF
|
146
160
|
end
|
@@ -143,7 +143,7 @@ that is a dependency of an existing gem. You can use the
|
|
143
143
|
uninstall_gem spec.name
|
144
144
|
end
|
145
145
|
|
146
|
-
alert "Uninstalled all gems in #{options[:install_dir]}"
|
146
|
+
alert "Uninstalled all gems in #{options[:install_dir] || Gem.dir}"
|
147
147
|
end
|
148
148
|
|
149
149
|
def uninstall_specific
|
@@ -46,7 +46,7 @@ module Kernel
|
|
46
46
|
$LOAD_PATH[0...Gem.load_path_insert_index || -1].each do |lp|
|
47
47
|
safe_lp = lp.dup.tap(&Gem::UNTAINT)
|
48
48
|
begin
|
49
|
-
if File.symlink? safe_lp # for
|
49
|
+
if File.symlink? safe_lp # for backward compatibility
|
50
50
|
next
|
51
51
|
end
|
52
52
|
rescue SecurityError
|
@@ -6,12 +6,16 @@ if RUBY_VERSION >= "2.5"
|
|
6
6
|
module Kernel
|
7
7
|
path = "#{__dir__}/" # Frames to be skipped start with this path.
|
8
8
|
|
9
|
-
# Suppress "method redefined" warning
|
10
|
-
original_warn = instance_method(:warn)
|
11
|
-
Module.new {define_method(:warn, original_warn)}
|
12
|
-
|
13
9
|
original_warn = method(:warn)
|
14
10
|
|
11
|
+
remove_method :warn
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
remove_method :warn
|
16
|
+
|
17
|
+
end
|
18
|
+
|
15
19
|
module_function define_method(:warn) {|*messages, **kw|
|
16
20
|
unless uplevel = kw[:uplevel]
|
17
21
|
if Gem.java_platform?
|
data/lib/rubygems/ext/builder.rb
CHANGED
@@ -6,7 +6,6 @@
|
|
6
6
|
#++
|
7
7
|
|
8
8
|
require 'rubygems/user_interaction'
|
9
|
-
require "open3"
|
10
9
|
|
11
10
|
class Gem::Ext::Builder
|
12
11
|
|
@@ -68,7 +67,10 @@ class Gem::Ext::Builder
|
|
68
67
|
results << "current directory: #{Dir.pwd}"
|
69
68
|
results << (command.respond_to?(:shelljoin) ? command.shelljoin : command)
|
70
69
|
|
71
|
-
|
70
|
+
require "open3"
|
71
|
+
# Set $SOURCE_DATE_EPOCH for the subprocess.
|
72
|
+
env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string}
|
73
|
+
output, status = Open3.capture2e(env, *command)
|
72
74
|
if verbose
|
73
75
|
puts output
|
74
76
|
else
|
@@ -4,6 +4,7 @@ require 'rubygems/request'
|
|
4
4
|
require 'rubygems/request/connection_pools'
|
5
5
|
require 'rubygems/s3_uri_signer'
|
6
6
|
require 'rubygems/uri_formatter'
|
7
|
+
require 'rubygems/uri_parsing'
|
7
8
|
require 'rubygems/user_interaction'
|
8
9
|
require 'resolv'
|
9
10
|
require 'rubygems/deprecate'
|
@@ -17,12 +18,16 @@ class Gem::RemoteFetcher
|
|
17
18
|
include Gem::UserInteraction
|
18
19
|
extend Gem::Deprecate
|
19
20
|
|
21
|
+
include Gem::UriParsing
|
22
|
+
|
20
23
|
##
|
21
24
|
# A FetchError exception wraps up the various possible IO and HTTP failures
|
22
25
|
# that could happen while downloading from the internet.
|
23
26
|
|
24
27
|
class FetchError < Gem::Exception
|
25
28
|
|
29
|
+
include Gem::UriParsing
|
30
|
+
|
26
31
|
##
|
27
32
|
# The URI which was being accessed when the exception happened.
|
28
33
|
|
@@ -30,13 +35,12 @@ class Gem::RemoteFetcher
|
|
30
35
|
|
31
36
|
def initialize(message, uri)
|
32
37
|
super message
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
38
|
+
|
39
|
+
uri = parse_uri(uri)
|
40
|
+
|
41
|
+
uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password
|
42
|
+
|
43
|
+
@uri = uri.to_s
|
40
44
|
end
|
41
45
|
|
42
46
|
def to_s # :nodoc:
|
@@ -107,7 +111,7 @@ class Gem::RemoteFetcher
|
|
107
111
|
|
108
112
|
spec, source = found.max_by { |(s,_)| s.version }
|
109
113
|
|
110
|
-
download spec, source.uri
|
114
|
+
download spec, source.uri
|
111
115
|
end
|
112
116
|
|
113
117
|
##
|
@@ -130,18 +134,7 @@ class Gem::RemoteFetcher
|
|
130
134
|
|
131
135
|
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
|
132
136
|
|
133
|
-
|
134
|
-
# It should also be considered that source_uri may already be
|
135
|
-
# a valid URI with escaped characters. e.g. "{DESede}" is encoded
|
136
|
-
# as "%7BDESede%7D". If this is escaped again the percentage
|
137
|
-
# symbols will be escaped.
|
138
|
-
unless source_uri.is_a?(URI::Generic)
|
139
|
-
begin
|
140
|
-
source_uri = URI.parse(source_uri)
|
141
|
-
rescue
|
142
|
-
source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri.to_s))
|
143
|
-
end
|
144
|
-
end
|
137
|
+
source_uri = parse_uri(source_uri)
|
145
138
|
|
146
139
|
scheme = source_uri.scheme
|
147
140
|
|
@@ -159,7 +152,7 @@ class Gem::RemoteFetcher
|
|
159
152
|
remote_gem_path = source_uri + "gems/#{gem_file_name}"
|
160
153
|
|
161
154
|
self.cache_update_path remote_gem_path, local_gem_path
|
162
|
-
rescue
|
155
|
+
rescue FetchError
|
163
156
|
raise if spec.original_platform == spec.platform
|
164
157
|
|
165
158
|
alternate_name = "#{spec.original_name}.gem"
|
@@ -236,7 +229,7 @@ class Gem::RemoteFetcher
|
|
236
229
|
unless location = response['Location']
|
237
230
|
raise FetchError.new("redirecting but no redirect location was given", uri)
|
238
231
|
end
|
239
|
-
location =
|
232
|
+
location = parse_uri location
|
240
233
|
|
241
234
|
if https?(uri) && !https?(location)
|
242
235
|
raise FetchError.new("redirecting to non-https resource: #{location}", uri)
|
@@ -254,9 +247,7 @@ class Gem::RemoteFetcher
|
|
254
247
|
# Downloads +uri+ and returns it as a String.
|
255
248
|
|
256
249
|
def fetch_path(uri, mtime = nil, head = false)
|
257
|
-
uri =
|
258
|
-
|
259
|
-
raise ArgumentError, "bad uri: #{uri}" unless uri
|
250
|
+
uri = parse_uri uri
|
260
251
|
|
261
252
|
unless uri.scheme
|
262
253
|
raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
|
@@ -268,21 +259,19 @@ class Gem::RemoteFetcher
|
|
268
259
|
begin
|
269
260
|
data = Gem::Util.gunzip data
|
270
261
|
rescue Zlib::GzipFile::Error
|
271
|
-
raise FetchError.new("server did not return a valid file", uri
|
262
|
+
raise FetchError.new("server did not return a valid file", uri)
|
272
263
|
end
|
273
264
|
end
|
274
265
|
|
275
266
|
data
|
276
|
-
rescue FetchError
|
277
|
-
raise
|
278
267
|
rescue Timeout::Error
|
279
|
-
raise UnknownHostError.new('timed out', uri
|
268
|
+
raise UnknownHostError.new('timed out', uri)
|
280
269
|
rescue IOError, SocketError, SystemCallError,
|
281
270
|
*(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e
|
282
271
|
if e.message =~ /getaddrinfo/
|
283
|
-
raise UnknownHostError.new('no such name', uri
|
272
|
+
raise UnknownHostError.new('no such name', uri)
|
284
273
|
else
|
285
|
-
raise FetchError.new("#{e.class}: #{e}", uri
|
274
|
+
raise FetchError.new("#{e.class}: #{e}", uri)
|
286
275
|
end
|
287
276
|
end
|
288
277
|
|
data/lib/rubygems/request.rb
CHANGED
@@ -19,6 +19,7 @@ class Gem::Request
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.proxy_uri(proxy) # :nodoc:
|
22
|
+
require "uri"
|
22
23
|
case proxy
|
23
24
|
when :no_proxy then nil
|
24
25
|
when URI::HTTP then proxy
|
@@ -173,6 +174,7 @@ class Gem::Request
|
|
173
174
|
:no_proxy : get_proxy_from_env('http')
|
174
175
|
end
|
175
176
|
|
177
|
+
require "uri"
|
176
178
|
uri = URI(Gem::UriFormatter.new(env_proxy).normalize)
|
177
179
|
|
178
180
|
if uri and uri.user.nil? and uri.password.nil?
|
@@ -23,7 +23,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
|
23
23
|
##
|
24
24
|
# Creates a new APISet that will retrieve gems from +uri+ using the RubyGems
|
25
25
|
# API URL +dep_uri+ which is described at
|
26
|
-
#
|
26
|
+
# https://guides.rubygems.org/rubygems-org-api
|
27
27
|
|
28
28
|
def initialize(dep_uri = 'https://rubygems.org/api/v1/dependencies')
|
29
29
|
super()
|
@@ -11,7 +11,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
|
|
11
11
|
# Creates an APISpecification for the given +set+ from the rubygems.org
|
12
12
|
# +api_data+.
|
13
13
|
#
|
14
|
-
# See
|
14
|
+
# See https://guides.rubygems.org/rubygems-org-api/#misc_methods for the
|
15
15
|
# format of the +api_data+.
|
16
16
|
|
17
17
|
def initialize(set, api_data)
|
data/lib/rubygems/server.rb
CHANGED
@@ -661,7 +661,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
661
661
|
"only_one_executable" => true,
|
662
662
|
"full_name" => "rubygems-#{Gem::VERSION}",
|
663
663
|
"has_deps" => false,
|
664
|
-
"homepage" => "
|
664
|
+
"homepage" => "https://guides.rubygems.org/",
|
665
665
|
"name" => 'rubygems',
|
666
666
|
"ri_installed" => true,
|
667
667
|
"summary" => "RubyGems itself",
|
data/lib/rubygems/source.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
autoload :FileUtils, 'fileutils'
|
3
|
-
autoload :URI, 'uri'
|
4
3
|
|
4
|
+
require "rubygems/text"
|
5
5
|
##
|
6
6
|
# A Source knows how to list and fetch gems from a RubyGems marshal index.
|
7
7
|
#
|
@@ -11,6 +11,7 @@ autoload :URI, 'uri'
|
|
11
11
|
class Gem::Source
|
12
12
|
|
13
13
|
include Comparable
|
14
|
+
include Gem::Text
|
14
15
|
|
15
16
|
FILES = { # :nodoc:
|
16
17
|
:released => 'specs',
|
@@ -219,6 +220,11 @@ class Gem::Source
|
|
219
220
|
end
|
220
221
|
end
|
221
222
|
|
223
|
+
def typo_squatting?(host, distance_threshold=4)
|
224
|
+
return if @uri.host.nil?
|
225
|
+
levenshtein_distance(@uri.host, host) <= distance_threshold
|
226
|
+
end
|
227
|
+
|
222
228
|
end
|
223
229
|
|
224
230
|
require 'rubygems/source/git'
|
data/lib/rubygems/source_list.rb
CHANGED
@@ -193,6 +193,12 @@ class Gem::Specification < Gem::BasicSpecification
|
|
193
193
|
@@spec_with_requirable_file = {}
|
194
194
|
@@active_stub_with_requirable_file = {}
|
195
195
|
|
196
|
+
# Tracking removed method calls to warn users during build time.
|
197
|
+
REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc:
|
198
|
+
def removed_method_calls
|
199
|
+
@removed_method_calls ||= []
|
200
|
+
end
|
201
|
+
|
196
202
|
######################################################################
|
197
203
|
# :section: Required gemspec attributes
|
198
204
|
|
@@ -726,14 +732,6 @@ class Gem::Specification < Gem::BasicSpecification
|
|
726
732
|
|
727
733
|
attr_writer :original_platform # :nodoc:
|
728
734
|
|
729
|
-
##
|
730
|
-
# Deprecated and ignored.
|
731
|
-
#
|
732
|
-
# Formerly used to set rubyforge project.
|
733
|
-
|
734
|
-
attr_writer :rubyforge_project
|
735
|
-
deprecate :rubyforge_project=, :none, 2019, 12
|
736
|
-
|
737
735
|
##
|
738
736
|
# The Gem::Specification version of this gemspec.
|
739
737
|
#
|
@@ -2107,9 +2105,15 @@ class Gem::Specification < Gem::BasicSpecification
|
|
2107
2105
|
end
|
2108
2106
|
|
2109
2107
|
##
|
2108
|
+
# Track removed method calls to warn about during build time.
|
2110
2109
|
# Warn about unknown attributes while loading a spec.
|
2111
2110
|
|
2112
2111
|
def method_missing(sym, *a, &b) # :nodoc:
|
2112
|
+
if REMOVED_METHODS.include?(sym)
|
2113
|
+
removed_method_calls << sym
|
2114
|
+
return
|
2115
|
+
end
|
2116
|
+
|
2113
2117
|
if @specification_version > CURRENT_SPECIFICATION_VERSION and
|
2114
2118
|
sym.to_s =~ /=$/
|
2115
2119
|
warn "ignoring #{sym} loading #{full_name}" if $DEBUG
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
require 'uri'
|
3
1
|
require 'rubygems/user_interaction'
|
4
2
|
|
5
|
-
class Gem::SpecificationPolicy
|
3
|
+
class Gem::SpecificationPolicy
|
6
4
|
|
7
5
|
include Gem::UserInteraction
|
8
6
|
|
@@ -25,7 +23,7 @@ class Gem::SpecificationPolicy < SimpleDelegator
|
|
25
23
|
def initialize(specification)
|
26
24
|
@warnings = 0
|
27
25
|
|
28
|
-
|
26
|
+
@specification = specification
|
29
27
|
end
|
30
28
|
|
31
29
|
##
|
@@ -51,7 +49,7 @@ class Gem::SpecificationPolicy < SimpleDelegator
|
|
51
49
|
|
52
50
|
validate_require_paths
|
53
51
|
|
54
|
-
keep_only_files_and_directories
|
52
|
+
@specification.keep_only_files_and_directories
|
55
53
|
|
56
54
|
validate_non_files
|
57
55
|
|
@@ -77,6 +75,8 @@ class Gem::SpecificationPolicy < SimpleDelegator
|
|
77
75
|
|
78
76
|
validate_dependencies
|
79
77
|
|
78
|
+
validate_removed_attributes
|
79
|
+
|
80
80
|
if @warnings > 0
|
81
81
|
if strict
|
82
82
|
error "specification has warnings"
|
@@ -92,6 +92,8 @@ class Gem::SpecificationPolicy < SimpleDelegator
|
|
92
92
|
# Implementation for Specification#validate_metadata
|
93
93
|
|
94
94
|
def validate_metadata
|
95
|
+
metadata = @specification.metadata
|
96
|
+
|
95
97
|
unless Hash === metadata
|
96
98
|
error 'metadata must be a hash'
|
97
99
|
end
|
@@ -130,7 +132,7 @@ class Gem::SpecificationPolicy < SimpleDelegator
|
|
130
132
|
|
131
133
|
error_messages = []
|
132
134
|
warning_messages = []
|
133
|
-
dependencies.each do |dep|
|
135
|
+
@specification.dependencies.each do |dep|
|
134
136
|
if prev = seen[dep.type][dep.name]
|
135
137
|
error_messages << <<-MESSAGE
|
136
138
|
duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
@@ -145,7 +147,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
145
147
|
end
|
146
148
|
|
147
149
|
warning_messages << "prerelease dependency on #{dep} is not recommended" if
|
148
|
-
prerelease_dep &&
|
150
|
+
prerelease_dep && !@specification.version.prerelease?
|
149
151
|
|
150
152
|
open_ended = dep.requirement.requirements.all? do |op, version|
|
151
153
|
not version.prerelease? and (op == '>' or op == '>=')
|
@@ -190,14 +192,14 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
190
192
|
def validate_permissions
|
191
193
|
return if Gem.win_platform?
|
192
194
|
|
193
|
-
files.each do |file|
|
195
|
+
@specification.files.each do |file|
|
194
196
|
next unless File.file?(file)
|
195
197
|
next if File.stat(file).mode & 0444 == 0444
|
196
198
|
warning "#{file} is not world-readable"
|
197
199
|
end
|
198
200
|
|
199
|
-
executables.each do |name|
|
200
|
-
exec = File.join bindir, name
|
201
|
+
@specification.executables.each do |name|
|
202
|
+
exec = File.join @specification.bindir, name
|
201
203
|
next unless File.file?(exec)
|
202
204
|
next if File.stat(exec).executable?
|
203
205
|
warning "#{exec} is not executable"
|
@@ -208,7 +210,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
208
210
|
|
209
211
|
def validate_nil_attributes
|
210
212
|
nil_attributes = Gem::Specification.non_nil_attributes.select do |attrname|
|
211
|
-
|
213
|
+
@specification.instance_variable_get("@#{attrname}").nil?
|
212
214
|
end
|
213
215
|
return if nil_attributes.empty?
|
214
216
|
error "#{nil_attributes.join ', '} must not be nil"
|
@@ -216,6 +218,9 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
216
218
|
|
217
219
|
def validate_rubygems_version
|
218
220
|
return unless packaging
|
221
|
+
|
222
|
+
rubygems_version = @specification.rubygems_version
|
223
|
+
|
219
224
|
return if rubygems_version == Gem::VERSION
|
220
225
|
|
221
226
|
error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
|
@@ -223,13 +228,15 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
223
228
|
|
224
229
|
def validate_required_attributes
|
225
230
|
Gem::Specification.required_attributes.each do |symbol|
|
226
|
-
unless send symbol
|
231
|
+
unless @specification.send symbol
|
227
232
|
error "missing value for attribute #{symbol}"
|
228
233
|
end
|
229
234
|
end
|
230
235
|
end
|
231
236
|
|
232
237
|
def validate_name
|
238
|
+
name = @specification.name
|
239
|
+
|
233
240
|
if !name.is_a?(String)
|
234
241
|
error "invalid value for attribute name: \"#{name.inspect}\" must be a string"
|
235
242
|
elsif name !~ /[a-zA-Z]/
|
@@ -242,14 +249,15 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
242
249
|
end
|
243
250
|
|
244
251
|
def validate_require_paths
|
245
|
-
return unless raw_require_paths.empty?
|
252
|
+
return unless @specification.raw_require_paths.empty?
|
246
253
|
|
247
254
|
error 'specification must have at least one require_path'
|
248
255
|
end
|
249
256
|
|
250
257
|
def validate_non_files
|
251
258
|
return unless packaging
|
252
|
-
|
259
|
+
|
260
|
+
non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x)}
|
253
261
|
|
254
262
|
unless non_files.empty?
|
255
263
|
error "[\"#{non_files.join "\", \""}\"] are not files"
|
@@ -257,18 +265,22 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
257
265
|
end
|
258
266
|
|
259
267
|
def validate_self_inclusion_in_files_list
|
260
|
-
|
268
|
+
file_name = @specification.file_name
|
269
|
+
|
270
|
+
return unless @specification.files.include?(file_name)
|
261
271
|
|
262
|
-
error "#{full_name} contains itself (#{file_name}), check your files list"
|
272
|
+
error "#{@specification.full_name} contains itself (#{file_name}), check your files list"
|
263
273
|
end
|
264
274
|
|
265
275
|
def validate_specification_version
|
266
|
-
return if specification_version.is_a?(Integer)
|
276
|
+
return if @specification.specification_version.is_a?(Integer)
|
267
277
|
|
268
278
|
error 'specification_version must be an Integer (did you mean version?)'
|
269
279
|
end
|
270
280
|
|
271
281
|
def validate_platform
|
282
|
+
platform = @specification.platform
|
283
|
+
|
272
284
|
case platform
|
273
285
|
when Gem::Platform, Gem::Platform::RUBY # ok
|
274
286
|
else
|
@@ -283,7 +295,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
283
295
|
end
|
284
296
|
|
285
297
|
def validate_array_attribute(field)
|
286
|
-
val =
|
298
|
+
val = @specification.send(field)
|
287
299
|
klass = case field
|
288
300
|
when :dependencies then
|
289
301
|
Gem::Dependency
|
@@ -298,12 +310,14 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
298
310
|
end
|
299
311
|
|
300
312
|
def validate_authors_field
|
301
|
-
return unless authors.empty?
|
313
|
+
return unless @specification.authors.empty?
|
302
314
|
|
303
315
|
error "authors may not be empty"
|
304
316
|
end
|
305
317
|
|
306
318
|
def validate_licenses
|
319
|
+
licenses = @specification.licenses
|
320
|
+
|
307
321
|
licenses.each do |license|
|
308
322
|
if license.length > 64
|
309
323
|
error "each license must be 64 characters or less"
|
@@ -331,24 +345,27 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
331
345
|
HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze
|
332
346
|
|
333
347
|
def validate_lazy_metadata
|
334
|
-
unless authors.grep(LAZY_PATTERN).empty?
|
348
|
+
unless @specification.authors.grep(LAZY_PATTERN).empty?
|
335
349
|
error "#{LAZY} is not an author"
|
336
350
|
end
|
337
351
|
|
338
|
-
unless Array(email).grep(LAZY_PATTERN).empty?
|
352
|
+
unless Array(@specification.email).grep(LAZY_PATTERN).empty?
|
339
353
|
error "#{LAZY} is not an email"
|
340
354
|
end
|
341
355
|
|
342
|
-
if description =~ LAZY_PATTERN
|
356
|
+
if @specification.description =~ LAZY_PATTERN
|
343
357
|
error "#{LAZY} is not a description"
|
344
358
|
end
|
345
359
|
|
346
|
-
if summary =~ LAZY_PATTERN
|
360
|
+
if @specification.summary =~ LAZY_PATTERN
|
347
361
|
error "#{LAZY} is not a summary"
|
348
362
|
end
|
349
363
|
|
364
|
+
homepage = @specification.homepage
|
365
|
+
|
350
366
|
# Make sure a homepage is valid HTTP/HTTPS URI
|
351
367
|
if homepage and not homepage.empty?
|
368
|
+
require 'uri'
|
352
369
|
begin
|
353
370
|
homepage_uri = URI.parse(homepage)
|
354
371
|
unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class
|
@@ -365,34 +382,40 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
365
382
|
validate_attribute_present(attribute)
|
366
383
|
end
|
367
384
|
|
368
|
-
if description == summary
|
385
|
+
if @specification.description == @specification.summary
|
369
386
|
warning "description and summary are identical"
|
370
387
|
end
|
371
388
|
|
372
389
|
# TODO: raise at some given date
|
373
|
-
warning "deprecated autorequire specified" if autorequire
|
390
|
+
warning "deprecated autorequire specified" if @specification.autorequire
|
374
391
|
|
375
|
-
executables.each do |executable|
|
392
|
+
@specification.executables.each do |executable|
|
376
393
|
validate_shebang_line_in(executable)
|
377
394
|
end
|
378
395
|
|
379
|
-
files.select { |f| File.symlink?(f) }.each do |file|
|
396
|
+
@specification.files.select { |f| File.symlink?(f) }.each do |file|
|
380
397
|
warning "#{file} is a symlink, which is not supported on all platforms"
|
381
398
|
end
|
382
399
|
end
|
383
400
|
|
384
401
|
def validate_attribute_present(attribute)
|
385
|
-
value =
|
402
|
+
value = @specification.send attribute
|
386
403
|
warning("no #{attribute} specified") if value.nil? || value.empty?
|
387
404
|
end
|
388
405
|
|
389
406
|
def validate_shebang_line_in(executable)
|
390
|
-
executable_path = File.join(bindir, executable)
|
407
|
+
executable_path = File.join(@specification.bindir, executable)
|
391
408
|
return if File.read(executable_path, 2) == '#!'
|
392
409
|
|
393
410
|
warning "#{executable_path} is missing #! line"
|
394
411
|
end
|
395
412
|
|
413
|
+
def validate_removed_attributes # :nodoc:
|
414
|
+
@specification.removed_method_calls.each do |attr|
|
415
|
+
warning("#{attr} is deprecated and ignored. Please remove this from your gemspec to ensure that your gem continues to build in the future.")
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
396
419
|
def warning(statement) # :nodoc:
|
397
420
|
@warnings += 1
|
398
421
|
|
@@ -406,7 +429,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
406
429
|
end
|
407
430
|
|
408
431
|
def help_text # :nodoc:
|
409
|
-
"See
|
432
|
+
"See https://guides.rubygems.org/specification-reference/ for help"
|
410
433
|
end
|
411
434
|
|
412
435
|
end
|