rubygems-update 3.1.0.pre3 → 3.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|