diff options
Diffstat (limited to 'lib')
190 files changed, 5588 insertions, 572 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index 7bb6690e52..59a1107bb7 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -200,12 +200,13 @@ module Bundler # # @param unlock [Hash, Boolean, nil] Gems that have been requested # to be updated or true if all gems should be updated + # @param lockfile [Pathname] Path to Gemfile.lock # @return [Bundler::Definition] - def definition(unlock = nil) + def definition(unlock = nil, lockfile = default_lockfile) @definition = nil if unlock @definition ||= begin configure - Definition.build(default_gemfile, default_lockfile, unlock) + Definition.build(default_gemfile, lockfile, unlock) end end diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index d93feb7b55..3640536762 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -620,7 +620,7 @@ module Bundler method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)" method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status" method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major" - method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated" + method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated" method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler" def lock require_relative "cli/lock" @@ -785,7 +785,7 @@ module Bundler return unless SharedHelpers.md5_available? latest = Fetcher::CompactIndex. - new(nil, Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil, nil). + new(nil, Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org")), nil, nil). send(:compact_index_client). instance_variable_get(:@cache). dependencies("bundler"). diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb index ad41ebf4b4..8ce138df96 100644 --- a/lib/bundler/cli/binstubs.rb +++ b/lib/bundler/cli/binstubs.rb @@ -45,7 +45,7 @@ module Bundler next end - Bundler.settings.temporary(path: (Bundler.settings[:path] || Bundler.root)) do + Bundler.settings.temporary(path: Bundler.settings[:path] || Bundler.root) do installer.generate_standalone_bundler_executable_stubs(spec, installer_opts) end else diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index 98192d952e..f0bb3aab18 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -437,7 +437,7 @@ module Bundler end def required_ruby_version - "2.6.0" + "3.0.0" end def rubocop_version diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb index 7247121df5..dac3d2a09a 100644 --- a/lib/bundler/cli/lock.rb +++ b/lib/bundler/cli/lock.rb @@ -33,8 +33,11 @@ module Bundler update = { bundler: bundler } end + file = options[:lockfile] + file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile + Bundler.settings.temporary(frozen: false) do - definition = Bundler.definition(update) + definition = Bundler.definition(update, file) Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update] @@ -60,10 +63,8 @@ module Bundler if print puts definition.to_lock else - file = options[:lockfile] - file = file ? File.expand_path(file) : Bundler.default_lockfile puts "Writing lockfile to #{file}" - definition.lock(file) + definition.lock end end diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb index 1a33b5fc27..fd61ef0d95 100644 --- a/lib/bundler/cli/plugin.rb +++ b/lib/bundler/cli/plugin.rb @@ -5,14 +5,15 @@ module Bundler class CLI::Plugin < Thor desc "install PLUGINS", "Install the plugin from the source" long_desc <<-D - Install plugins either from the rubygems source provided (with --source option) or from a git source provided with --git (for remote repos) or --local_git (for local repos). If no sources are provided, it uses Gem.sources + Install plugins either from the rubygems source provided (with --source option), from a git source provided with --git, or a local path provided with --path. If no sources are provided, it uses Gem.sources D method_option "source", type: :string, default: nil, banner: "URL of the RubyGems source to fetch the plugin from" method_option "version", type: :string, default: nil, banner: "The version of the plugin to fetch" method_option "git", type: :string, default: nil, banner: "URL of the git repo to fetch from" - method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from" + method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (deprecated)" method_option "branch", type: :string, default: nil, banner: "The git branch to checkout" method_option "ref", type: :string, default: nil, banner: "The git revision to check out" + method_option "path", type: :string, default: nil, banner: "Path of a local gem to directly use" def install(*plugins) Bundler::Plugin.install(plugins, options) end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 0b0e63f77e..c8faf77b3b 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -320,38 +320,26 @@ module Bundler dependencies.map(&:groups).flatten.uniq end - def lock(file, preserve_unknown_sections = false) - return if Definition.no_lock - - contents = to_lock - - # Convert to \r\n if the existing lock has them - # i.e., Windows with `git config core.autocrlf=true` - contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n") - - if @locked_bundler_version - locked_major = @locked_bundler_version.segments.first - current_major = bundler_version_to_lock.segments.first - - updating_major = locked_major < current_major - end + def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false) + if [true, false, nil].include?(file_or_preserve_unknown_sections) + target_lockfile = lockfile || Bundler.default_lockfile + preserve_unknown_sections = file_or_preserve_unknown_sections + else + target_lockfile = file_or_preserve_unknown_sections + preserve_unknown_sections = preserve_unknown_sections_or_unused - preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler)) + suggestion = if target_lockfile == lockfile + "To fix this warning, remove it from the `Definition#lock` call." + else + "Instead, instantiate a new definition passing `#{target_lockfile}`, and call `lock` without a file argument on that definition" + end - if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections) - return if Bundler.frozen_bundle? - SharedHelpers.filesystem_access(file) { FileUtils.touch(file) } - return - end + msg = "`Definition#lock` was passed a target file argument. #{suggestion}" - if Bundler.frozen_bundle? - Bundler.ui.error "Cannot write a changed lockfile while frozen." - return + Bundler::SharedHelpers.major_deprecation 2, msg end - SharedHelpers.filesystem_access(file) do |p| - File.open(p, "wb") {|f| f.puts(contents) } - end + write_lock(target_lockfile, preserve_unknown_sections) end def locked_ruby_version @@ -518,7 +506,45 @@ module Bundler end def lockfile_exists? - lockfile && File.exist?(lockfile) + file_exists?(lockfile) + end + + def file_exists?(file) + file && File.exist?(file) + end + + def write_lock(file, preserve_unknown_sections) + return if Definition.no_lock + + contents = to_lock + + # Convert to \r\n if the existing lock has them + # i.e., Windows with `git config core.autocrlf=true` + contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n") + + if @locked_bundler_version + locked_major = @locked_bundler_version.segments.first + current_major = bundler_version_to_lock.segments.first + + updating_major = locked_major < current_major + end + + preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler)) + + if file_exists?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections) + return if Bundler.frozen_bundle? + SharedHelpers.filesystem_access(file) { FileUtils.touch(file) } + return + end + + if Bundler.frozen_bundle? + Bundler.ui.error "Cannot write a changed lockfile while frozen." + return + end + + SharedHelpers.filesystem_access(file) do |p| + File.open(p, "wb") {|f| f.puts(contents) } + end end def resolver diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 1460b9f52f..6af80fb31f 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -19,6 +19,7 @@ module Bundler platform platforms type source install_if gemfile force_ruby_platform].freeze GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z} + GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z} attr_reader :gemspecs, :gemfile attr_accessor :dependencies @@ -46,7 +47,7 @@ module Bundler @gemfile = expanded_gemfile_path @gemfiles << expanded_gemfile_path contents ||= Bundler.read_file(@gemfile.to_s) - instance_eval(contents, gemfile.to_s, 1) + instance_eval(contents, @gemfile.to_s, 1) rescue Exception => e # rubocop:disable Lint/RescueException message = "There was an error " \ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \ @@ -308,6 +309,20 @@ module Bundler repo_name ||= user_name "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git" end + + git_source(:gitlab) do |repo_name| + if repo_name =~ GITLAB_MERGE_REQUEST_URL + { + "git" => "https://gitlab.com/#{$1}.git", + "branch" => nil, + "ref" => "refs/merge-requests/#{$2}/head", + "tag" => nil, + } + else + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://gitlab.com/#{repo_name}.git" + end + end end def with_source(source) diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb index 57013f5d50..c4c1b53fa4 100644 --- a/lib/bundler/environment_preserver.rb +++ b/lib/bundler/environment_preserver.rb @@ -58,9 +58,9 @@ module Bundler env = @original.clone @keys.each do |key| value = env[key] - if !value.nil? && !value.empty? + if !value.nil? env[@prefix + key] ||= value - elsif value.nil? + else env[@prefix + key] ||= INTENTIONALLY_NIL end end @@ -72,7 +72,7 @@ module Bundler env = @original.clone @keys.each do |key| value_original = env[@prefix + key] - next if value_original.nil? || value_original.empty? + next if value_original.nil? if value_original == INTENTIONALLY_NIL env.delete(key) else diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index 42bd2c0984..6288b22dcd 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -111,7 +111,7 @@ module Bundler spec -= [nil, "ruby", ""] spec_file_name = "#{spec.join "-"}.gemspec" - uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") + uri = Gem::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") spec = if uri.scheme == "file" path = Gem::Util.correct_for_windows_path(uri.path) Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path)) @@ -255,7 +255,7 @@ module Bundler con = Gem::Net::HTTP::Persistent.new name: "bundler", proxy: :ENV if gem_proxy = Gem.configuration[:http_proxy] - con.proxy = Bundler::URI.parse(gem_proxy) if gem_proxy != :no_proxy + con.proxy = Gem::URI.parse(gem_proxy) if gem_proxy != :no_proxy end if remote_uri.scheme == "https" diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb index b5282a322e..868b39b959 100644 --- a/lib/bundler/fetcher/downloader.rb +++ b/lib/bundler/fetcher/downloader.rb @@ -23,7 +23,7 @@ module Bundler when Gem::Net::HTTPSuccess, Gem::Net::HTTPNotModified response when Gem::Net::HTTPRedirection - new_uri = Bundler::URI.parse(response["location"]) + new_uri = Gem::URI.parse(response["location"]) if new_uri.host == uri.host new_uri.user = uri.user new_uri.password = uri.password diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb index c7eacd1930..ecc65b4956 100644 --- a/lib/bundler/gem_version_promoter.rb +++ b/lib/bundler/gem_version_promoter.rb @@ -45,17 +45,37 @@ module Bundler # Given a Resolver::Package and an Array of Specifications of available # versions for a gem, this method will return the Array of Specifications - # sorted (and possibly truncated if strict is true) in an order to give - # preference to the current level (:major, :minor or :patch) when resolution - # is deciding what versions best resolve all dependencies in the bundle. + # sorted in an order to give preference to the current level (:major, :minor + # or :patch) when resolution is deciding what versions best resolve all + # dependencies in the bundle. # @param package [Resolver::Package] The package being resolved. # @param specs [Specification] An array of Specifications for the package. - # @return [Specification] A new instance of the Specification Array sorted and - # possibly filtered. + # @return [Specification] A new instance of the Specification Array sorted. def sort_versions(package, specs) - specs = filter_dep_specs(specs, package) if strict + locked_version = package.locked_version - sort_dep_specs(specs, package) + result = specs.sort do |a, b| + unless package.prerelease_specified? || pre? + a_pre = a.prerelease? + b_pre = b.prerelease? + + next 1 if a_pre && !b_pre + next -1 if b_pre && !a_pre + end + + if major? || locked_version.nil? + b <=> a + elsif either_version_older_than_locked?(a, b, locked_version) + b <=> a + elsif segments_do_not_match?(a, b, :major) + a <=> b + elsif !minor? && segments_do_not_match?(a, b, :minor) + a <=> b + else + b <=> a + end + end + post_sort(result, package.unlock?, locked_version) end # @return [bool] Convenience method for testing value of level variable. @@ -73,9 +93,18 @@ module Bundler pre == true end - private + # Given a Resolver::Package and an Array of Specifications of available + # versions for a gem, this method will truncate the Array if strict + # is true. That means filtering out downgrades from the version currently + # locked, and filtering out upgrades that go past the selected level (major, + # minor, or patch). + # @param package [Resolver::Package] The package being resolved. + # @param specs [Specification] An array of Specifications for the package. + # @return [Specification] A new instance of the Specification Array + # truncated. + def filter_versions(package, specs) + return specs unless strict - def filter_dep_specs(specs, package) locked_version = package.locked_version return specs if locked_version.nil? || major? @@ -89,32 +118,7 @@ module Bundler end end - def sort_dep_specs(specs, package) - locked_version = package.locked_version - - result = specs.sort do |a, b| - unless package.prerelease_specified? || pre? - a_pre = a.prerelease? - b_pre = b.prerelease? - - next -1 if a_pre && !b_pre - next 1 if b_pre && !a_pre - end - - if major? || locked_version.nil? - a <=> b - elsif either_version_older_than_locked?(a, b, locked_version) - a <=> b - elsif segments_do_not_match?(a, b, :major) - b <=> a - elsif !minor? && segments_do_not_match?(a, b, :minor) - b <=> a - else - a <=> b - end - end - post_sort(result, package.unlock?, locked_version) - end + private def either_version_older_than_locked?(a, b, locked_version) a.version < locked_version || b.version < locked_version @@ -133,13 +137,13 @@ module Bundler if unlock || locked_version.nil? result else - move_version_to_end(result, locked_version) + move_version_to_beginning(result, locked_version) end end - def move_version_to_end(result, version) + def move_version_to_beginning(result, version) move, keep = result.partition {|s| s.version.to_s == version.to_s } - keep.concat(move) + move.concat(keep) end end end diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb index 2cf7754ecb..cf561c2ee4 100644 --- a/lib/bundler/injector.rb +++ b/lib/bundler/injector.rb @@ -50,7 +50,7 @@ module Bundler append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any? # since we resolved successfully, write out the lockfile - @definition.lock(Bundler.default_lockfile) + @definition.lock # invalidate the cached Bundler.definition Bundler.reset_paths! diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index e837f732cf..018324f840 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -260,8 +260,8 @@ module Bundler true end - def lock(opts = {}) - @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections]) + def lock + @definition.lock end end end diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index 210911dcf4..a6cbc88f34 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-ADD" "1" "December 2023" "" +.TH "BUNDLE\-ADD" "1" "March 2024" "" .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index b71347d6e1..2b35bc956a 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-BINSTUBS" "1" "December 2023" "" +.TH "BUNDLE\-BINSTUBS" "1" "March 2024" "" .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index 5f03c38abe..3b86b995a6 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CACHE" "1" "December 2023" "" +.TH "BUNDLE\-CACHE" "1" "March 2024" "" .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index bc24dfe2b2..7f18e26537 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CHECK" "1" "December 2023" "" +.TH "BUNDLE\-CHECK" "1" "March 2024" "" .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index 00787da5f1..0180eb38a2 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CLEAN" "1" "December 2023" "" +.TH "BUNDLE\-CLEAN" "1" "March 2024" "" .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index c5a976da46..b768f1e3d2 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CONFIG" "1" "December 2023" "" +.TH "BUNDLE\-CONFIG" "1" "March 2024" "" .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1 index 14e5f55647..1368a50eb1 100644 --- a/lib/bundler/man/bundle-console.1 +++ b/lib/bundler/man/bundle-console.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CONSOLE" "1" "December 2023" "" +.TH "BUNDLE\-CONSOLE" "1" "March 2024" "" .SH "NAME" \fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index aea8bacdad..80eaf2a888 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-DOCTOR" "1" "December 2023" "" +.TH "BUNDLE\-DOCTOR" "1" "March 2024" "" .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index af622f4423..191863c045 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-EXEC" "1" "December 2023" "" +.TH "BUNDLE\-EXEC" "1" "March 2024" "" .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index bc62a883ea..464d8d1126 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-GEM" "1" "December 2023" "" +.TH "BUNDLE\-GEM" "1" "March 2024" "" .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1 index 3e6d7a851e..3604ad6127 100644 --- a/lib/bundler/man/bundle-help.1 +++ b/lib/bundler/man/bundle-help.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-HELP" "1" "December 2023" "" +.TH "BUNDLE\-HELP" "1" "March 2024" "" .SH "NAME" \fBbundle\-help\fR \- Displays detailed help for each subcommand .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index 43cc7d23b6..647f5987be 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INFO" "1" "December 2023" "" +.TH "BUNDLE\-INFO" "1" "March 2024" "" .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index 9c6f89a6b2..2c41a3c7de 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INIT" "1" "December 2023" "" +.TH "BUNDLE\-INIT" "1" "March 2024" "" .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index f8c4d4342e..c7269db34d 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INJECT" "1" "December 2023" "" +.TH "BUNDLE\-INJECT" "1" "March 2024" "" .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index a23763889b..3fa1a467e2 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INSTALL" "1" "December 2023" "" +.TH "BUNDLE\-INSTALL" "1" "March 2024" "" .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile .SH "SYNOPSIS" @@ -208,8 +208,8 @@ To explicitly update \fBactionpack\fR, including its dependencies which other ge \fBSummary\fR: In general, after making a change to the Gemfile(5) , you should first try to run \fBbundle install\fR, which will guarantee that no other gem in the Gemfile(5) is impacted by the change\. If that does not work, run bundle update(1) \fIbundle\-update\.1\.html\fR\. .SH "SEE ALSO" .IP "\(bu" 4 -Gem install docs \fIhttp://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR +Gem install docs \fIhttps://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR .IP "\(bu" 4 -Rubygems signing docs \fIhttp://guides\.rubygems\.org/security/\fR +Rubygems signing docs \fIhttps://guides\.rubygems\.org/security/\fR .IP "" 0 diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn index ac0014e24e..ed8169de05 100644 --- a/lib/bundler/man/bundle-install.1.ronn +++ b/lib/bundler/man/bundle-install.1.ronn @@ -379,5 +379,5 @@ does not work, run [bundle update(1)](bundle-update.1.html). ## SEE ALSO -* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems) -* [Rubygems signing docs](http://guides.rubygems.org/security/) +* [Gem install docs](https://guides.rubygems.org/rubygems-basics/#installing-gems) +* [Rubygems signing docs](https://guides.rubygems.org/security/) diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 943f17ab83..f91fd95739 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-LIST" "1" "December 2023" "" +.TH "BUNDLE\-LIST" "1" "March 2024" "" .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index 041c2d739e..f992f5ee5f 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-LOCK" "1" "December 2023" "" +.TH "BUNDLE\-LOCK" "1" "March 2024" "" .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index a349288987..53d3541555 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-OPEN" "1" "December 2023" "" +.TH "BUNDLE\-OPEN" "1" "March 2024" "" .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index a501fec83e..f79eff5ae9 100644 --- a/lib/bundler/man/bundle-outdated.1 +++ b/lib/bundler/man/bundle-outdated.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-OUTDATED" "1" "December 2023" "" +.TH "BUNDLE\-OUTDATED" "1" "March 2024" "" .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1 index 2ff1938585..d2133ec4d3 100644 --- a/lib/bundler/man/bundle-platform.1 +++ b/lib/bundler/man/bundle-platform.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PLATFORM" "1" "December 2023" "" +.TH "BUNDLE\-PLATFORM" "1" "March 2024" "" .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index 09e0d816ac..cbdfac11b6 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -1,10 +1,10 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PLUGIN" "1" "December 2023" "" +.TH "BUNDLE\-PLUGIN" "1" "March 2024" "" .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins .SH "SYNOPSIS" -\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git|\-\-local_git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] +\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR] .br \fBbundle plugin\fR uninstall PLUGINS .br @@ -27,7 +27,7 @@ Install bundler\-graph gem from example\.com\. The global source, specified in s You can specify the version of the gem via \fB\-\-version\fR\. .TP \fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR -Install bundler\-graph gem from Git repository\. \fB\-\-git\fR can be replaced with \fB\-\-local\-git\fR\. You cannot use both \fB\-\-git\fR and \fB\-\-local\-git\fR\. You can use standard Git URLs like: +Install bundler\-graph gem from Git repository\. You can use standard Git URLs like: .IP \fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR .br @@ -37,7 +37,10 @@ Install bundler\-graph gem from Git repository\. \fB\-\-git\fR can be replaced w .br \fBfile:///path/to/repo\fR .IP -When you specify \fB\-\-git\fR/\fB\-\-local\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. When you specify both, only the latter is used\. +When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. +.TP +\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR +Install bundler\-graph gem from a local path\. .SS "uninstall" Uninstall the plugin(s) specified in PLUGINS\. .SS "list" diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn index a11df4c162..b0a34660ea 100644 --- a/lib/bundler/man/bundle-plugin.1.ronn +++ b/lib/bundler/man/bundle-plugin.1.ronn @@ -4,7 +4,8 @@ bundle-plugin(1) -- Manage Bundler plugins ## SYNOPSIS `bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>] - [--git|--local_git=<git-url>] [--branch=<branch>|--ref=<rev>]<br> + [--git=<git-url>] [--branch=<branch>|--ref=<rev>] + [--path=<path>]<br> `bundle plugin` uninstall PLUGINS<br> `bundle plugin` list<br> `bundle plugin` help [COMMAND] @@ -29,14 +30,17 @@ Install the given plugin(s). You can specify the version of the gem via `--version`. * `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`: - Install bundler-graph gem from Git repository. `--git` can be replaced with `--local-git`. You cannot use both `--git` and `--local-git`. You can use standard Git URLs like: + Install bundler-graph gem from Git repository. You can use standard Git URLs like: `ssh://[user@]host.xz[:port]/path/to/repo.git`<br> `http[s]://host.xz[:port]/path/to/repo.git`<br> `/path/to/repo`<br> `file:///path/to/repo` - When you specify `--git`/`--local-git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. When you specify both, only the latter is used. + When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. + +* `bundle plugin install bundler-graph --path ../bundler-graph`: + Install bundler-graph gem from a local path. ### uninstall diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1 index 60609f4ee8..faa04d7676 100644 --- a/lib/bundler/man/bundle-pristine.1 +++ b/lib/bundler/man/bundle-pristine.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PRISTINE" "1" "December 2023" "" +.TH "BUNDLE\-PRISTINE" "1" "March 2024" "" .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1 index 31eae269c8..3f8cbbd9b6 100644 --- a/lib/bundler/man/bundle-remove.1 +++ b/lib/bundler/man/bundle-remove.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-REMOVE" "1" "December 2023" "" +.TH "BUNDLE\-REMOVE" "1" "March 2024" "" .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1 index 761629c625..bc72c6e3b6 100644 --- a/lib/bundler/man/bundle-show.1 +++ b/lib/bundler/man/bundle-show.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-SHOW" "1" "December 2023" "" +.TH "BUNDLE\-SHOW" "1" "March 2024" "" .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1 index 838261df0d..d1284c2e72 100644 --- a/lib/bundler/man/bundle-update.1 +++ b/lib/bundler/man/bundle-update.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-UPDATE" "1" "December 2023" "" +.TH "BUNDLE\-UPDATE" "1" "March 2024" "" .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1 index d9b0e7c3b1..05905e1347 100644 --- a/lib/bundler/man/bundle-version.1 +++ b/lib/bundler/man/bundle-version.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-VERSION" "1" "December 2023" "" +.TH "BUNDLE\-VERSION" "1" "March 2024" "" .SH "NAME" \fBbundle\-version\fR \- Prints Bundler version information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1 index 0e7981ac9a..681563cd4c 100644 --- a/lib/bundler/man/bundle-viz.1 +++ b/lib/bundler/man/bundle-viz.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-VIZ" "1" "December 2023" "" +.TH "BUNDLE\-VIZ" "1" "March 2024" "" .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1 index 2417348be4..1d2c780060 100644 --- a/lib/bundler/man/bundle.1 +++ b/lib/bundler/man/bundle.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE" "1" "December 2023" "" +.TH "BUNDLE" "1" "March 2024" "" .SH "NAME" \fBbundle\fR \- Ruby Dependency Management .SH "SYNOPSIS" diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index 9f73687c8c..39503f22a6 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "GEMFILE" "5" "December 2023" "" +.TH "GEMFILE" "5" "March 2024" "" .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs .SH "SYNOPSIS" @@ -72,7 +72,7 @@ A Ruby engine is an implementation of the Ruby language\. .IP "\(bu" 4 For background: the reference or original implementation of the Ruby programming language is called Matz's Ruby Interpreter \fIhttps://en\.wikipedia\.org/wiki/Ruby_MRI\fR, or MRI for short\. This is named after Ruby creator Yukihiro Matsumoto, also known as Matz\. MRI is also known as CRuby, because it is written in C\. MRI is the most widely used Ruby engine\. .IP "\(bu" 4 -Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include JRuby \fIhttp://jruby\.org/\fR and TruffleRuby \fIhttps://www\.graalvm\.org/ruby/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM\. +Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include JRuby \fIhttps://www\.jruby\.org/\fR and TruffleRuby \fIhttps://www\.graalvm\.org/ruby/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM\. .IP "" 0 .SS "ENGINE VERSION" Each application \fImay\fR specify a Ruby engine version\. If an engine version is specified, an engine \fImust\fR also be specified\. If the engine is "ruby" the engine version specified \fImust\fR match the Ruby version\. @@ -449,7 +449,7 @@ end .fi .IP "" 0 .SH "GEMSPEC" -The \fB\.gemspec\fR \fIhttp://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\. +The \fB\.gemspec\fR \fIhttps://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\. .P If you wish to use Bundler to help install dependencies for a gem while it is being developed, use the \fBgemspec\fR method to pull in the dependencies listed in the \fB\.gemspec\fR file\. .P diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn index e8a1f8b79e..7c1e00d13a 100644 --- a/lib/bundler/man/gemfile.5.ronn +++ b/lib/bundler/man/gemfile.5.ronn @@ -96,7 +96,7 @@ What exactly is an Engine? - [Other implementations](https://www.ruby-lang.org/en/about/) of Ruby exist. Some of the more well-known implementations include - [JRuby](http://jruby.org/) and [TruffleRuby](https://www.graalvm.org/ruby/). + [JRuby](https://www.jruby.org/) and [TruffleRuby](https://www.graalvm.org/ruby/). Rubinius is an alternative implementation of Ruby written in Ruby. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM. @@ -509,7 +509,7 @@ software is installed or some other conditions are met. ## GEMSPEC -The [`.gemspec`](http://guides.rubygems.org/specification-reference/) file is where +The [`.gemspec`](https://guides.rubygems.org/specification-reference/) file is where you provide metadata about your gem to Rubygems. Some required Gemspec attributes include the name, description, and homepage of your gem. This is also where you specify the dependencies your gem needs to run. diff --git a/lib/bundler/mirror.rb b/lib/bundler/mirror.rb index 9d437a0951..494a6d6aef 100644 --- a/lib/bundler/mirror.rb +++ b/lib/bundler/mirror.rb @@ -47,7 +47,7 @@ module Bundler def fetch_valid_mirror_for(uri) downcased = uri.to_s.downcase - mirror = @mirrors[downcased] || @mirrors[Bundler::URI(downcased).host] || Mirror.new(uri) + mirror = @mirrors[downcased] || @mirrors[Gem::URI(downcased).host] || Mirror.new(uri) mirror.validate!(@prober) mirror = Mirror.new(uri) unless mirror.valid? mirror @@ -74,7 +74,7 @@ module Bundler @uri = if uri.nil? nil else - Bundler::URI(uri.to_s) + Gem::URI(uri.to_s) end @valid = nil end @@ -126,7 +126,7 @@ module Bundler if uri == "all" @all = true else - @uri = Bundler::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri + @uri = Gem::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri end @value = value end diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb index f051f938c2..8563ee358a 100644 --- a/lib/bundler/plugin/api/source.rb +++ b/lib/bundler/plugin/api/source.rb @@ -107,7 +107,7 @@ module Bundler def install_path @install_path ||= begin - base_name = File.basename(Bundler::URI.parse(uri).normalize.path) + base_name = File.basename(Gem::URI.parse(uri).normalize.path) gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}") end @@ -176,7 +176,7 @@ module Bundler # # This is used by `app_cache_path` def app_cache_dirname - base_name = File.basename(Bundler::URI.parse(uri).normalize.path) + base_name = File.basename(Gem::URI.parse(uri).normalize.path) "#{base_name}-#{uri_hash}" end diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb index 256dcf526c..4f60862bb4 100644 --- a/lib/bundler/plugin/installer.rb +++ b/lib/bundler/plugin/installer.rb @@ -10,6 +10,7 @@ module Bundler class Installer autoload :Rubygems, File.expand_path("installer/rubygems", __dir__) autoload :Git, File.expand_path("installer/git", __dir__) + autoload :Path, File.expand_path("installer/path", __dir__) def install(names, options) check_sources_consistency!(options) @@ -18,8 +19,8 @@ module Bundler if options[:git] install_git(names, version, options) - elsif options[:local_git] - install_local_git(names, version, options) + elsif options[:path] + install_path(names, version, options[:path]) else sources = options[:source] || Gem.sources install_rubygems(names, version, sources) @@ -45,20 +46,40 @@ module Bundler if options.key?(:git) && options.key?(:local_git) raise InvalidOption, "Remote and local plugin git sources can't be both specified" end + + # back-compat; local_git is an alias for git + if options.key?(:local_git) + Bundler::SharedHelpers.major_deprecation(2, "--local_git is deprecated, use --git") + options[:git] = options.delete(:local_git) + end + + if (options.keys & [:source, :git, :path]).length > 1 + raise InvalidOption, "Only one of --source, --git, or --path may be specified" + end + + if (options.key?(:branch) || options.key?(:ref)) && !options.key?(:git) + raise InvalidOption, "--#{options.key?(:branch) ? "branch" : "ref"} can only be used with git sources" + end + + if options.key?(:branch) && options.key?(:ref) + raise InvalidOption, "--branch and --ref can't be both specified" + end end def install_git(names, version, options) - uri = options.delete(:git) - options["uri"] = uri + source_list = SourceList.new + source = source_list.add_git_source({ "uri" => options[:git], + "branch" => options[:branch], + "ref" => options[:ref] }) - install_all_sources(names, version, options, options[:source]) + install_all_sources(names, version, source_list, source) end - def install_local_git(names, version, options) - uri = options.delete(:local_git) - options["uri"] = uri + def install_path(names, version, path) + source_list = SourceList.new + source = source_list.add_path_source({ "path" => path, "root_path" => SharedHelpers.pwd }) - install_all_sources(names, version, options, options[:source]) + install_all_sources(names, version, source_list, source) end # Installs the plugin from rubygems source and returns the path where the @@ -70,16 +91,15 @@ module Bundler # # @return [Hash] map of names to the specs of plugins installed def install_rubygems(names, version, sources) - install_all_sources(names, version, nil, sources) - end - - def install_all_sources(names, version, git_source_options, rubygems_source) source_list = SourceList.new - source_list.add_git_source(git_source_options) if git_source_options - Array(rubygems_source).each {|remote| source_list.add_global_rubygems_remote(remote) } if rubygems_source + Array(sources).each {|remote| source_list.add_global_rubygems_remote(remote) } + + install_all_sources(names, version, source_list) + end - deps = names.map {|name| Dependency.new name, version } + def install_all_sources(names, version, source_list, source = nil) + deps = names.map {|name| Dependency.new(name, version, { "source" => source }) } Bundler.configure_gem_home_and_path(Plugin.root) diff --git a/lib/bundler/plugin/installer/path.rb b/lib/bundler/plugin/installer/path.rb new file mode 100644 index 0000000000..58a8fa7426 --- /dev/null +++ b/lib/bundler/plugin/installer/path.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Bundler + module Plugin + class Installer + class Path < Bundler::Source::Path + def root + SharedHelpers.in_bundle? ? Bundler.root : Plugin.root + end + + def generate_bin(spec, disable_extensions = false) + # Need to find a way without code duplication + # For now, we can ignore this + end + end + end + end +end diff --git a/lib/bundler/plugin/source_list.rb b/lib/bundler/plugin/source_list.rb index 547661cf2f..746996de55 100644 --- a/lib/bundler/plugin/source_list.rb +++ b/lib/bundler/plugin/source_list.rb @@ -9,6 +9,10 @@ module Bundler add_source_to_list Plugin::Installer::Git.new(options), git_sources end + def add_path_source(options = {}) + add_source_to_list Plugin::Installer::Path.new(options), path_sources + end + def add_rubygems_source(options = {}) add_source_to_list Plugin::Installer::Rubygems.new(options), @rubygems_sources end @@ -17,10 +21,6 @@ module Bundler path_sources + git_sources + rubygems_sources + [metadata_source] end - def default_source - git_sources.first || global_rubygems_source - end - private def rubygems_aggregate_class diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index f60069f421..1a6711ea6f 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -50,26 +50,26 @@ module Bundler specs[name] = matches.sort_by {|s| [s.version, s.platform.to_s] } end + @all_versions = Hash.new do |candidates, package| + candidates[package] = all_versions_for(package) + end + @sorted_versions = Hash.new do |candidates, package| - candidates[package] = if package.root? - [root_version] - else - all_versions_for(package).sort - end + candidates[package] = filtered_versions_for(package).sort end + @sorted_versions[root] = [root_version] + root_dependencies = prepare_dependencies(@requirements, @packages) @cached_dependencies = Hash.new do |dependencies, package| - dependencies[package] = if package.root? - { root_version => root_dependencies } - else - Hash.new do |versions, version| - versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages) - end + dependencies[package] = Hash.new do |versions, version| + versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages) end end + @cached_dependencies[root] = { root_version => root_dependencies } + logger = Bundler::UI::Shell.new logger.level = debug? ? "debug" : "warn" @@ -156,9 +156,15 @@ module Bundler end def versions_for(package, range=VersionRange.any) - versions = range.select_versions(@sorted_versions[package]) + versions = select_sorted_versions(package, range) - sort_versions(package, versions) + # Conditional avoids (among other things) calling + # sort_versions_by_preferred with the root package + if versions.size > 1 + sort_versions_by_preferred(package, versions) + else + versions + end end def no_versions_incompatibility_for(package, unsatisfied_term) @@ -247,7 +253,7 @@ module Bundler locked_requirement = base_requirements[name] results = filter_matching_specs(results, locked_requirement) if locked_requirement - versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)| + results.group_by(&:version).reduce([]) do |groups, (version, specs)| platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) } # If package is a top-level dependency, @@ -274,8 +280,6 @@ module Bundler groups end - - sort_versions(package, versions) end def source_for(name) @@ -334,6 +338,21 @@ module Bundler private + def filtered_versions_for(package) + @gem_version_promoter.filter_versions(package, @all_versions[package]) + end + + def raise_all_versions_filtered_out!(package) + level = @gem_version_promoter.level + name = package.name + locked_version = package.locked_version + requirement = package.dependency + + raise GemNotFound, + "#{name} is locked to #{locked_version}, while Gemfile is requesting #{requirement}. " \ + "--strict --#{level} was specified, but there are no #{level} level upgrades from #{locked_version} satisfying #{requirement}, so version solving has failed" + end + def filter_matching_specs(specs, requirements) Array(requirements).flat_map do |requirement| specs.select {| spec| requirement_satisfied_by?(requirement, spec) } @@ -357,12 +376,8 @@ module Bundler requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec) end - def sort_versions(package, versions) - if versions.size > 1 - @gem_version_promoter.sort_versions(package, versions).reverse - else - versions - end + def sort_versions_by_preferred(package, versions) + @gem_version_promoter.sort_versions(package, versions) end def repository_for(package) @@ -379,12 +394,19 @@ module Bundler next [dep_package, dep_constraint] if name == "bundler" - versions = versions_for(dep_package, dep_constraint.range) + dep_range = dep_constraint.range + versions = select_sorted_versions(dep_package, dep_range) if versions.empty? && dep_package.ignores_prereleases? + @all_versions.delete(dep_package) @sorted_versions.delete(dep_package) dep_package.consider_prereleases! - versions = versions_for(dep_package, dep_constraint.range) + versions = select_sorted_versions(dep_package, dep_range) end + + if versions.empty? && select_all_versions(dep_package, dep_range).any? + raise_all_versions_filtered_out!(dep_package) + end + next [dep_package, dep_constraint] unless versions.empty? next unless dep_package.current_platform? @@ -393,6 +415,14 @@ module Bundler end.compact.to_h end + def select_sorted_versions(package, range) + range.select_versions(@sorted_versions[package]) + end + + def select_all_versions(package, range) + range.select_versions(@all_versions[package]) + end + def other_specs_matching_message(specs, requirement) message = String.new("The source contains the following gems matching '#{requirement}':\n") message << specs.map {|s| " * #{s.full_name}" }.join("\n") diff --git a/lib/bundler/resolver/candidate.rb b/lib/bundler/resolver/candidate.rb index e695ef08ee..9e8b913335 100644 --- a/lib/bundler/resolver/candidate.rb +++ b/lib/bundler/resolver/candidate.rb @@ -15,7 +15,7 @@ module Bundler # considered separately. # # Some candidates may also keep some information explicitly about the - # package the refer to. These candidates are referred to as "canonical" and + # package they refer to. These candidates are referred to as "canonical" and # are used when materializing resolution results back into RubyGems # specifications that can be installed, written to lock files, and so on. # diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb index 993f1082c3..ec772cfe7b 100644 --- a/lib/bundler/runtime.rb +++ b/lib/bundler/runtime.rb @@ -95,7 +95,7 @@ module Bundler def lock(opts = {}) return if @definition.no_resolve_needed? - @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections]) + @definition.lock(opts[:preserve_unknown_sections]) end alias_method :gems, :specs diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb index 5accda4bcb..bfd000b1a0 100644 --- a/lib/bundler/self_manager.rb +++ b/lib/bundler/self_manager.rb @@ -113,7 +113,7 @@ module Bundler end def local_specs - @local_specs ||= Bundler::Source::Rubygems.new("allow_local" => true).specs.select {|spec| spec.name == "bundler" } + @local_specs ||= Bundler::Source::Rubygems.new("allow_local" => true, "allow_cached" => true).specs.select {|spec| spec.name == "bundler" } end def remote_specs diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index 8f941c448d..379abfb24a 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -189,7 +189,7 @@ module Bundler def mirror_for(uri) if uri.is_a?(String) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) end gem_mirrors.for(uri.to_s).uri @@ -492,16 +492,19 @@ module Bundler valid_file = file.exist? && !file.size.zero? return {} unless valid_file serializer_class.load(file.read).inject({}) do |config, (k, v)| - if k.include?("-") - Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \ - "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ - "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)." + unless k.start_with?("#") + if k.include?("-") + Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \ + "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ + "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)." - # string hash keys are frozen - k = k.gsub("-", "___") + # string hash keys are frozen + k = k.gsub("-", "___") + end + + config[k] = v end - config[k] = v config end end @@ -549,7 +552,7 @@ module Bundler end uri = URINormalizer.normalize_suffix(uri) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) unless uri.absolute? raise ArgumentError, format("Gem sources must be absolute. You provided '%s'.", uri) end @@ -564,7 +567,7 @@ module Bundler key when Symbol key.name - when Bundler::URI::HTTP + when Gem::URI::HTTP key.to_s else raise ArgumentError, "Invalid key: #{key.inspect}" @@ -577,7 +580,7 @@ module Bundler key when Symbol key.to_s - when Bundler::URI::HTTP + when Gem::URI::HTTP key.to_s else raise ArgumentError, "Invalid key: #{key.inspect}" diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb index 831a13cba3..198e335bb6 100644 --- a/lib/bundler/source/git.rb +++ b/lib/bundler/source/git.rb @@ -326,7 +326,7 @@ module Bundler if %r{^\w+://(\w+@)?}.match?(uri) # Downcase the domain component of the URI # and strip off a trailing slash, if one is present - input = Bundler::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") + input = Gem::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") else # If there is no URI scheme, assume it is an ssh/git URI input = uri diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb index 8b6d420884..645851286c 100644 --- a/lib/bundler/source/git/git_proxy.rb +++ b/lib/bundler/source/git/git_proxy.rb @@ -320,7 +320,7 @@ module Bundler # Adds credentials to the URI def configured_uri if /https?:/.match?(uri) - remote = Bundler::URI(uri) + remote = Gem::URI(uri) config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host] remote.userinfo ||= config_auth remote.to_s diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb index dfcedb5b16..04cfc0a850 100644 --- a/lib/bundler/source/rubygems.rb +++ b/lib/bundler/source/rubygems.rb @@ -17,7 +17,7 @@ module Bundler @remotes = [] @dependency_names = [] @allow_remote = false - @allow_cached = false + @allow_cached = options["allow_cached"] || false @allow_local = options["allow_local"] || false @checksum_store = Checksum::Store.new @@ -133,7 +133,7 @@ module Bundler # sources, and large_idx.merge! small_idx is way faster than # small_idx.merge! large_idx. index = @allow_remote ? remote_specs.dup : Index.new - index.merge!(cached_specs) if @allow_cached || @allow_remote + index.merge!(cached_specs) if @allow_cached index.merge!(installed_specs) if @allow_local index end @@ -349,9 +349,9 @@ module Bundler def normalize_uri(uri) uri = URINormalizer.normalize_suffix(uri.to_s) require_relative "../vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) raise ArgumentError, "The source must be an absolute URI. For example:\n" \ - "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Bundler::URI::HTTP) && uri.host.nil?) + "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Gem::URI::HTTP) && uri.host.nil?) uri end diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb index 82c850ffbb..9c5c06de24 100644 --- a/lib/bundler/source/rubygems/remote.rb +++ b/lib/bundler/source/rubygems/remote.rb @@ -48,7 +48,7 @@ module Bundler end uri - rescue Bundler::URI::InvalidComponentError + rescue Gem::URI::InvalidComponentError error_message = "Please CGI escape your usernames and passwords before " \ "setting them for authentication." raise HTTPError.new(error_message) diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index 4419695b7f..d85e1c1c01 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -9,7 +9,7 @@ module Bundler :metadata_source def global_rubygems_source - @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true) + @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true, "allow_cached" => true) end def initialize @@ -174,7 +174,7 @@ module Bundler replacement_source = replacement_sources.find {|s| s == global_rubygems_source } return global_rubygems_source unless replacement_source - replacement_source.local! + replacement_source.cached! replacement_source end diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index cc649abaf8..96e1403bf7 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -65,7 +65,7 @@ module Bundler platforms.concat(new_platforms) - less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform } + less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform } platforms.delete(Bundler.local_platform) if less_specific_platform platforms diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt index 51f19a5be9..6e88f4dab1 100644 --- a/lib/bundler/templates/newgem/newgem.gemspec.tt +++ b/lib/bundler/templates/newgem/newgem.gemspec.tt @@ -27,9 +27,10 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(__dir__) do - `git ls-files -z`.split("\x0").reject do |f| - (File.expand_path(f) == __FILE__) || + gemspec = File.basename(__FILE__) + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| + ls.readlines("\x0", chomp: true).reject do |f| + (f == gemspec) || f.start_with?(*%w[bin/ test/ spec/ features/ .git <%= config[:ci_config_path] %>appveyor Gemfile]) end end diff --git a/lib/bundler/templates/newgem/rubocop.yml.tt b/lib/bundler/templates/newgem/rubocop.yml.tt index 9ecec78807..3d1c4ee7b2 100644 --- a/lib/bundler/templates/newgem/rubocop.yml.tt +++ b/lib/bundler/templates/newgem/rubocop.yml.tt @@ -2,12 +2,7 @@ AllCops: TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %> Style/StringLiterals: - Enabled: true EnforcedStyle: double_quotes Style/StringLiteralsInInterpolation: - Enabled: true EnforcedStyle: double_quotes - -Layout/LineLength: - Max: 120 diff --git a/lib/bundler/uri_credentials_filter.rb b/lib/bundler/uri_credentials_filter.rb index ccfaf0bc5d..a83f5304e2 100644 --- a/lib/bundler/uri_credentials_filter.rb +++ b/lib/bundler/uri_credentials_filter.rb @@ -11,7 +11,7 @@ module Bundler return uri if File.exist?(uri) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) end if uri.userinfo @@ -25,7 +25,7 @@ module Bundler end return uri.to_s if uri_to_anonymize.is_a?(String) uri - rescue Bundler::URI::InvalidURIError # uri is not canonical uri scheme + rescue Gem::URI::InvalidURIError # uri is not canonical uri scheme uri end diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb index c702bebc39..c15b346330 100644 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb @@ -1,5 +1,5 @@ require_relative '../../../../../vendored_net_http' -require_relative '../../../../uri/lib/uri' +require_relative '../../../../../vendored_uri' require 'cgi' # for escaping require_relative '../../../../connection_pool/lib/connection_pool' @@ -22,7 +22,7 @@ autoload :OpenSSL, 'openssl' # # require 'bundler/vendor/net-http-persistent/lib/net/http/persistent' # -# uri = Bundler::URI 'http://example.com/awesome/web/service' +# uri = Gem::URI 'http://example.com/awesome/web/service' # # http = Gem::Net::HTTP::Persistent.new # @@ -39,17 +39,17 @@ autoload :OpenSSL, 'openssl' # post = Gem::Net::HTTP::Post.new post_uri.path # post.set_form_data 'some' => 'cool data' # -# # perform the POST, the Bundler::URI is always required +# # perform the POST, the Gem::URI is always required # response http.request post_uri, post # # Note that for GET, HEAD and other requests that do not have a body you want -# to use Bundler::URI#request_uri not Bundler::URI#path. The request_uri contains the query +# to use Gem::URI#request_uri not Gem::URI#path. The request_uri contains the query # params which are sent in the body for other requests. # # == TLS/SSL # # TLS connections are automatically created depending upon the scheme of the -# Bundler::URI. TLS connections are automatically verified against the default +# Gem::URI. TLS connections are automatically verified against the default # certificate store for your computer. You can override this by changing # verify_mode or by specifying an alternate cert_store. # @@ -72,7 +72,7 @@ autoload :OpenSSL, 'openssl' # == Proxies # # A proxy can be set through #proxy= or at initialization time by providing a -# second argument to ::new. The proxy may be the Bundler::URI of the proxy server or +# second argument to ::new. The proxy may be the Gem::URI of the proxy server or # <code>:ENV</code> which will consult environment variables. # # See #proxy= and #proxy_from_env for details. @@ -197,7 +197,7 @@ class Gem::Net::HTTP::Persistent # NOTE: This may not work on ruby > 1.9. def self.detect_idle_timeout uri, max = 10 - uri = Bundler::URI uri unless Bundler::URI::Generic === uri + uri = Gem::URI uri unless Gem::URI::Generic === uri uri += '/' req = Gem::Net::HTTP::Head.new uri.request_uri @@ -455,13 +455,13 @@ class Gem::Net::HTTP::Persistent # Set a +name+ for fun. Your library name should be good enough, but this # otherwise has no purpose. # - # +proxy+ may be set to a Bundler::URI::HTTP or :ENV to pick up proxy options from + # +proxy+ may be set to a Gem::URI::HTTP or :ENV to pick up proxy options from # the environment. See proxy_from_env for details. # - # In order to use a Bundler::URI for the proxy you may need to do some extra work - # beyond Bundler::URI parsing if the proxy requires a password: + # In order to use a Gem::URI for the proxy you may need to do some extra work + # beyond Gem::URI parsing if the proxy requires a password: # - # proxy = Bundler::URI 'http://proxy.example' + # proxy = Gem::URI 'http://proxy.example' # proxy.user = 'AzureDiamond' # proxy.password = 'hunter2' # @@ -510,7 +510,7 @@ class Gem::Net::HTTP::Persistent @verify_mode = nil @cert_store = nil - @generation = 0 # incremented when proxy Bundler::URI changes + @generation = 0 # incremented when proxy Gem::URI changes if HAVE_OPENSSL then @verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -720,12 +720,12 @@ class Gem::Net::HTTP::Persistent alias key= private_key= ## - # Sets the proxy server. The +proxy+ may be the Bundler::URI of the proxy server, + # Sets the proxy server. The +proxy+ may be the Gem::URI of the proxy server, # the symbol +:ENV+ which will read the proxy from the environment or nil to # disable use of a proxy. See #proxy_from_env for details on setting the # proxy from the environment. # - # If the proxy Bundler::URI is set after requests have been made, the next request + # If the proxy Gem::URI is set after requests have been made, the next request # will shut-down and re-open all connections. # # The +no_proxy+ query parameter can be used to specify hosts which shouldn't @@ -736,9 +736,9 @@ class Gem::Net::HTTP::Persistent def proxy= proxy @proxy_uri = case proxy when :ENV then proxy_from_env - when Bundler::URI::HTTP then proxy + when Gem::URI::HTTP then proxy when nil then # ignore - else raise ArgumentError, 'proxy must be :ENV or a Bundler::URI::HTTP' + else raise ArgumentError, 'proxy must be :ENV or a Gem::URI::HTTP' end @no_proxy.clear @@ -763,13 +763,13 @@ class Gem::Net::HTTP::Persistent end ## - # Creates a Bundler::URI for an HTTP proxy server from ENV variables. + # Creates a Gem::URI for an HTTP proxy server from ENV variables. # # If +HTTP_PROXY+ is set a proxy will be returned. # - # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Bundler::URI is given the + # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Gem::URI is given the # indicated user and password unless HTTP_PROXY contains either of these in - # the Bundler::URI. + # the Gem::URI. # # The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't # be reached via proxy; if set it should be a comma separated list of @@ -785,7 +785,7 @@ class Gem::Net::HTTP::Persistent return nil if env_proxy.nil? or env_proxy.empty? - uri = Bundler::URI normalize_uri env_proxy + uri = Gem::URI normalize_uri env_proxy env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] @@ -863,7 +863,7 @@ class Gem::Net::HTTP::Persistent # +req+ must be a Gem::Net::HTTPGenericRequest subclass (see Gem::Net::HTTP for a list). def request uri, req = nil, &block - uri = Bundler::URI uri + uri = Gem::URI uri req = request_setup req || uri response = nil @@ -896,7 +896,7 @@ class Gem::Net::HTTP::Persistent end ## - # Creates a GET request if +req_or_uri+ is a Bundler::URI and adds headers to the + # Creates a GET request if +req_or_uri+ is a Gem::URI and adds headers to the # request. # # Returns the request. diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb index 4bf61461b2..36ab06254d 100644 --- a/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb @@ -1,4 +1,5 @@ require_relative 'package' +require_relative 'rubygems' require_relative 'version_constraint' require_relative 'incompatibility' require_relative 'basic_package_source' diff --git a/lib/bundler/vendored_net_http.rb b/lib/bundler/vendored_net_http.rb index 908ec4bcaf..0dcabaa7d7 100644 --- a/lib/bundler/vendored_net_http.rb +++ b/lib/bundler/vendored_net_http.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true begin - require "rubygems/net/http" + require "rubygems/vendored_net_http" rescue LoadError - require "net/http" - Gem::Net = Net + begin + require "rubygems/net/http" + rescue LoadError + require "net/http" + Gem::Net = Net + end end diff --git a/lib/bundler/vendored_timeout.rb b/lib/bundler/vendored_timeout.rb index 34770f2116..9b2507c0cc 100644 --- a/lib/bundler/vendored_timeout.rb +++ b/lib/bundler/vendored_timeout.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true begin - require "rubygems/timeout" + require "rubygems/vendored_timeout" rescue LoadError - require "timeout" - Gem::Timeout = Timeout + begin + require "rubygems/timeout" + rescue LoadError + require "timeout" + Gem::Timeout = Timeout + end end diff --git a/lib/bundler/vendored_uri.rb b/lib/bundler/vendored_uri.rb index 905e8158e8..2efddc65f9 100644 --- a/lib/bundler/vendored_uri.rb +++ b/lib/bundler/vendored_uri.rb @@ -1,4 +1,21 @@ # frozen_string_literal: true module Bundler; end -require_relative "vendor/uri/lib/uri" + +# Use RubyGems vendored copy when available. Otherwise fallback to Bundler +# vendored copy. The vendored copy in Bundler can be removed once support for +# RubyGems 3.5 is dropped. + +begin + require "rubygems/vendor/uri/lib/uri" +rescue LoadError + require_relative "vendor/uri/lib/uri" + Gem::URI = Bundler::URI + + module Gem + def URI(uri) # rubocop:disable Naming/MethodName + Bundler::URI(uri) + end + module_function :URI + end +end diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index 05b6c66ce4..cc9550e988 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.5.5".freeze + VERSION = "2.5.9".freeze def self.bundler_major_version @bundler_major_version ||= VERSION.split(".").first.to_i diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb index 37ccc46c26..42e6aaf89d 100644 --- a/lib/bundler/yaml_serializer.rb +++ b/lib/bundler/yaml_serializer.rb @@ -58,6 +58,8 @@ module Bundler str.split(/\r?\n/) do |line| if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures + val = strip_comment(val) + convert_to_backward_compatible_key!(key) depth = indent.size / 2 if quote.empty? && val.empty? @@ -72,6 +74,8 @@ module Bundler end elsif match = ARRAY_REGEX.match(line) _, val = match.captures + val = strip_comment(val) + last_hash[last_empty_key] = [] unless last_hash[last_empty_key].is_a?(Array) last_hash[last_empty_key].push(val) @@ -80,6 +84,14 @@ module Bundler res end + def strip_comment(val) + if val.include?("#") && !val.start_with?("#") + val.split("#", 2).first.strip + else + val + end + end + # for settings' keys def convert_to_backward_compatible_key!(key) key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index d4138b2d8f..9e9eca0182 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -9,7 +9,7 @@ require "rbconfig" module Gem - VERSION = "3.5.5" + VERSION = "3.5.9" end # Must be first since it unloads the prelude from 1.9.2 @@ -1225,7 +1225,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] - return default_spec if default_spec && loaded_specs[default_spec.name] != default_spec + default_spec if default_spec && loaded_specs[default_spec.name] != default_spec end ## diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index 06ec2a5bdd..ec498a8b94 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require_relative "optparse" +require_relative "vendored_optparse" require_relative "requirement" require_relative "user_interaction" diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index ee28dce626..8e578dc196 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -60,6 +60,7 @@ class Gem::CommandManager :push, :query, :rdoc, + :rebuild, :search, :server, :signin, @@ -106,7 +107,7 @@ class Gem::CommandManager # Register all the subcommands supported by the gem command. def initialize - require_relative "timeout" + require_relative "vendored_timeout" @commands = {} BUILTIN_COMMANDS.each do |name| diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb index 0ebdec565b..2ec8324141 100644 --- a/lib/rubygems/commands/build_command.rb +++ b/lib/rubygems/commands/build_command.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true require_relative "../command" +require_relative "../gemspec_helpers" require_relative "../package" require_relative "../version_option" class Gem::Commands::BuildCommand < Gem::Command include Gem::VersionOption + include Gem::GemspecHelpers def initialize super "build", "Build a gem from a gemspec" @@ -75,17 +77,6 @@ Gems can be saved to a specified filename with the output option: private - def find_gemspec(glob = "*.gemspec") - gemspecs = Dir.glob(glob).sort - - if gemspecs.size > 1 - alert_error "Multiple gemspecs found: #{gemspecs}, please specify one" - terminate_interaction(1) - end - - gemspecs.first - end - def build_gem gemspec = resolve_gem_name diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb index 8994f1aa09..1619b152e7 100644 --- a/lib/rubygems/commands/help_command.rb +++ b/lib/rubygems/commands/help_command.rb @@ -59,7 +59,7 @@ multiple environments. The RubyGems implementation is designed to be compatible with Bundler's Gemfile format. You can see additional documentation on the format at: - http://bundler.io + https://bundler.io RubyGems automatically looks for these gem dependencies files: @@ -172,7 +172,7 @@ and #platforms methods: See the bundler Gemfile manual page for a list of platforms supported in a gem dependencies file.: - http://bundler.io/v1.6/man/gemfile.5.html + https://bundler.io/v2.5/man/gemfile.5.html Ruby Version and Engine Dependency ================================== diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb index 1321bc45f7..977c90b8c4 100644 --- a/lib/rubygems/commands/rdoc_command.rb +++ b/lib/rubygems/commands/rdoc_command.rb @@ -84,14 +84,7 @@ Use --overwrite to force rebuilding of documentation. FileUtils.rm_rf File.join(spec.doc_dir, "rdoc") end - begin - doc.generate - rescue Errno::ENOENT => e - match = / - /.match(e.message) - alert_error "Unable to document #{spec.full_name}, " \ - " #{match.post_match} is missing, skipping" - terminate_interaction 1 if specs.length == 1 - end + doc.generate end end end diff --git a/lib/rubygems/commands/rebuild_command.rb b/lib/rubygems/commands/rebuild_command.rb new file mode 100644 index 0000000000..97f05ef79c --- /dev/null +++ b/lib/rubygems/commands/rebuild_command.rb @@ -0,0 +1,264 @@ +# frozen_string_literal: true + +require "date" +require "digest" +require "fileutils" +require "tmpdir" +require_relative "../gemspec_helpers" +require_relative "../package" + +class Gem::Commands::RebuildCommand < Gem::Command + include Gem::GemspecHelpers + + DATE_FORMAT = "%Y-%m-%d %H:%M:%S.%N Z" + + def initialize + super "rebuild", "Attempt to reproduce a build of a gem." + + add_option "--diff", "If the files don't match, compare them using diffoscope." do |_value, options| + options[:diff] = true + end + + add_option "--force", "Skip validation of the spec." do |_value, options| + options[:force] = true + end + + add_option "--strict", "Consider warnings as errors when validating the spec." do |_value, options| + options[:strict] = true + end + + add_option "--source GEM_SOURCE", "Specify the source to download the gem from." do |value, options| + options[:source] = value + end + + add_option "--original GEM_FILE", "Specify a local file to compare against (instead of downloading it)." do |value, options| + options[:original_gem_file] = value + end + + add_option "--gemspec GEMSPEC_FILE", "Specify the name of the gemspec file." do |value, options| + options[:gemspec_file] = value + end + + add_option "-C PATH", "Run as if gem build was started in <PATH> instead of the current working directory." do |value, options| + options[:build_path] = value + end + end + + def arguments # :nodoc: + "GEM_NAME gem name on gem server\n" \ + "GEM_VERSION gem version you are attempting to rebuild" + end + + def description # :nodoc: + <<-EOF +The rebuild command allows you to (attempt to) reproduce a build of a gem +from a ruby gemspec. + +This command assumes the gemspec can be built with the `gem build` command. +If you use any of `gem build`, `rake build`, or`rake release` in the +build/release process for a gem, it is a potential candidate. + +You will need to match the RubyGems version used, since this is included in +the Gem metadata. + +If the gem includes lockfiles (e.g. Gemfile.lock) and similar, it will +require more effort to reproduce a build. For example, it might require +more precisely matched versions of Ruby and/or Bundler to be used. + EOF + end + + def usage # :nodoc: + "#{program_name} GEM_NAME GEM_VERSION" + end + + def execute + gem_name, gem_version = get_gem_name_and_version + + old_dir, new_dir = prep_dirs + + gem_filename = "#{gem_name}-#{gem_version}.gem" + old_file = File.join(old_dir, gem_filename) + new_file = File.join(new_dir, gem_filename) + + if options[:original_gem_file] + FileUtils.copy_file(options[:original_gem_file], old_file) + else + download_gem(gem_name, gem_version, old_file) + end + + rg_version = rubygems_version(old_file) + unless rg_version == Gem::VERSION + alert_error <<-EOF +You need to use the same RubyGems version #{gem_name} v#{gem_version} was built with. + +#{gem_name} v#{gem_version} was built using RubyGems v#{rg_version}. +Gem files include the version of RubyGems used to build them. +This means in order to reproduce #{gem_filename}, you must also use RubyGems v#{rg_version}. + +You're using RubyGems v#{Gem::VERSION}. + +Please install RubyGems v#{rg_version} and try again. + EOF + terminate_interaction 1 + end + + source_date_epoch = get_timestamp(old_file).to_s + + if build_path = options[:build_path] + Dir.chdir(build_path) { build_gem(gem_name, source_date_epoch, new_file) } + else + build_gem(gem_name, source_date_epoch, new_file) + end + + compare(source_date_epoch, old_file, new_file) + end + + private + + def sha256(file) + Digest::SHA256.hexdigest(Gem.read_binary(file)) + end + + def get_timestamp(file) + mtime = nil + File.open(file, Gem.binary_mode) do |f| + Gem::Package::TarReader.new(f) do |tar| + mtime = tar.seek("metadata.gz") {|tf| tf.header.mtime } + end + end + + mtime + end + + def compare(source_date_epoch, old_file, new_file) + date = Time.at(source_date_epoch.to_i).strftime("%F %T %Z") + + old_hash = sha256(old_file) + new_hash = sha256(new_file) + + say + say "Built at: #{date} (#{source_date_epoch})" + say "Original build saved to: #{old_file}" + say "Reproduced build saved to: #{new_file}" + say "Working directory: #{options[:build_path] || Dir.pwd}" + say + say "Hash comparison:" + say " #{old_hash}\t#{old_file}" + say " #{new_hash}\t#{new_file}" + say + + if old_hash == new_hash + say "SUCCESS - original and rebuild hashes matched" + else + say "FAILURE - original and rebuild hashes did not match" + say + + if options[:diff] + if system("diffoscope", old_file, new_file).nil? + alert_error "error: could not find `diffoscope` executable" + end + else + say "Pass --diff for more details (requires diffoscope to be installed)." + end + + terminate_interaction 1 + end + end + + def prep_dirs + rebuild_dir = Dir.mktmpdir("gem_rebuild") + old_dir = File.join(rebuild_dir, "old") + new_dir = File.join(rebuild_dir, "new") + + FileUtils.mkdir_p(old_dir) + FileUtils.mkdir_p(new_dir) + + [old_dir, new_dir] + end + + def get_gem_name_and_version + args = options[:args] || [] + if args.length == 2 + gem_name, gem_version = args + elsif args.length > 2 + raise Gem::CommandLineError, "Too many arguments" + else + raise Gem::CommandLineError, "Expected GEM_NAME and GEM_VERSION arguments (gem rebuild GEM_NAME GEM_VERSION)" + end + + [gem_name, gem_version] + end + + def build_gem(gem_name, source_date_epoch, output_file) + gemspec = options[:gemspec_file] || find_gemspec("#{gem_name}.gemspec") + + if gemspec + build_package(gemspec, source_date_epoch, output_file) + else + alert_error error_message(gem_name) + terminate_interaction(1) + end + end + + def build_package(gemspec, source_date_epoch, output_file) + with_source_date_epoch(source_date_epoch) do + spec = Gem::Specification.load(gemspec) + if spec + Gem::Package.build( + spec, + options[:force], + options[:strict], + output_file + ) + else + alert_error "Error loading gemspec. Aborting." + terminate_interaction 1 + end + end + end + + def with_source_date_epoch(source_date_epoch) + old_sde = ENV["SOURCE_DATE_EPOCH"] + ENV["SOURCE_DATE_EPOCH"] = source_date_epoch.to_s + + yield + ensure + ENV["SOURCE_DATE_EPOCH"] = old_sde + end + + def error_message(gem_name) + if gem_name + "Couldn't find a gemspec file matching '#{gem_name}' in #{Dir.pwd}" + else + "Couldn't find a gemspec file in #{Dir.pwd}" + end + end + + def download_gem(gem_name, gem_version, old_file) + # This code was based loosely off the `gem fetch` command. + version = "= #{gem_version}" + dep = Gem::Dependency.new gem_name, version + + specs_and_sources, errors = + Gem::SpecFetcher.fetcher.spec_for_dependency dep + + # There should never be more than one item in specs_and_sources, + # since we search for an exact version. + spec, source = specs_and_sources[0] + + if spec.nil? + show_lookup_failure gem_name, version, errors, options[:domain] + terminate_interaction 1 + end + + download_path = source.download spec + + FileUtils.move(download_path, old_file) + + say "Downloaded #{gem_name} version #{gem_version} as #{old_file}." + end + + def rubygems_version(gem_file) + Gem::Package.new(gem_file).spec.rubygems_version + end +end diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb index c9c6ee80ed..976f4a4ea2 100644 --- a/lib/rubygems/commands/sources_command.rb +++ b/lib/rubygems/commands/sources_command.rb @@ -59,7 +59,7 @@ class Gem::Commands::SourcesCommand < Gem::Command say "#{source_uri} added to sources" end - rescue URI::Error, ArgumentError + rescue Gem::URI::Error, ArgumentError say "#{source_uri} is not a URI" terminate_interaction 1 rescue Gem::RemoteFetcher::FetchError => e @@ -81,7 +81,7 @@ Do you want to add this source? end def check_rubygems_https(source_uri) # :nodoc: - uri = URI source_uri + uri = Gem::URI source_uri if uri.scheme && uri.scheme.casecmp("http").zero? && uri.host.casecmp("rubygems.org").zero? diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb index 1cad6af272..3200beb45f 100644 --- a/lib/rubygems/config_file.rb +++ b/lib/rubygems/config_file.rb @@ -202,21 +202,33 @@ class Gem::ConfigFile @hash = @hash.merge environment_config end + @hash.transform_keys! do |k| + # gemhome and gempath are not working with symbol keys + if %w[backtrace bulk_threshold verbose update_sources cert_expiration_length_days + install_extension_in_lib ipv4_fallback_enabled sources disable_default_gem_server + ssl_verify_mode ssl_ca_cert ssl_client_cert].include?(k) + k.to_sym + else + k + end + end + # HACK: these override command-line args, which is bad @backtrace = @hash[:backtrace] if @hash.key? :backtrace @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold - @home = @hash[:gemhome] if @hash.key? :gemhome - @path = @hash[:gempath] if @hash.key? :gempath - @update_sources = @hash[:update_sources] if @hash.key? :update_sources @verbose = @hash[:verbose] if @hash.key? :verbose - @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server - @sources = @hash[:sources] if @hash.key? :sources + @update_sources = @hash[:update_sources] if @hash.key? :update_sources + # TODO: We should handle concurrent_downloads same as other options @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled - @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode - @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert - @ssl_client_cert = @hash[:ssl_client_cert] if @hash.key? :ssl_client_cert + @home = @hash[:gemhome] if @hash.key? :gemhome + @path = @hash[:gempath] if @hash.key? :gempath + @sources = @hash[:sources] if @hash.key? :sources + @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server + @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode + @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert + @ssl_client_cert = @hash[:ssl_client_cert] if @hash.key? :ssl_client_cert @api_keys = nil @rubygems_api_key = nil diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb index 19cf306f88..ca161a4d95 100644 --- a/lib/rubygems/defaults.rb +++ b/lib/rubygems/defaults.rb @@ -112,7 +112,7 @@ module Gem # The path to standard location of the user's configuration directory. def self.config_home - @config_home ||= (ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config")) + @config_home ||= ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config") end ## @@ -145,21 +145,21 @@ module Gem # The path to standard location of the user's cache directory. def self.cache_home - @cache_home ||= (ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache")) + @cache_home ||= ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache") end ## # The path to standard location of the user's data directory. def self.data_home - @data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share")) + @data_home ||= ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share") end ## # The path to standard location of the user's state directory. def self.state_home - @state_home ||= (ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state")) + @state_home ||= ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state") end ## diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb index 00eff2dfe7..d1bf074441 100644 --- a/lib/rubygems/dependency.rb +++ b/lib/rubygems/dependency.rb @@ -328,9 +328,9 @@ class Gem::Dependency return active if active unless prerelease? - # Move prereleases to the end of the list for >= 0 requirements + # Consider prereleases only as a fallback pre, matches = matches.partition {|spec| spec.version.prerelease? } - matches += pre if requirement == Gem::Requirement.default + matches = pre if matches.empty? end matches.first diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb index 30098ff0b5..ad5e59e8c1 100644 --- a/lib/rubygems/dependency_list.rb +++ b/lib/rubygems/dependency_list.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require_relative "tsort" +require_relative "vendored_tsort" require_relative "deprecate" ## diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb index 5cf32e9af3..3eaf5f4ef8 100644 --- a/lib/rubygems/ext/cargo_builder.rb +++ b/lib/rubygems/ext/cargo_builder.rb @@ -293,7 +293,7 @@ EOF case var_name # On windows, it is assumed that mkmf has setup an exports file for the - # extension, so we have to to create one ourselves. + # extension, so we have to create one ourselves. when "DEFFILE" write_deffile(dest_dir, crate_name) else diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 7fcc0e037d..a8361b7ff1 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -10,7 +10,8 @@ require_relative "gemcutter_utilities/webauthn_poller" module Gem::GemcutterUtilities ERROR_CODE = 1 - API_SCOPES = [:index_rubygems, :push_rubygem, :yank_rubygem, :add_owner, :remove_owner, :access_webhooks, :show_dashboard].freeze + API_SCOPES = [:index_rubygems, :push_rubygem, :yank_rubygem, :add_owner, :remove_owner, :access_webhooks].freeze + EXCLUSIVELY_API_SCOPES = [:show_dashboard].freeze include Gem::Text @@ -84,7 +85,7 @@ module Gem::GemcutterUtilities # If +allowed_push_host+ metadata is present, then it will only allow that host. def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scope: nil, credentials: {}, &block) - require_relative "net/http" + require_relative "vendored_net_http" self.host = host if host unless self.host @@ -93,8 +94,8 @@ module Gem::GemcutterUtilities end if allowed_push_host - allowed_host_uri = URI.parse(allowed_push_host) - host_uri = URI.parse(self.host) + allowed_host_uri = Gem::URI.parse(allowed_push_host) + host_uri = Gem::URI.parse(self.host) unless (host_uri.scheme == allowed_host_uri.scheme) && (host_uri.host == allowed_host_uri.host) alert_error "#{self.host.inspect} is not allowed by the gemspec, which only allows #{allowed_push_host.inspect}" @@ -102,7 +103,7 @@ module Gem::GemcutterUtilities end end - uri = URI.parse "#{self.host}/#{path}" + uri = Gem::URI.parse "#{self.host}/#{path}" response = request_with_otp(method, uri, &block) if mfa_unauthorized?(response) @@ -129,14 +130,14 @@ module Gem::GemcutterUtilities say "The existing key doesn't have access of #{scope} on #{pretty_host}. Please sign in to update access." - email = ask " Email: " - password = ask_for_password "Password: " + identifier = ask "Username/email: " + password = ask_for_password " Password: " response = rubygems_api_request(:put, "api/v1/api_key", sign_in_host, scope: scope) do |request| - request.basic_auth email, password + request.basic_auth identifier, password request["OTP"] = otp if otp - request.body = URI.encode_www_form({ api_key: api_key }.merge(update_scope_params)) + request.body = Gem::URI.encode_www_form({ api_key: api_key }.merge(update_scope_params)) end with_response response do |_resp| @@ -158,25 +159,25 @@ module Gem::GemcutterUtilities say "Don't have an account yet? " \ "Create one at #{sign_in_host}/sign_up" - email = ask " Email: " - password = ask_for_password "Password: " + identifier = ask "Username/email: " + password = ask_for_password " Password: " say "\n" key_name = get_key_name(scope) scope_params = get_scope_params(scope) - profile = get_user_profile(email, password) + profile = get_user_profile(identifier, password) mfa_params = get_mfa_params(profile) all_params = scope_params.merge(mfa_params) warning = profile["warning"] - credentials = { email: email, password: password } + credentials = { identifier: identifier, password: password } say "#{warning}\n" if warning response = rubygems_api_request(:post, "api/v1/api_key", sign_in_host, credentials: credentials, scope: scope) do |request| - request.basic_auth email, password + request.basic_auth identifier, password request["OTP"] = otp if otp - request.body = URI.encode_www_form({ name: key_name }.merge(all_params)) + request.body = Gem::URI.encode_www_form({ name: key_name }.merge(all_params)) end with_response response do |resp| @@ -294,7 +295,7 @@ module Gem::GemcutterUtilities if credentials.empty? request.add_field "Authorization", api_key else - request.basic_auth credentials[:email], credentials[:password] + request.basic_auth credentials[:identifier], credentials[:password] end end response.is_a?(Gem::Net::HTTPSuccess) ? response.body : nil @@ -309,15 +310,31 @@ module Gem::GemcutterUtilities end def get_scope_params(scope) - scope_params = {} + scope_params = { index_rubygems: true } if scope scope_params = { scope => true } else - say "Please select scopes you want to enable for the API key (y/n)" - API_SCOPES.each do |s| - selected = ask_yes_no(s.to_s, false) - scope_params[s] = true if selected + say "The default access scope is:" + scope_params.each do |k, _v| + say " #{k}: y" + end + say "\n" + customise = ask_yes_no("Do you want to customise scopes?", false) + if customise + EXCLUSIVELY_API_SCOPES.each do |excl_scope| + selected = ask_yes_no("#{excl_scope} (exclusive scope, answering yes will not prompt for other scopes)", false) + next unless selected + + return { excl_scope => true } + end + + scope_params = {} + + API_SCOPES.each do |s| + selected = ask_yes_no(s.to_s, false) + scope_params[s] = true if selected + end end say "\n" end @@ -329,11 +346,11 @@ module Gem::GemcutterUtilities host == Gem::DEFAULT_HOST end - def get_user_profile(email, password) + def get_user_profile(identifier, password) return {} unless default_host? response = rubygems_api_request(:get, "api/v1/profile/me.yaml") do |request| - request.basic_auth email, password + request.basic_auth identifier, password end with_response response do |resp| diff --git a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb index bea9d9e397..abf65efe37 100644 --- a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +++ b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb @@ -51,7 +51,7 @@ module Gem::GemcutterUtilities request_line = socket.gets method, req_uri, _protocol = request_line.split(" ") - req_uri = URI.parse(req_uri) + req_uri = Gem::URI.parse(req_uri) responder = SocketResponder.new(socket) diff --git a/lib/rubygems/gemspec_helpers.rb b/lib/rubygems/gemspec_helpers.rb new file mode 100644 index 0000000000..2b20fcafa1 --- /dev/null +++ b/lib/rubygems/gemspec_helpers.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require_relative "../rubygems" + +## +# Mixin methods for commands that work with gemspecs. + +module Gem::GemspecHelpers + def find_gemspec(glob = "*.gemspec") + gemspecs = Dir.glob(glob).sort + + if gemspecs.size > 1 + alert_error "Multiple gemspecs found: #{gemspecs}, please specify one" + terminate_interaction(1) + end + + gemspecs.first + end +end diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb index e2a008fada..51a61213a5 100644 --- a/lib/rubygems/local_remote_options.rb +++ b/lib/rubygems/local_remote_options.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require "uri" +require_relative "vendor/uri/lib/uri" require_relative "../rubygems" ## @@ -17,10 +17,10 @@ module Gem::LocalRemoteOptions # Allows Gem::OptionParser to handle HTTP URIs. def accept_uri_http - Gem::OptionParser.accept URI::HTTP do |value| + Gem::OptionParser.accept Gem::URI::HTTP do |value| begin - uri = URI.parse value - rescue URI::InvalidURIError + uri = Gem::URI.parse value + rescue Gem::URI::InvalidURIError raise Gem::OptionParser::InvalidArgument, value end @@ -88,7 +88,7 @@ module Gem::LocalRemoteOptions def add_proxy_option accept_uri_http - add_option(:"Local/Remote", "-p", "--[no-]http-proxy [URL]", URI::HTTP, + add_option(:"Local/Remote", "-p", "--[no-]http-proxy [URL]", Gem::URI::HTTP, "Use HTTP proxy for remote operations") do |value, options| options[:http_proxy] = value == false ? :no_proxy : value Gem.configuration[:http_proxy] = options[:http_proxy] @@ -101,7 +101,7 @@ module Gem::LocalRemoteOptions def add_source_option accept_uri_http - add_option(:"Local/Remote", "-s", "--source URL", URI::HTTP, + add_option(:"Local/Remote", "-s", "--source URL", Gem::URI::HTTP, "Append URL to list of remote gem sources") do |source, options| source << "/" unless source.end_with?("/") diff --git a/lib/rubygems/net/http.rb b/lib/rubygems/net/http.rb deleted file mode 100644 index 1a21c05191..0000000000 --- a/lib/rubygems/net/http.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "../net-http/lib/net/http" diff --git a/lib/rubygems/optparse.rb b/lib/rubygems/optparse.rb deleted file mode 100644 index 6ed718423c..0000000000 --- a/lib/rubygems/optparse.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "optparse/lib/optparse" diff --git a/lib/rubygems/optparse/lib/optparse/uri.rb b/lib/rubygems/optparse/lib/optparse/uri.rb deleted file mode 100644 index 664d7f2af4..0000000000 --- a/lib/rubygems/optparse/lib/optparse/uri.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: false -# -*- ruby -*- - -require_relative '../optparse' -require 'uri' - -Gem::OptionParser.accept(URI) {|s,| URI.parse(s) if s} diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 387e40ffd7..1d5d764237 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -59,7 +59,7 @@ class Gem::Package def initialize(message, source = nil) if source - @path = source.path + @path = source.is_a?(String) ? source : source.path message += " in #{path}" if path end @@ -454,7 +454,7 @@ EOM if entry.file? File.open(destination, "wb") {|out| copy_stream(entry, out) } - FileUtils.chmod file_mode(entry.header.mode), destination + FileUtils.chmod file_mode(entry.header.mode) & ~File.umask, destination end verbose destination diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 8f14d7bc8d..c3a41592f6 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -74,9 +74,9 @@ class Gem::RemoteFetcher def initialize(proxy=nil, dns=nil, headers={}) require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled - require_relative "net/http" + require_relative "vendored_net_http" require "stringio" - require "uri" + require_relative "vendor/uri/lib/uri" Socket.do_not_reverse_lookup = true @@ -135,7 +135,7 @@ class Gem::RemoteFetcher scheme = source_uri.scheme - # URI.parse gets confused by MS Windows paths with forward slashes. + # Gem::URI.parse gets confused by MS Windows paths with forward slashes. scheme = nil if /^[a-z]$/i.match?(scheme) # REFACTOR: split this up and dispatch on scheme (eg download_http) diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb index 8702e223d6..9116785231 100644 --- a/lib/rubygems/request.rb +++ b/lib/rubygems/request.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "net/http" +require_relative "vendored_net_http" require_relative "user_interaction" class Gem::Request @@ -18,11 +18,11 @@ class Gem::Request end def self.proxy_uri(proxy) # :nodoc: - require "uri" + require_relative "vendor/uri/lib/uri" case proxy when :no_proxy then nil - when URI::HTTP then proxy - else URI.parse(proxy) + when Gem::URI::HTTP then proxy + else Gem::URI.parse(proxy) end end @@ -176,7 +176,7 @@ class Gem::Request end require "uri" - uri = URI(Gem::UriFormatter.new(env_proxy).normalize) + uri = Gem::URI(Gem::UriFormatter.new(env_proxy).normalize) if uri && uri.user.nil? && uri.password.nil? user = ENV["#{downcase_scheme}_proxy_user"] || ENV["#{upcase_scheme}_PROXY_USER"] diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index 02b3477661..875df7e019 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "tsort" +require_relative "vendored_tsort" ## # A RequestSet groups a request to activate a set of dependencies. diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb index 4ebafb065f..02543cb14a 100644 --- a/lib/rubygems/requirement.rb +++ b/lib/rubygems/requirement.rb @@ -284,6 +284,11 @@ class Gem::Requirement def _tilde_requirements @_tilde_requirements ||= _sorted_requirements.select {|r| r.first == "~>" } end + + def initialize_copy(other) # :nodoc: + @requirements = other.requirements.dup + super + end end class Gem::Version diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index 620ba921bc..115c716b6b 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -11,7 +11,7 @@ require_relative "util/list" # all the requirements. class Gem::Resolver - require_relative "resolver/molinillo" + require_relative "vendored_molinillo" ## # If the DEBUG_RESOLVER environment variable is set then debugging mode is @@ -167,7 +167,7 @@ class Gem::Resolver reqs end - include Molinillo::UI + include Gem::Molinillo::UI def output @output ||= debug? ? $stdout : File.open(IO::NULL, "w") @@ -177,14 +177,14 @@ class Gem::Resolver DEBUG_RESOLVER end - include Molinillo::SpecificationProvider + include Gem::Molinillo::SpecificationProvider ## # Proceed with resolution! Returns an array of ActivationRequest objects. def resolve - Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.map(&:payload).compact - rescue Molinillo::VersionConflict => e + Gem::Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.map(&:payload).compact + rescue Gem::Molinillo::VersionConflict => e conflict = e.conflicts.values.first raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement) ensure diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb index e8e3747361..3e4dadc40f 100644 --- a/lib/rubygems/resolver/api_set.rb +++ b/lib/rubygems/resolver/api_set.rb @@ -30,7 +30,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set def initialize(dep_uri = "https://index.rubygems.org/info/") super() - dep_uri = URI dep_uri unless URI === dep_uri + dep_uri = Gem::URI dep_uri unless Gem::URI === dep_uri @dep_uri = dep_uri @uri = dep_uri + ".." diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb index c2e8982047..a983f8c6b6 100644 --- a/lib/rubygems/resolver/best_set.rb +++ b/lib/rubygems/resolver/best_set.rb @@ -60,7 +60,7 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet def replace_failed_api_set(error) # :nodoc: uri = error.original_uri - uri = URI uri unless URI === uri + uri = Gem::URI uri unless Gem::URI === uri uri += "." raise error unless api_set = @sets.find do |set| diff --git a/lib/rubygems/resolver/molinillo.rb b/lib/rubygems/resolver/molinillo.rb deleted file mode 100644 index d703505410..0000000000 --- a/lib/rubygems/resolver/molinillo.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "molinillo/lib/molinillo" diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb deleted file mode 100644 index d540d3baff..0000000000 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Gem::Resolver::Molinillo - # @!visibility private - module Delegates - # Delegates all {Gem::Resolver::Molinillo::ResolutionState} methods to a `#state` property. - module ResolutionState - # (see Gem::Resolver::Molinillo::ResolutionState#name) - def name - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.name - end - - # (see Gem::Resolver::Molinillo::ResolutionState#requirements) - def requirements - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.requirements - end - - # (see Gem::Resolver::Molinillo::ResolutionState#activated) - def activated - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.activated - end - - # (see Gem::Resolver::Molinillo::ResolutionState#requirement) - def requirement - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.requirement - end - - # (see Gem::Resolver::Molinillo::ResolutionState#possibilities) - def possibilities - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.possibilities - end - - # (see Gem::Resolver::Molinillo::ResolutionState#depth) - def depth - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.depth - end - - # (see Gem::Resolver::Molinillo::ResolutionState#conflicts) - def conflicts - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.conflicts - end - - # (see Gem::Resolver::Molinillo::ResolutionState#unused_unwind_options) - def unused_unwind_options - current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty - current_state.unused_unwind_options - end - end - end -end diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb deleted file mode 100644 index 86c249c404..0000000000 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -module Gem::Resolver::Molinillo - # The version of Gem::Resolver::Molinillo. - VERSION = '0.8.0'.freeze -end diff --git a/lib/rubygems/resolver/spec_specification.rb b/lib/rubygems/resolver/spec_specification.rb index 79a34d8063..00ef9fdba0 100644 --- a/lib/rubygems/resolver/spec_specification.rb +++ b/lib/rubygems/resolver/spec_specification.rb @@ -66,4 +66,11 @@ class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification def version spec.version end + + ## + # The hash value for this specification. + + def hash + spec.hash + end end diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb index 53d49ec432..7c95a9d4f5 100644 --- a/lib/rubygems/s3_uri_signer.rb +++ b/lib/rubygems/s3_uri_signer.rb @@ -49,7 +49,7 @@ class Gem::S3URISigner string_to_sign = generate_string_to_sign(date_time, credential_info, canonical_request) signature = generate_signature(s3_config, date, string_to_sign) - URI.parse("https://#{canonical_host}#{uri.path}?#{query_params}&X-Amz-Signature=#{signature}") + Gem::URI.parse("https://#{canonical_host}#{uri.path}?#{query_params}&X-Amz-Signature=#{signature}") end private @@ -140,7 +140,7 @@ class Gem::S3URISigner end def ec2_metadata_credentials_json - require_relative "net/http" + require_relative "vendored_net_http" require_relative "request" require_relative "request/connection_pools" require "json" @@ -152,7 +152,7 @@ class Gem::S3URISigner end def ec2_metadata_request(url) - uri = URI(url) + uri = Gem::URI(url) @request_pool ||= create_request_pool(uri) request = Gem::Request.new(uri, Gem::Net::HTTP::Get, nil, @request_pool) response = request.fetch diff --git a/lib/rubygems/safe_yaml.rb b/lib/rubygems/safe_yaml.rb index dba3cfb16d..6a02a48230 100644 --- a/lib/rubygems/safe_yaml.rb +++ b/lib/rubygems/safe_yaml.rb @@ -25,8 +25,17 @@ module Gem runtime ].freeze + @aliases_enabled = true + def self.aliases_enabled=(value) # :nodoc: + @aliases_enabled = !!value + end + + def self.aliases_enabled? # :nodoc: + @aliases_enabled + end + def self.safe_load(input) - ::Psych.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true) + ::Psych.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: @aliases_enabled) end def self.load(input) diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb index 1e8e57b5a9..69ba87b07f 100644 --- a/lib/rubygems/security.rb +++ b/lib/rubygems/security.rb @@ -323,7 +323,7 @@ require_relative "openssl" # == Original author # # Paul Duncan <[email protected]> -# http://pablotron.org/ +# https://pablotron.org/ module Gem::Security ## diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb index a0d03312b9..bda63c6844 100644 --- a/lib/rubygems/source/git.rb +++ b/lib/rubygems/source/git.rb @@ -221,14 +221,14 @@ class Gem::Source::Git < Gem::Source end ## - # A hash for the git gem based on the git repository URI. + # A hash for the git gem based on the git repository Gem::URI. def uri_hash # :nodoc: require_relative "../openssl" normalized = if @repository.match?(%r{^\w+://(\w+@)?}) - uri = URI(@repository).normalize.to_s.sub %r{/$},"" + uri = Gem::URI(@repository).normalize.to_s.sub %r{/$},"" uri.sub(/\A(\w+)/) { $1.downcase } else @repository diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb index 9e8a9e16ef..33db64fbc1 100644 --- a/lib/rubygems/source_list.rb +++ b/lib/rubygems/source_list.rb @@ -44,7 +44,7 @@ class Gem::SourceList end ## - # Appends +obj+ to the source list which may be a Gem::Source, URI or URI + # Appends +obj+ to the source list which may be a Gem::Source, Gem::URI or URI # String. def <<(obj) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 169002d7c7..61ea3fcfdc 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -341,7 +341,7 @@ class Gem::Specification < Gem::BasicSpecification # https://opensource.org/licenses/ approved. # # The most commonly used OSI-approved licenses are MIT and Apache-2.0. - # GitHub also provides a license picker at http://choosealicense.com/. + # GitHub also provides a license picker at https://choosealicense.com/. # # You can also use a custom license file along with your gemspec and specify # a LicenseRef-<idstring>, where idstring is the name of the file containing @@ -1003,8 +1003,6 @@ class Gem::Specification < Gem::BasicSpecification def self.find_all_by_name(name, *requirements) requirements = Gem::Requirement.default if requirements.empty? - # TODO: maybe try: find_all { |s| spec === dep } - Gem::Dependency.new(name, *requirements).matching_specs end @@ -1022,8 +1020,6 @@ class Gem::Specification < Gem::BasicSpecification def self.find_by_name(name, *requirements) requirements = Gem::Requirement.default if requirements.empty? - # TODO: maybe try: find { |s| spec === dep } - Gem::Dependency.new(name, *requirements).to_spec end @@ -2079,7 +2075,8 @@ class Gem::Specification < Gem::BasicSpecification end ## - # Duplicates array_attributes from +other_spec+ so state isn't shared. + # Duplicates Array and Gem::Requirement attributes from +other_spec+ so state isn't shared. + # def initialize_copy(other_spec) self.class.array_attributes.each do |name| @@ -2101,6 +2098,9 @@ class Gem::Specification < Gem::BasicSpecification raise e end end + + @required_ruby_version = other_spec.required_ruby_version.dup + @required_rubygems_version = other_spec.required_rubygems_version.dup end def base_dir diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index 6655825287..516c26f53c 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -7,7 +7,7 @@ class Gem::SpecificationPolicy VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc: - SPECIAL_CHARACTERS = /\A[#{Regexp.escape('.-_')}]+/ # :nodoc: + SPECIAL_CHARACTERS = /\A[#{Regexp.escape(".-_")}]+/ # :nodoc: VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z} # :nodoc: @@ -103,6 +103,8 @@ class Gem::SpecificationPolicy validate_dependencies + validate_required_ruby_version + validate_extensions validate_removed_attributes @@ -227,6 +229,12 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use: end end + def validate_required_ruby_version + if @specification.required_ruby_version.requirements == [Gem::Requirement::DefaultRequirement] + warning "make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute" + end + end + ## # Issues a warning for each file to be packaged which is world-readable. # @@ -427,13 +435,13 @@ or set it to nil if you don't want to specify a license. # Make sure a homepage is valid HTTP/HTTPS URI if homepage && !homepage.empty? - require "uri" + require_relative "vendor/uri/lib/uri" begin - homepage_uri = URI.parse(homepage) - unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class + homepage_uri = Gem::URI.parse(homepage) + unless [Gem::URI::HTTP, Gem::URI::HTTPS].member? homepage_uri.class error "\"#{homepage}\" is not a valid HTTP URI" end - rescue URI::InvalidURIError + rescue Gem::URI::InvalidURIError error "\"#{homepage}\" is not a valid HTTP URI" end end @@ -497,10 +505,10 @@ You have specified rust based extension, but Cargo.lock is not part of the gem f def validate_rake_extensions(builder) # :nodoc: rake_extension = @specification.extensions.any? {|s| builder.builder_for(s) == Gem::Ext::RakeBuilder } - rake_dependency = @specification.dependencies.any? {|d| d.name == "rake" } + rake_dependency = @specification.dependencies.any? {|d| d.name == "rake" && d.type == :runtime } warning <<-WARNING if rake_extension && !rake_dependency -You have specified rake based extension, but rake is not added as dependency. It is recommended to add rake as a dependency in gemspec since there's no guarantee rake will be already installed. +You have specified rake based extension, but rake is not added as runtime dependency. It is recommended to add rake as a runtime dependency in gemspec since there's no guarantee rake will be already installed. WARNING end diff --git a/lib/rubygems/timeout.rb b/lib/rubygems/timeout.rb deleted file mode 100644 index 33c54a2aa4..0000000000 --- a/lib/rubygems/timeout.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "timeout/lib/timeout" diff --git a/lib/rubygems/tsort.rb b/lib/rubygems/tsort.rb deleted file mode 100644 index 60ebe22e81..0000000000 --- a/lib/rubygems/tsort.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "tsort/lib/tsort" diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb index 4b5d035aa0..a44aaceba5 100644 --- a/lib/rubygems/uri.rb +++ b/lib/rubygems/uri.rb @@ -16,9 +16,9 @@ class Gem::Uri # Parses uri, raising if it's invalid def self.parse!(uri) - require "uri" + require_relative "vendor/uri/lib/uri" - raise URI::InvalidURIError unless uri + raise Gem::URI::InvalidURIError unless uri return uri unless uri.is_a?(String) @@ -28,9 +28,9 @@ class Gem::Uri # as "%7BDESede%7D". If this is escaped again the percentage # symbols will be escaped. begin - URI.parse(uri) - rescue URI::InvalidURIError - URI.parse(URI::DEFAULT_PARSER.escape(uri)) + Gem::URI.parse(uri) + rescue Gem::URI::InvalidURIError + Gem::URI.parse(Gem::URI::DEFAULT_PARSER.escape(uri)) end end @@ -39,7 +39,7 @@ class Gem::Uri def self.parse(uri) parse!(uri) - rescue URI::InvalidURIError + rescue Gem::URI::InvalidURIError uri end diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb index 1815f6af6f..51f9c2029f 100644 --- a/lib/rubygems/util.rb +++ b/lib/rubygems/util.rb @@ -105,7 +105,7 @@ module Gem::Util end ## - # Corrects +path+ (usually returned by `URI.parse().path` on Windows), that + # Corrects +path+ (usually returned by `Gem::URI.parse().path` on Windows), that # comes with a leading slash. def self.correct_for_windows_path(path) diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb index 47dbc17304..f3c7201639 100644 --- a/lib/rubygems/util/licenses.rb +++ b/lib/rubygems/util/licenses.rb @@ -28,6 +28,7 @@ class Gem::Licenses AGPL-3.0-or-later AMDPLPA AML + AML-glslang AMPAS ANTLR-PD ANTLR-PD-fallback @@ -42,6 +43,7 @@ class Gem::Licenses Abstyles AdaCore-doc Adobe-2006 + Adobe-Display-PostScript Adobe-Glyph Adobe-Utopia Afmparse @@ -57,6 +59,7 @@ class Gem::Licenses Artistic-2.0 BSD-1-Clause BSD-2-Clause + BSD-2-Clause-Darwin BSD-2-Clause-Patent BSD-2-Clause-Views BSD-3-Clause @@ -71,6 +74,7 @@ class Gem::Licenses BSD-3-Clause-No-Nuclear-Warranty BSD-3-Clause-Open-MPI BSD-3-Clause-Sun + BSD-3-Clause-acpica BSD-3-Clause-flex BSD-4-Clause BSD-4-Clause-Shortened @@ -82,7 +86,9 @@ class Gem::Licenses BSD-Inferno-Nettverk BSD-Protection BSD-Source-Code + BSD-Source-beginning-file BSD-Systemics + BSD-Systemics-W3Works BSL-1.0 BUSL-1.1 Baekmuk @@ -96,6 +102,7 @@ class Gem::Licenses BlueOak-1.0.0 Boehm-GC Borceux + Brian-Gladman-2-Clause Brian-Gladman-3-Clause C-UDA-1.0 CAL-1.0 @@ -107,6 +114,7 @@ class Gem::Licenses CC-BY-2.5-AU CC-BY-3.0 CC-BY-3.0-AT + CC-BY-3.0-AU CC-BY-3.0-DE CC-BY-3.0-IGO CC-BY-3.0-NL @@ -172,6 +180,7 @@ class Gem::Licenses CERN-OHL-W-2.0 CFITSIO CMU-Mach + CMU-Mach-nodoc CNRI-Jython CNRI-Python CNRI-Python-GPL-Compatible @@ -181,6 +190,7 @@ class Gem::Licenses CPOL-1.02 CUA-OPL-1.0 Caldera + Caldera-no-preamble ClArtistic Clips Community-Spec-1.0 @@ -191,10 +201,12 @@ class Gem::Licenses CrystalStacker Cube D-FSL-1.0 + DEC-3-Clause DL-DE-BY-2.0 DL-DE-ZERO-2.0 DOC DRL-1.0 + DRL-1.1 DSDP Dotseqn ECL-1.0 @@ -215,6 +227,7 @@ class Gem::Licenses FBM FDK-AAC FSFAP + FSFAP-no-warranty-disclaimer FSFUL FSFULLR FSFULLRWD @@ -225,6 +238,7 @@ class Gem::Licenses FreeBSD-DOC FreeImage Furuseth + GCR-docs GD GFDL-1.1-invariants-only GFDL-1.1-invariants-or-later @@ -260,6 +274,10 @@ class Gem::Licenses HP-1989 HPND HPND-DEC + HPND-Fenneberg-Livingston + HPND-INRIA-IMAG + HPND-Kevlin-Henney + HPND-MIT-disclaimer HPND-Markus-Kuhn HPND-Pbmplus HPND-UC @@ -267,6 +285,7 @@ class Gem::Licenses HPND-doc-sell HPND-export-US HPND-export-US-modify + HPND-sell-MIT-disclaimer-xserver HPND-sell-regexpr HPND-sell-variant HPND-sell-variant-MIT-disclaimer @@ -281,6 +300,7 @@ class Gem::Licenses IPA IPL-1.0 ISC + ISC-Veillard ImageMagick Imlib2 Info-ZIP @@ -306,6 +326,7 @@ class Gem::Licenses LGPL-3.0-or-later LGPLLR LOOP + LPD-document LPL-1.0 LPL-1.02 LPPL-1.0 @@ -350,6 +371,8 @@ class Gem::Licenses MS-PL MS-RL MTLL + Mackerras-3-Clause + Mackerras-3-Clause-acknowledgment MakeIndex Martin-Birgmeier McPhee-slideshow @@ -434,6 +457,8 @@ class Gem::Licenses OSL-3.0 OpenPBS-2.3 OpenSSL + OpenSSL-standalone + OpenVision PADL PDDL-1.0 PHP-3.0 @@ -441,6 +466,7 @@ class Gem::Licenses PSF-2.0 Parity-6.0.0 Parity-7.0.0 + Pixar Plexus PolyForm-Noncommercial-1.0.0 PolyForm-Small-Business-1.0.0 @@ -459,6 +485,7 @@ class Gem::Licenses Rdisc Ruby SAX-PD + SAX-PD-2.0 SCEA SGI-B-1.0 SGI-B-1.1 @@ -476,6 +503,7 @@ class Gem::Licenses SPL-1.0 SSH-OpenSSH SSH-short + SSLeay-standalone SSPL-1.0 SWL Saxpath @@ -489,11 +517,13 @@ class Gem::Licenses Spencer-94 Spencer-99 SugarCRM-1.1.3 + Sun-PPP SunPro Symlinks TAPR-OHL-1.0 TCL TCP-wrappers + TGPPL-1.0 TMate TORQUE-1.1 TOSL @@ -506,8 +536,10 @@ class Gem::Licenses TermReadKey UCAR UCL-1.0 + UMich-Merit UPL-1.0 URT-RLE + Unicode-3.0 Unicode-DFS-2015 Unicode-DFS-2016 Unicode-TOU @@ -542,6 +574,7 @@ class Gem::Licenses Zimbra-1.3 Zimbra-1.4 Zlib + bcrypt-Solar-Designer blessing bzip2-1.0.6 check-cvs @@ -557,6 +590,8 @@ class Gem::Licenses fwlw gSOAP-1.3b gnuplot + gtkbook + hdparm iMatix libpng-2.0 libselinux-1.0 @@ -564,6 +599,7 @@ class Gem::Licenses libutil-David-Nugent lsof magaz + mailprio metamail mpi-permissive mpich2 @@ -572,12 +608,15 @@ class Gem::Licenses psfrag psutils python-ldap + radvd snprintf + softSurfer ssh-keyscan swrule ulem w3m xinetd + xkeyboard-config-Zinoviev xlock xpp zlib-acknowledgement @@ -626,6 +665,7 @@ class Gem::Licenses Autoconf-exception-generic Autoconf-exception-generic-3.0 Autoconf-exception-macro + Bison-exception-1.24 Bison-exception-2.2 Bootloader-exception CLISP-exception-2.0 @@ -638,6 +678,7 @@ class Gem::Licenses GCC-exception-2.0-note GCC-exception-3.1 GNAT-exception + GNOME-examples-exception GNU-compiler-exception GPL-3.0-interface-exception GPL-3.0-linking-exception @@ -645,6 +686,7 @@ class Gem::Licenses GPL-CC-1.0 GStreamer-exception-2005 GStreamer-exception-2008 + Gmsh-exception KiCad-libraries-exception LGPL-3.0-linking-exception LLGPL @@ -671,6 +713,7 @@ class Gem::Licenses WxWindows-exception-3.1 cryptsetup-OpenSSL-exception eCos-exception-2.0 + fmt-exception freertos-exception-2.0 gnu-javamail-exception i2p-gpl-java-exception diff --git a/lib/rubygems/net-http/.document b/lib/rubygems/vendor/molinillo/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/net-http/.document +++ b/lib/rubygems/vendor/molinillo/.document diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo.rb b/lib/rubygems/vendor/molinillo/lib/molinillo.rb index f67badbde7..dd5600c9e3 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo.rb @@ -6,6 +6,6 @@ require_relative 'molinillo/resolver' require_relative 'molinillo/modules/ui' require_relative 'molinillo/modules/specification_provider' -# Gem::Resolver::Molinillo is a generic dependency resolution algorithm. -module Gem::Resolver::Molinillo +# Gem::Molinillo is a generic dependency resolution algorithm. +module Gem::Molinillo end diff --git a/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb new file mode 100644 index 0000000000..34842d46d5 --- /dev/null +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Gem::Molinillo + # @!visibility private + module Delegates + # Delegates all {Gem::Molinillo::ResolutionState} methods to a `#state` property. + module ResolutionState + # (see Gem::Molinillo::ResolutionState#name) + def name + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.name + end + + # (see Gem::Molinillo::ResolutionState#requirements) + def requirements + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.requirements + end + + # (see Gem::Molinillo::ResolutionState#activated) + def activated + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.activated + end + + # (see Gem::Molinillo::ResolutionState#requirement) + def requirement + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.requirement + end + + # (see Gem::Molinillo::ResolutionState#possibilities) + def possibilities + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.possibilities + end + + # (see Gem::Molinillo::ResolutionState#depth) + def depth + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.depth + end + + # (see Gem::Molinillo::ResolutionState#conflicts) + def conflicts + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.conflicts + end + + # (see Gem::Molinillo::ResolutionState#unused_unwind_options) + def unused_unwind_options + current_state = state || Gem::Molinillo::ResolutionState.empty + current_state.unused_unwind_options + end + end + end +end diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb index b765226fb0..8417721537 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb @@ -1,67 +1,67 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo module Delegates - # Delegates all {Gem::Resolver::Molinillo::SpecificationProvider} methods to a + # Delegates all {Gem::Molinillo::SpecificationProvider} methods to a # `#specification_provider` property. module SpecificationProvider - # (see Gem::Resolver::Molinillo::SpecificationProvider#search_for) + # (see Gem::Molinillo::SpecificationProvider#search_for) def search_for(dependency) with_no_such_dependency_error_handling do specification_provider.search_for(dependency) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_for) + # (see Gem::Molinillo::SpecificationProvider#dependencies_for) def dependencies_for(specification) with_no_such_dependency_error_handling do specification_provider.dependencies_for(specification) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#requirement_satisfied_by?) + # (see Gem::Molinillo::SpecificationProvider#requirement_satisfied_by?) def requirement_satisfied_by?(requirement, activated, spec) with_no_such_dependency_error_handling do specification_provider.requirement_satisfied_by?(requirement, activated, spec) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_equal?) + # (see Gem::Molinillo::SpecificationProvider#dependencies_equal?) def dependencies_equal?(dependencies, other_dependencies) with_no_such_dependency_error_handling do specification_provider.dependencies_equal?(dependencies, other_dependencies) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#name_for) + # (see Gem::Molinillo::SpecificationProvider#name_for) def name_for(dependency) with_no_such_dependency_error_handling do specification_provider.name_for(dependency) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#name_for_explicit_dependency_source) + # (see Gem::Molinillo::SpecificationProvider#name_for_explicit_dependency_source) def name_for_explicit_dependency_source with_no_such_dependency_error_handling do specification_provider.name_for_explicit_dependency_source end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#name_for_locking_dependency_source) + # (see Gem::Molinillo::SpecificationProvider#name_for_locking_dependency_source) def name_for_locking_dependency_source with_no_such_dependency_error_handling do specification_provider.name_for_locking_dependency_source end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#sort_dependencies) + # (see Gem::Molinillo::SpecificationProvider#sort_dependencies) def sort_dependencies(dependencies, activated, conflicts) with_no_such_dependency_error_handling do specification_provider.sort_dependencies(dependencies, activated, conflicts) end end - # (see Gem::Resolver::Molinillo::SpecificationProvider#allow_missing?) + # (see Gem::Molinillo::SpecificationProvider#allow_missing?) def allow_missing?(dependency) with_no_such_dependency_error_handling do specification_provider.allow_missing?(dependency) diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb index 731a9e3e90..2dbbc589dc 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require_relative '../../../../tsort' +require_relative '../../../../vendored_tsort' require_relative 'dependency_graph/log' require_relative 'dependency_graph/vertex' -module Gem::Resolver::Molinillo +module Gem::Molinillo # A directed acyclic graph that is tuned to hold named dependencies class DependencyGraph include Enumerable diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/action.rb index cc140031b3..8707ec451d 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/action.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # An action that modifies a {DependencyGraph} that is reversible. # @abstract diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb index 5570483253..aa9815c5ae 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # (see DependencyGraph#add_edge_no_circular) diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb index f1411d5efa..9c7066a669 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # (see DependencyGraph#add_vertex) diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb index 3b48d77a50..1e62c0a0b6 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # (see DependencyGraph#delete_edge) diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb index 92f60d5be8..6132f969b9 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # @see DependencyGraph#detach_vertex_named diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/log.rb index 7aeb8847ec..6954c4b1f8 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/log.rb @@ -7,7 +7,7 @@ require_relative 'detach_vertex_named' require_relative 'set_payload' require_relative 'tag' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # A log for dependency graph actions class Log diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb index 726292a2c3..9bcaaae0f9 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # @see DependencyGraph#set_payload diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb index bfe6fd31f8..62f243a2af 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative 'action' -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # @!visibility private # @see DependencyGraph#tag diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb index 77114951b2..074de369be 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo class DependencyGraph # A vertex in a {DependencyGraph} that encapsulates a {#name} and a # {#payload} diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/errors.rb index 4289902828..07ea5fdf37 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/errors.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo # An error that occurred during the resolution process class ResolverError < StandardError; end diff --git a/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb new file mode 100644 index 0000000000..8ed3a920a2 --- /dev/null +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Gem::Molinillo + # The version of Gem::Molinillo. + VERSION = '0.8.0'.freeze +end diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/modules/specification_provider.rb index 1067bf7439..85860902fc 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/modules/specification_provider.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo # Provides information about specifications and dependencies to the resolver, # allowing the {Resolver} class to remain generic while still providing power # and flexibility. # - # This module contains the methods that users of Gem::Resolver::Molinillo must to implement, + # This module contains the methods that users of Gem::Molinillo must to implement, # using knowledge of their own model classes. module SpecificationProvider # Search for the specifications that match the given dependency. diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/modules/ui.rb index a810fd519c..464722902e 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/modules/ui.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo # Conveys information about the resolution process to a user. module UI # The {IO} object that should be used to print output. `STDOUT`, by default. diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/resolution.rb index 8b40e59e42..5cfc6e3a0d 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/resolution.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo class Resolver # A specific resolution from a given {Resolver} class Resolution @@ -244,8 +244,8 @@ module Gem::Resolver::Molinillo require_relative 'delegates/resolution_state' require_relative 'delegates/specification_provider' - include Gem::Resolver::Molinillo::Delegates::ResolutionState - include Gem::Resolver::Molinillo::Delegates::SpecificationProvider + include Gem::Molinillo::Delegates::ResolutionState + include Gem::Molinillo::Delegates::SpecificationProvider # Processes the topmost available {RequirementState} on the stack # @return [void] diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/resolver.rb index d43121f8ca..86229c3fa1 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/resolver.rb @@ -2,7 +2,7 @@ require_relative 'dependency_graph' -module Gem::Resolver::Molinillo +module Gem::Molinillo # This class encapsulates a dependency resolver. # The resolver is responsible for determining which set of dependencies to # activate, with feedback from the {#specification_provider} diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/state.rb index 6e7c715fce..c48ec6af9c 100644 --- a/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/state.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Gem::Resolver::Molinillo +module Gem::Molinillo # A state that a {Resolution} can be in # @attr [String] name the name of the current requirement # @attr [Array<Object>] requirements currently unsatisfied requirements diff --git a/lib/rubygems/net-protocol/.document b/lib/rubygems/vendor/net-http/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/net-protocol/.document +++ b/lib/rubygems/vendor/net-http/.document diff --git a/lib/rubygems/net-http/lib/net/http.rb b/lib/rubygems/vendor/net-http/lib/net/http.rb index 833912e9a2..25c870a591 100644 --- a/lib/rubygems/net-http/lib/net/http.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http.rb @@ -21,7 +21,7 @@ # require_relative '../../../net-protocol/lib/net/protocol' -require 'uri' +require_relative '../../../uri/lib/uri' require_relative '../../../resolv/lib/resolv' autoload :OpenSSL, 'openssl' @@ -46,7 +46,7 @@ module Gem::Net #:nodoc: # == Strategies # # - If you will make only a few GET requests, - # consider using {OpenURI}[rdoc-ref:OpenURI]. + # consider using {OpenURI}[https://docs.ruby-lang.org/en/master/OpenURI.html]. # - If you will make only a few requests of all kinds, # consider using the various singleton convenience methods in this class. # Each of the following methods automatically starts and finishes @@ -106,20 +106,20 @@ module Gem::Net #:nodoc: # It consists of some or all of: scheme, hostname, path, query, and fragment; # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax]. # - # A Ruby {URI::Generic}[rdoc-ref:URI::Generic] object + # A Ruby {Gem::URI::Generic}[https://docs.ruby-lang.org/en/master/Gem/URI/Generic.html] object # represents an internet URI. # It provides, among others, methods # +scheme+, +hostname+, +path+, +query+, and +fragment+. # # === Schemes # - # An internet \URI has + # An internet \Gem::URI has # a {scheme}[https://en.wikipedia.org/wiki/List_of_URI_schemes]. # # The two schemes supported in \Gem::Net::HTTP are <tt>'https'</tt> and <tt>'http'</tt>: # # uri.scheme # => "https" - # URI('http://example.com').scheme # => "http" + # Gem::URI('http://example.com').scheme # => "http" # # === Hostnames # @@ -146,8 +146,8 @@ module Gem::Net #:nodoc: # # _uri = uri.dup # params = {userId: 1, completed: false} - # _uri.query = URI.encode_www_form(params) - # _uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false> + # _uri.query = Gem::URI.encode_www_form(params) + # _uri # => #<Gem::URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false> # Gem::Net::HTTP.get(_uri) # # === Fragments @@ -273,7 +273,7 @@ module Gem::Net #:nodoc: # # You should choose a better exception. # raise ArgumentError, 'Too many HTTP redirects' if limit == 0 # - # res = Gem::Net::HTTP.get_response(URI(uri)) + # res = Gem::Net::HTTP.get_response(Gem::URI(uri)) # case res # when Gem::Net::HTTPSuccess # Any success class. # res @@ -327,9 +327,9 @@ module Gem::Net #:nodoc: # # Or if you simply want to make a GET request, you may pass in a URI # object that has an \HTTPS URL. \Gem::Net::HTTP automatically turns on TLS - # verification if the URI object has a 'https' URI scheme: + # verification if the URI object has a 'https' :URI scheme: # - # uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com/> + # uri # => #<Gem::URI::HTTPS https://jsonplaceholder.typicode.com/> # Gem::Net::HTTP.get(uri) # # == Proxy Server @@ -371,9 +371,9 @@ module Gem::Net #:nodoc: # === Proxy Using '<tt>ENV['http_proxy']</tt>' # # When environment variable <tt>'http_proxy'</tt> - # is set to a \URI string, + # is set to a \Gem::URI string, # the returned +http+ will have the server at that URI as its proxy; - # note that the \URI string must have a protocol + # note that the \Gem::URI string must have a protocol # such as <tt>'http'</tt> or <tt>'https'</tt>: # # ENV['http_proxy'] = 'http://example.com' @@ -386,7 +386,7 @@ module Gem::Net #:nodoc: # http.proxy_user # => nil # http.proxy_pass # => nil # - # The \URI string may include proxy username, password, and port number: + # The \Gem::URI string may include proxy username, password, and port number: # # ENV['http_proxy'] = 'http://pname:[email protected]:8000' # http = Gem::Net::HTTP.new(hostname) @@ -790,7 +790,7 @@ module Gem::Net #:nodoc: # # With URI object +uri+ and optional hash argument +headers+: # - # uri = URI('https://jsonplaceholder.typicode.com/todos/1') + # uri = Gem::URI('https://jsonplaceholder.typicode.com/todos/1') # headers = {'Content-type' => 'application/json; charset=UTF-8'} # Gem::Net::HTTP.get(uri, headers) # @@ -1074,7 +1074,7 @@ module Gem::Net #:nodoc: elsif p_addr == :ENV then http.proxy_from_env = true else - if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, port, p_no_proxy) + if p_addr && p_no_proxy && !Gem::URI::Generic.use_proxy?(address, address, port, p_no_proxy) p_addr = nil p_port = nil end @@ -1217,7 +1217,7 @@ module Gem::Net #:nodoc: # - The name of an encoding. # - An alias for an encoding name. # - # See {Encoding}[rdoc-ref:Encoding]. + # See {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html]. # # Examples: # @@ -1490,11 +1490,11 @@ module Gem::Net #:nodoc: attr_accessor :cert_store # Sets or returns the available SSL ciphers. - # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D]. + # See {OpenSSL::SSL::SSLContext#ciphers=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ciphers-3D]. attr_accessor :ciphers # Sets or returns the extra X509 certificates to be added to the certificate chain. - # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate]. + # See {OpenSSL::SSL::SSLContext#add_certificate}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-add_certificate]. attr_accessor :extra_chain_cert # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. @@ -1504,15 +1504,15 @@ module Gem::Net #:nodoc: attr_accessor :ssl_timeout # Sets or returns the SSL version. - # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D]. + # See {OpenSSL::SSL::SSLContext#ssl_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D]. attr_accessor :ssl_version # Sets or returns the minimum SSL version. - # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D]. + # See {OpenSSL::SSL::SSLContext#min_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D]. attr_accessor :min_version # Sets or returns the maximum SSL version. - # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D]. + # See {OpenSSL::SSL::SSLContext#max_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D]. attr_accessor :max_version # Sets or returns the callback for the server certification verification. @@ -1528,7 +1528,7 @@ module Gem::Net #:nodoc: # Sets or returns whether to verify that the server certificate is valid # for the hostname. - # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode]. + # See {OpenSSL::SSL::SSLContext#verify_hostname=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_mode]. attr_accessor :verify_hostname # Returns the X509 certificate chain (an array of strings) @@ -1796,7 +1796,7 @@ module Gem::Net #:nodoc: # The proxy URI determined from the environment for this connection. def proxy_uri # :nodoc: return if @proxy_uri == false - @proxy_uri ||= URI::HTTP.new( + @proxy_uri ||= Gem::URI::HTTP.new( "http", nil, address, port, nil, nil, nil, nil, nil ).find_proxy || false @proxy_uri || nil diff --git a/lib/rubygems/net-http/lib/net/http/backward.rb b/lib/rubygems/vendor/net-http/lib/net/http/backward.rb index 10dbc16224..10dbc16224 100644 --- a/lib/rubygems/net-http/lib/net/http/backward.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/backward.rb diff --git a/lib/rubygems/net-http/lib/net/http/exceptions.rb b/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb index c629c0113b..c629c0113b 100644 --- a/lib/rubygems/net-http/lib/net/http/exceptions.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb diff --git a/lib/rubygems/net-http/lib/net/http/generic_request.rb b/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb index a83f4761f2..5cfe75a7cd 100644 --- a/lib/rubygems/net-http/lib/net/http/generic_request.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb @@ -17,10 +17,10 @@ class Gem::Net::HTTPGenericRequest @request_has_body = reqbody @response_has_body = resbody - if URI === uri_or_path then - raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path + if Gem::URI === uri_or_path then + raise ArgumentError, "not an HTTP Gem::URI" unless Gem::URI::HTTP === uri_or_path hostname = uri_or_path.hostname - raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0) + raise ArgumentError, "no host component for Gem::URI" unless (hostname && hostname.length > 0) @uri = uri_or_path.dup host = @uri.hostname.dup host << ":" << @uri.port.to_s if @uri.port != @uri.default_port @@ -71,10 +71,10 @@ class Gem::Net::HTTPGenericRequest # attr_reader :path - # Returns the URI object for the request, or +nil+ if none: + # Returns the Gem::URI object for the request, or +nil+ if none: # # Gem::Net::HTTP::Get.new(uri).uri - # # => #<URI::HTTPS https://jsonplaceholder.typicode.com/> + # # => #<Gem::URI::HTTPS https://jsonplaceholder.typicode.com/> # Gem::Net::HTTP::Get.new('example.com').uri # => nil # attr_reader :uri @@ -213,10 +213,10 @@ class Gem::Net::HTTPGenericRequest if ssl scheme = 'https' - klass = URI::HTTPS + klass = Gem::URI::HTTPS else scheme = 'http' - klass = URI::HTTP + klass = Gem::URI::HTTP end if host = self['host'] @@ -225,7 +225,7 @@ class Gem::Net::HTTPGenericRequest else host = addr end - # convert the class of the URI + # convert the class of the Gem::URI if @uri.is_a?(klass) @uri.host = host @uri.port = port @@ -286,7 +286,7 @@ class Gem::Net::HTTPGenericRequest def send_request_with_body_data(sock, ver, path, params) if /\Amultipart\/form-data\z/i !~ self.content_type self.content_type = 'application/x-www-form-urlencoded' - return send_request_with_body(sock, ver, path, URI.encode_www_form(params)) + return send_request_with_body(sock, ver, path, Gem::URI.encode_www_form(params)) end opt = @form_option.dup diff --git a/lib/rubygems/net-http/lib/net/http/header.rb b/lib/rubygems/vendor/net-http/lib/net/http/header.rb index 918ffa9c08..1488e60068 100644 --- a/lib/rubygems/net-http/lib/net/http/header.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/header.rb @@ -782,7 +782,7 @@ module Gem::Net::HTTPHeader # The resulting request is suitable for HTTP request +POST+ or +PUT+. # # Argument +params+ must be suitable for use as argument +enum+ to - # {URI.encode_www_form}[https://docs.ruby-lang.org/en/master/URI.html#method-c-encode_www_form]. + # {Gem::URI.encode_www_form}[https://docs.ruby-lang.org/en/master/Gem::URI.html#method-c-encode_www_form]. # # With only argument +params+ given, # sets the body to a URL-encoded string with the default separator <tt>'&'</tt>: @@ -810,7 +810,7 @@ module Gem::Net::HTTPHeader # # Gem::Net::HTTPHeader#form_data= is an alias for Gem::Net::HTTPHeader#set_form_data. def set_form_data(params, sep = '&') - query = URI.encode_www_form(params) + query = Gem::URI.encode_www_form(params) query.gsub!(/&/, sep) if sep != '&' self.body = query self.content_type = 'application/x-www-form-urlencoded' diff --git a/lib/rubygems/net-http/lib/net/http/proxy_delta.rb b/lib/rubygems/vendor/net-http/lib/net/http/proxy_delta.rb index 137295a883..137295a883 100644 --- a/lib/rubygems/net-http/lib/net/http/proxy_delta.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/proxy_delta.rb diff --git a/lib/rubygems/net-http/lib/net/http/request.rb b/lib/rubygems/vendor/net-http/lib/net/http/request.rb index 857cbc7f67..495ec9be54 100644 --- a/lib/rubygems/net-http/lib/net/http/request.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/request.rb @@ -6,10 +6,10 @@ # # == Creating a Request # -# An request object may be created with either a URI or a string hostname: +# An request object may be created with either a Gem::URI or a string hostname: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('https://jsonplaceholder.typicode.com/') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('https://jsonplaceholder.typicode.com/') # req = Gem::Net::HTTP::Get.new(uri) # => #<Gem::Net::HTTP::Get GET> # req = Gem::Net::HTTP::Get.new(uri.hostname) # => #<Gem::Net::HTTP::Get GET> # diff --git a/lib/rubygems/net-http/lib/net/http/requests.rb b/lib/rubygems/vendor/net-http/lib/net/http/requests.rb index 3e26be949b..1a57ddc7c2 100644 --- a/lib/rubygems/net-http/lib/net/http/requests.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/requests.rb @@ -5,8 +5,8 @@ # \Class for representing # {HTTP method GET}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#GET_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Get.new(uri) # => #<Gem::Net::HTTP::Get GET> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -37,8 +37,8 @@ end # \Class for representing # {HTTP method HEAD}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#HEAD_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Head.new(uri) # => #<Gem::Net::HTTP::Head HEAD> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -68,8 +68,8 @@ end # \Class for representing # {HTTP method POST}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#POST_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Post.new(uri) # => #<Gem::Net::HTTP::Post POST> @@ -103,8 +103,8 @@ end # \Class for representing # {HTTP method PUT}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PUT_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Put.new(uri) # => #<Gem::Net::HTTP::Put PUT> @@ -133,8 +133,8 @@ end # \Class for representing # {HTTP method DELETE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#DELETE_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts/1' # req = Gem::Net::HTTP::Delete.new(uri) # => #<Gem::Net::HTTP::Delete DELETE> @@ -165,8 +165,8 @@ end # \Class for representing # {HTTP method OPTIONS}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#OPTIONS_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Options.new(uri) # => #<Gem::Net::HTTP::Options OPTIONS> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -196,8 +196,8 @@ end # \Class for representing # {HTTP method TRACE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#TRACE_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Trace.new(uri) # => #<Gem::Net::HTTP::Trace TRACE> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -227,8 +227,8 @@ end # \Class for representing # {HTTP method PATCH}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PATCH_method]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Patch.new(uri) # => #<Gem::Net::HTTP::Patch PATCH> @@ -265,8 +265,8 @@ end # \Class for representing # {WebDAV method PROPFIND}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Propfind.new(uri) # => #<Gem::Net::HTTP::Propfind PROPFIND> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -288,8 +288,8 @@ end # \Class for representing # {WebDAV method PROPPATCH}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPPATCH]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Proppatch.new(uri) # => #<Gem::Net::HTTP::Proppatch PROPPATCH> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -311,8 +311,8 @@ end # \Class for representing # {WebDAV method MKCOL}[http://www.webdav.org/specs/rfc4918.html#METHOD_MKCOL]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Mkcol.new(uri) # => #<Gem::Net::HTTP::Mkcol MKCOL> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -334,8 +334,8 @@ end # \Class for representing # {WebDAV method COPY}[http://www.webdav.org/specs/rfc4918.html#METHOD_COPY]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Copy.new(uri) # => #<Gem::Net::HTTP::Copy COPY> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -357,8 +357,8 @@ end # \Class for representing # {WebDAV method MOVE}[http://www.webdav.org/specs/rfc4918.html#METHOD_MOVE]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Move.new(uri) # => #<Gem::Net::HTTP::Move MOVE> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -380,8 +380,8 @@ end # \Class for representing # {WebDAV method LOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_LOCK]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Lock.new(uri) # => #<Gem::Net::HTTP::Lock LOCK> # res = Gem::Net::HTTP.start(hostname) do |http| @@ -403,8 +403,8 @@ end # \Class for representing # {WebDAV method UNLOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_UNLOCK]: # -# require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# require 'rubygems/vendor/net-http/lib/net/http' +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Unlock.new(uri) # => #<Gem::Net::HTTP::Unlock UNLOCK> # res = Gem::Net::HTTP.start(hostname) do |http| diff --git a/lib/rubygems/net-http/lib/net/http/response.rb b/lib/rubygems/vendor/net-http/lib/net/http/response.rb index 28ee365978..cbbd191d87 100644 --- a/lib/rubygems/net-http/lib/net/http/response.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/response.rb @@ -216,8 +216,8 @@ class Gem::Net::HTTPResponse attr_reader :message alias msg message # :nodoc: obsolete - # The URI used to fetch this response. The response URI is only available - # if a URI was used to create the request. + # The Gem::URI used to fetch this response. The response Gem::URI is only available + # if a Gem::URI was used to create the request. attr_reader :uri # Set to true automatically when the request did not contain an diff --git a/lib/rubygems/net-http/lib/net/http/responses.rb b/lib/rubygems/vendor/net-http/lib/net/http/responses.rb index 95ce9dd46a..0f26ae6c26 100644 --- a/lib/rubygems/net-http/lib/net/http/responses.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/responses.rb @@ -379,7 +379,7 @@ module Gem::Net # Response class for <tt>See Other</tt> responses (status code 303). # - # The response to the request can be found under another URI using the GET method. + # The response to the request can be found under another Gem::URI using the GET method. # # :include: doc/net-http/included_getters.rdoc # @@ -428,8 +428,8 @@ module Gem::Net # Response class for <tt>Temporary Redirect</tt> responses (status code 307). # - # The request should be repeated with another URI; - # however, future requests should still use the original URI. + # The request should be repeated with another Gem::URI; + # however, future requests should still use the original Gem::URI. # # :include: doc/net-http/included_getters.rdoc # @@ -445,7 +445,7 @@ module Gem::Net # Response class for <tt>Permanent Redirect</tt> responses (status code 308). # - # This and all future requests should be directed to the given URI. + # This and all future requests should be directed to the given Gem::URI. # # :include: doc/net-http/included_getters.rdoc # @@ -690,9 +690,9 @@ module Gem::Net end HTTPRequestEntityTooLarge = HTTPPayloadTooLarge - # Response class for <tt>URI Too Long</tt> responses (status code 414). + # Response class for <tt>Gem::URI Too Long</tt> responses (status code 414). # - # The URI provided was too long for the server to process. + # The Gem::URI provided was too long for the server to process. # # :include: doc/net-http/included_getters.rdoc # diff --git a/lib/rubygems/net-http/lib/net/http/status.rb b/lib/rubygems/vendor/net-http/lib/net/http/status.rb index 10cbc8e3ee..9110b108b8 100644 --- a/lib/rubygems/net-http/lib/net/http/status.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http/status.rb @@ -11,7 +11,7 @@ if $0 == __FILE__ puts puts "Gem::Net::HTTP::STATUS_CODES = {" url = "https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv" - URI(url).read.each_line do |line| + Gem::URI(url).read.each_line do |line| code, mes, = line.split(',') next if ['(Unused)', 'Unassigned', 'Description'].include?(mes) puts " #{code} => '#{mes}'," diff --git a/lib/rubygems/net-http/lib/net/https.rb b/lib/rubygems/vendor/net-http/lib/net/https.rb index 401d64a87c..d2784f0be0 100644 --- a/lib/rubygems/net-http/lib/net/https.rb +++ b/lib/rubygems/vendor/net-http/lib/net/https.rb @@ -4,7 +4,7 @@ = net/https -- SSL/TLS enhancement for Gem::Net::HTTP. This file has been merged with net/http. There is no longer any need to - require 'rubygems/net-http/lib/net/https' to use HTTPS. + require 'rubygems/vendor/net-http/lib/net/https' to use HTTPS. See Gem::Net::HTTP for details on how to make HTTPS connections. diff --git a/lib/rubygems/optparse/.document b/lib/rubygems/vendor/net-protocol/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/optparse/.document +++ b/lib/rubygems/vendor/net-protocol/.document diff --git a/lib/rubygems/net-protocol/lib/net/protocol.rb b/lib/rubygems/vendor/net-protocol/lib/net/protocol.rb index 53d34d8d98..53d34d8d98 100644 --- a/lib/rubygems/net-protocol/lib/net/protocol.rb +++ b/lib/rubygems/vendor/net-protocol/lib/net/protocol.rb diff --git a/lib/rubygems/resolv/.document b/lib/rubygems/vendor/optparse/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/resolv/.document +++ b/lib/rubygems/vendor/optparse/.document diff --git a/lib/rubygems/optparse/lib/optionparser.rb b/lib/rubygems/vendor/optparse/lib/optionparser.rb index 4b9b40d82a..4b9b40d82a 100644 --- a/lib/rubygems/optparse/lib/optionparser.rb +++ b/lib/rubygems/vendor/optparse/lib/optionparser.rb diff --git a/lib/rubygems/optparse/lib/optparse.rb b/lib/rubygems/vendor/optparse/lib/optparse.rb index 8e700016b0..5937431720 100644 --- a/lib/rubygems/optparse/lib/optparse.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse.rb @@ -73,7 +73,7 @@ # # === Minimal example # -# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse' # # options = {} # Gem::OptionParser.new do |parser| @@ -92,7 +92,7 @@ # Gem::OptionParser can be used to automatically generate help for the commands you # write: # -# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse' # # Options = Struct.new(:name) # @@ -130,7 +130,7 @@ # option name in all caps. If an option is used without the required argument, # an exception will be raised. # -# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse' # # options = {} # Gem::OptionParser.new do |parser| @@ -158,7 +158,7 @@ # - Date -- Anything accepted by +Date.parse+ (need to require +optparse/date+) # - DateTime -- Anything accepted by +DateTime.parse+ (need to require +optparse/date+) # - Time -- Anything accepted by +Time.httpdate+ or +Time.parse+ (need to require +optparse/time+) -# - URI -- Anything accepted by +URI.parse+ (need to require +optparse/uri+) +# - URI -- Anything accepted by +Gem::URI.parse+ (need to require +optparse/uri+) # - Shellwords -- Anything accepted by +Shellwords.shellwords+ (need to require +optparse/shellwords+) # - String -- Any non-empty string # - Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040) @@ -183,8 +183,8 @@ # as a +Time+. If it succeeds, that time will be passed to the # handler block. Otherwise, an exception will be raised. # -# require 'rubygems/optparse/lib/optparse' -# require 'rubygems/optparse/lib/optparse/time' +# require 'rubygems/vendor/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse/time' # Gem::OptionParser.new do |parser| # parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| # p time @@ -206,7 +206,7 @@ # It specifies which conversion block to call whenever a class is specified. # The example below uses it to fetch a +User+ object before the +on+ handler receives it. # -# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse' # # User = Struct.new(:id, :name) # @@ -242,7 +242,7 @@ # # The +into+ option of +order+, +parse+ and so on methods stores command line options into a Hash. # -# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse' # # options = {} # Gem::OptionParser.new do |parser| @@ -268,8 +268,8 @@ # effect of specifying various options. This is probably the best way to learn # the features of +optparse+. # -# require 'rubygems/optparse/lib/optparse' -# require 'rubygems/optparse/lib/optparse/time' +# require 'rubygems/vendor/optparse/lib/optparse' +# require 'rubygems/vendor/optparse/lib/optparse/time' # require 'ostruct' # require 'pp' # @@ -1084,7 +1084,7 @@ XXX Switch::OptionalArgument.new do |pkg| if pkg begin - require 'rubygems/optparse/lib/optparse/version' + require 'rubygems/vendor/optparse/lib/optparse/version' rescue LoadError else show_version(*pkg.split(/,/)) or diff --git a/lib/rubygems/optparse/lib/optparse/ac.rb b/lib/rubygems/vendor/optparse/lib/optparse/ac.rb index e84d01bf91..e84d01bf91 100644 --- a/lib/rubygems/optparse/lib/optparse/ac.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/ac.rb diff --git a/lib/rubygems/optparse/lib/optparse/date.rb b/lib/rubygems/vendor/optparse/lib/optparse/date.rb index d9a9f4f48a..d9a9f4f48a 100644 --- a/lib/rubygems/optparse/lib/optparse/date.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/date.rb diff --git a/lib/rubygems/optparse/lib/optparse/kwargs.rb b/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb index 6987a5ed62..6987a5ed62 100644 --- a/lib/rubygems/optparse/lib/optparse/kwargs.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb diff --git a/lib/rubygems/optparse/lib/optparse/shellwords.rb b/lib/rubygems/vendor/optparse/lib/optparse/shellwords.rb index d47ad60255..d47ad60255 100644 --- a/lib/rubygems/optparse/lib/optparse/shellwords.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/shellwords.rb diff --git a/lib/rubygems/optparse/lib/optparse/time.rb b/lib/rubygems/vendor/optparse/lib/optparse/time.rb index c59e1e4ced..c59e1e4ced 100644 --- a/lib/rubygems/optparse/lib/optparse/time.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/time.rb diff --git a/lib/rubygems/vendor/optparse/lib/optparse/uri.rb b/lib/rubygems/vendor/optparse/lib/optparse/uri.rb new file mode 100644 index 0000000000..398127479a --- /dev/null +++ b/lib/rubygems/vendor/optparse/lib/optparse/uri.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: false +# -*- ruby -*- + +require_relative '../optparse' +require_relative '../../../uri/lib/uri' + +Gem::OptionParser.accept(Gem::URI) {|s,| Gem::URI.parse(s) if s} diff --git a/lib/rubygems/optparse/lib/optparse/version.rb b/lib/rubygems/vendor/optparse/lib/optparse/version.rb index 5d79e9db44..5d79e9db44 100644 --- a/lib/rubygems/optparse/lib/optparse/version.rb +++ b/lib/rubygems/vendor/optparse/lib/optparse/version.rb diff --git a/lib/rubygems/resolver/molinillo/.document b/lib/rubygems/vendor/resolv/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/resolver/molinillo/.document +++ b/lib/rubygems/vendor/resolv/.document diff --git a/lib/rubygems/resolv/lib/resolv.rb b/lib/rubygems/vendor/resolv/lib/resolv.rb index 1209d5167a..1209d5167a 100644 --- a/lib/rubygems/resolv/lib/resolv.rb +++ b/lib/rubygems/vendor/resolv/lib/resolv.rb diff --git a/lib/rubygems/timeout/.document b/lib/rubygems/vendor/timeout/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/timeout/.document +++ b/lib/rubygems/vendor/timeout/.document diff --git a/lib/rubygems/timeout/lib/timeout.rb b/lib/rubygems/vendor/timeout/lib/timeout.rb index 24d877b994..df97d64ca0 100644 --- a/lib/rubygems/timeout/lib/timeout.rb +++ b/lib/rubygems/vendor/timeout/lib/timeout.rb @@ -3,7 +3,7 @@ # # == Synopsis # -# require 'rubygems/timeout/lib/timeout' +# require 'rubygems/vendor/timeout/lib/timeout' # status = Gem::Timeout::timeout(5) { # # Something that should be interrupted if it takes more than 5 seconds... # } diff --git a/lib/rubygems/tsort/.document b/lib/rubygems/vendor/tsort/.document index 0c43bbd6b3..0c43bbd6b3 100644 --- a/lib/rubygems/tsort/.document +++ b/lib/rubygems/vendor/tsort/.document diff --git a/lib/rubygems/tsort/lib/tsort.rb b/lib/rubygems/vendor/tsort/lib/tsort.rb index 05f3683d38..9dd7c09521 100644 --- a/lib/rubygems/tsort/lib/tsort.rb +++ b/lib/rubygems/vendor/tsort/lib/tsort.rb @@ -32,7 +32,7 @@ # method, which fetches the array of child nodes and then iterates over that # array using the user-supplied block. # -# require 'rubygems/tsort/lib/tsort' +# require 'rubygems/vendor/tsort/lib/tsort' # # class Hash # include Gem::TSort @@ -52,7 +52,7 @@ # # A very simple `make' like tool can be implemented as follows: # -# require 'rubygems/tsort/lib/tsort' +# require 'rubygems/vendor/tsort/lib/tsort' # # class Make # def initialize diff --git a/lib/rubygems/vendor/uri/.document b/lib/rubygems/vendor/uri/.document new file mode 100644 index 0000000000..0c43bbd6b3 --- /dev/null +++ b/lib/rubygems/vendor/uri/.document @@ -0,0 +1 @@ +# Vendored files do not need to be documented diff --git a/lib/rubygems/vendor/uri/lib/uri.rb b/lib/rubygems/vendor/uri/lib/uri.rb new file mode 100644 index 0000000000..f1ccc167cc --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: false +# Gem::URI is a module providing classes to handle Uniform Resource Identifiers +# (RFC2396[http://tools.ietf.org/html/rfc2396]). +# +# == Features +# +# * Uniform way of handling URIs. +# * Flexibility to introduce custom Gem::URI schemes. +# * Flexibility to have an alternate Gem::URI::Parser (or just different patterns +# and regexp's). +# +# == Basic example +# +# require 'rubygems/vendor/uri/lib/uri' +# +# uri = Gem::URI("http://foo.com/posts?id=30&limit=5#time=1305298413") +# #=> #<Gem::URI::HTTP http://foo.com/posts?id=30&limit=5#time=1305298413> +# +# uri.scheme #=> "http" +# uri.host #=> "foo.com" +# uri.path #=> "/posts" +# uri.query #=> "id=30&limit=5" +# uri.fragment #=> "time=1305298413" +# +# uri.to_s #=> "http://foo.com/posts?id=30&limit=5#time=1305298413" +# +# == Adding custom URIs +# +# module Gem::URI +# class RSYNC < Generic +# DEFAULT_PORT = 873 +# end +# register_scheme 'RSYNC', RSYNC +# end +# #=> Gem::URI::RSYNC +# +# Gem::URI.scheme_list +# #=> {"FILE"=>Gem::URI::File, "FTP"=>Gem::URI::FTP, "HTTP"=>Gem::URI::HTTP, +# # "HTTPS"=>Gem::URI::HTTPS, "LDAP"=>Gem::URI::LDAP, "LDAPS"=>Gem::URI::LDAPS, +# # "MAILTO"=>Gem::URI::MailTo, "RSYNC"=>Gem::URI::RSYNC} +# +# uri = Gem::URI("rsync://rsync.foo.com") +# #=> #<Gem::URI::RSYNC rsync://rsync.foo.com> +# +# == RFC References +# +# A good place to view an RFC spec is http://www.ietf.org/rfc.html. +# +# Here is a list of all related RFC's: +# - RFC822[http://tools.ietf.org/html/rfc822] +# - RFC1738[http://tools.ietf.org/html/rfc1738] +# - RFC2255[http://tools.ietf.org/html/rfc2255] +# - RFC2368[http://tools.ietf.org/html/rfc2368] +# - RFC2373[http://tools.ietf.org/html/rfc2373] +# - RFC2396[http://tools.ietf.org/html/rfc2396] +# - RFC2732[http://tools.ietf.org/html/rfc2732] +# - RFC3986[http://tools.ietf.org/html/rfc3986] +# +# == Class tree +# +# - Gem::URI::Generic (in uri/generic.rb) +# - Gem::URI::File - (in uri/file.rb) +# - Gem::URI::FTP - (in uri/ftp.rb) +# - Gem::URI::HTTP - (in uri/http.rb) +# - Gem::URI::HTTPS - (in uri/https.rb) +# - Gem::URI::LDAP - (in uri/ldap.rb) +# - Gem::URI::LDAPS - (in uri/ldaps.rb) +# - Gem::URI::MailTo - (in uri/mailto.rb) +# - Gem::URI::Parser - (in uri/common.rb) +# - Gem::URI::REGEXP - (in uri/common.rb) +# - Gem::URI::REGEXP::PATTERN - (in uri/common.rb) +# - Gem::URI::Util - (in uri/common.rb) +# - Gem::URI::Error - (in uri/common.rb) +# - Gem::URI::InvalidURIError - (in uri/common.rb) +# - Gem::URI::InvalidComponentError - (in uri/common.rb) +# - Gem::URI::BadURIError - (in uri/common.rb) +# +# == Copyright Info +# +# Author:: Akira Yamada <[email protected]> +# Documentation:: +# Akira Yamada <[email protected]> +# Dmitry V. Sabanin <[email protected]> +# Vincent Batts <[email protected]> +# License:: +# Copyright (c) 2001 akira yamada <[email protected]> +# You can redistribute it and/or modify it under the same term as Ruby. +# + +module Gem::URI +end + +require_relative 'uri/version' +require_relative 'uri/common' +require_relative 'uri/generic' +require_relative 'uri/file' +require_relative 'uri/ftp' +require_relative 'uri/http' +require_relative 'uri/https' +require_relative 'uri/ldap' +require_relative 'uri/ldaps' +require_relative 'uri/mailto' +require_relative 'uri/ws' +require_relative 'uri/wss' diff --git a/lib/rubygems/vendor/uri/lib/uri/common.rb b/lib/rubygems/vendor/uri/lib/uri/common.rb new file mode 100644 index 0000000000..921fb9dd28 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/common.rb @@ -0,0 +1,853 @@ +# frozen_string_literal: true +#-- +# = uri/common.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative "rfc2396_parser" +require_relative "rfc3986_parser" + +module Gem::URI + include RFC2396_REGEXP + + REGEXP = RFC2396_REGEXP + Parser = RFC2396_Parser + RFC3986_PARSER = RFC3986_Parser.new + Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor) + + # Gem::URI::Parser.new + DEFAULT_PARSER = Parser.new + DEFAULT_PARSER.pattern.each_pair do |sym, str| + unless REGEXP::PATTERN.const_defined?(sym) + REGEXP::PATTERN.const_set(sym, str) + end + end + DEFAULT_PARSER.regexp.each_pair do |sym, str| + const_set(sym, str) + end + Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor) + + module Util # :nodoc: + def make_components_hash(klass, array_hash) + tmp = {} + if array_hash.kind_of?(Array) && + array_hash.size == klass.component.size - 1 + klass.component[1..-1].each_index do |i| + begin + tmp[klass.component[i + 1]] = array_hash[i].clone + rescue TypeError + tmp[klass.component[i + 1]] = array_hash[i] + end + end + + elsif array_hash.kind_of?(Hash) + array_hash.each do |key, value| + begin + tmp[key] = value.clone + rescue TypeError + tmp[key] = value + end + end + else + raise ArgumentError, + "expected Array of or Hash of components of #{klass} (#{klass.component[1..-1].join(', ')})" + end + tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase + + return tmp + end + module_function :make_components_hash + end + + module Schemes + end + private_constant :Schemes + + # Registers the given +klass+ as the class to be instantiated + # when parsing a \Gem::URI with the given +scheme+: + # + # Gem::URI.register_scheme('MS_SEARCH', Gem::URI::Generic) # => Gem::URI::Generic + # Gem::URI.scheme_list['MS_SEARCH'] # => Gem::URI::Generic + # + # Note that after calling String#upcase on +scheme+, it must be a valid + # constant name. + def self.register_scheme(scheme, klass) + Schemes.const_set(scheme.to_s.upcase, klass) + end + + # Returns a hash of the defined schemes: + # + # Gem::URI.scheme_list + # # => + # {"MAILTO"=>Gem::URI::MailTo, + # "LDAPS"=>Gem::URI::LDAPS, + # "WS"=>Gem::URI::WS, + # "HTTP"=>Gem::URI::HTTP, + # "HTTPS"=>Gem::URI::HTTPS, + # "LDAP"=>Gem::URI::LDAP, + # "FILE"=>Gem::URI::File, + # "FTP"=>Gem::URI::FTP} + # + # Related: Gem::URI.register_scheme. + def self.scheme_list + Schemes.constants.map { |name| + [name.to_s.upcase, Schemes.const_get(name)] + }.to_h + end + + INITIAL_SCHEMES = scheme_list + private_constant :INITIAL_SCHEMES + Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor) + + # Returns a new object constructed from the given +scheme+, +arguments+, + # and +default+: + # + # - The new object is an instance of <tt>Gem::URI.scheme_list[scheme.upcase]</tt>. + # - The object is initialized by calling the class initializer + # using +scheme+ and +arguments+. + # See Gem::URI::Generic.new. + # + # Examples: + # + # values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top'] + # Gem::URI.for('https', *values) + # # => #<Gem::URI::HTTPS https://[email protected]:123/forum/questions/?tag=networking&order=newest#top> + # Gem::URI.for('foo', *values, default: Gem::URI::HTTP) + # # => #<Gem::URI::HTTP foo://[email protected]:123/forum/questions/?tag=networking&order=newest#top> + # + def self.for(scheme, *arguments, default: Generic) + const_name = scheme.to_s.upcase + + uri_class = INITIAL_SCHEMES[const_name] + uri_class ||= if /\A[A-Z]\w*\z/.match?(const_name) && Schemes.const_defined?(const_name, false) + Schemes.const_get(const_name, false) + end + uri_class ||= default + + return uri_class.new(scheme, *arguments) + end + + # + # Base class for all Gem::URI exceptions. + # + class Error < StandardError; end + # + # Not a Gem::URI. + # + class InvalidURIError < Error; end + # + # Not a Gem::URI component. + # + class InvalidComponentError < Error; end + # + # Gem::URI is valid, bad usage is not. + # + class BadURIError < Error; end + + # Returns a 9-element array representing the parts of the \Gem::URI + # formed from the string +uri+; + # each array element is a string or +nil+: + # + # names = %w[scheme userinfo host port registry path opaque query fragment] + # values = Gem::URI.split('https://[email protected]:123/forum/questions/?tag=networking&order=newest#top') + # names.zip(values) + # # => + # [["scheme", "https"], + # ["userinfo", "john.doe"], + # ["host", "www.example.com"], + # ["port", "123"], + # ["registry", nil], + # ["path", "/forum/questions/"], + # ["opaque", nil], + # ["query", "tag=networking&order=newest"], + # ["fragment", "top"]] + # + def self.split(uri) + RFC3986_PARSER.split(uri) + end + + # Returns a new \Gem::URI object constructed from the given string +uri+: + # + # Gem::URI.parse('https://[email protected]:123/forum/questions/?tag=networking&order=newest#top') + # # => #<Gem::URI::HTTPS https://[email protected]:123/forum/questions/?tag=networking&order=newest#top> + # Gem::URI.parse('http://[email protected]:123/forum/questions/?tag=networking&order=newest#top') + # # => #<Gem::URI::HTTP http://[email protected]:123/forum/questions/?tag=networking&order=newest#top> + # + # It's recommended to first ::escape string +uri+ + # if it may contain invalid Gem::URI characters. + # + def self.parse(uri) + RFC3986_PARSER.parse(uri) + end + + # Merges the given Gem::URI strings +str+ + # per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html]. + # + # Each string in +str+ is converted to an + # {RFC3986 Gem::URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged. + # + # Examples: + # + # Gem::URI.join("http://example.com/","main.rbx") + # # => #<Gem::URI::HTTP http://example.com/main.rbx> + # + # Gem::URI.join('http://example.com', 'foo') + # # => #<Gem::URI::HTTP http://example.com/foo> + # + # Gem::URI.join('http://example.com', '/foo', '/bar') + # # => #<Gem::URI::HTTP http://example.com/bar> + # + # Gem::URI.join('http://example.com', '/foo', 'bar') + # # => #<Gem::URI::HTTP http://example.com/bar> + # + # Gem::URI.join('http://example.com', '/foo/', 'bar') + # # => #<Gem::URI::HTTP http://example.com/foo/bar> + # + def self.join(*str) + RFC3986_PARSER.join(*str) + end + + # + # == Synopsis + # + # Gem::URI::extract(str[, schemes][,&blk]) + # + # == Args + # + # +str+:: + # String to extract URIs from. + # +schemes+:: + # Limit Gem::URI matching to specific schemes. + # + # == Description + # + # Extracts URIs from a string. If block given, iterates through all matched URIs. + # Returns nil if block given or array with matches. + # + # == Usage + # + # require "rubygems/vendor/uri/lib/uri" + # + # Gem::URI.extract("text here http://foo.example.org/bla and here mailto:[email protected] and here also.") + # # => ["http://foo.example.com/bla", "mailto:[email protected]"] + # + def self.extract(str, schemes = nil, &block) # :nodoc: + warn "Gem::URI.extract is obsolete", uplevel: 1 if $VERBOSE + DEFAULT_PARSER.extract(str, schemes, &block) + end + + # + # == Synopsis + # + # Gem::URI::regexp([match_schemes]) + # + # == Args + # + # +match_schemes+:: + # Array of schemes. If given, resulting regexp matches to URIs + # whose scheme is one of the match_schemes. + # + # == Description + # + # Returns a Regexp object which matches to Gem::URI-like strings. + # The Regexp object returned by this method includes arbitrary + # number of capture group (parentheses). Never rely on its number. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # # extract first Gem::URI from html_string + # html_string.slice(Gem::URI.regexp) + # + # # remove ftp URIs + # html_string.sub(Gem::URI.regexp(['ftp']), '') + # + # # You should not rely on the number of parentheses + # html_string.scan(Gem::URI.regexp) do |*matches| + # p $& + # end + # + def self.regexp(schemes = nil)# :nodoc: + warn "Gem::URI.regexp is obsolete", uplevel: 1 if $VERBOSE + DEFAULT_PARSER.make_regexp(schemes) + end + + TBLENCWWWCOMP_ = {} # :nodoc: + 256.times do |i| + TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i) + end + TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze + TBLENCWWWCOMP_[' '] = '+' + TBLENCWWWCOMP_.freeze + TBLDECWWWCOMP_ = {} # :nodoc: + 256.times do |i| + h, l = i>>4, i&15 + TBLDECWWWCOMP_[-('%%%X%X' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%x%X' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%X%x' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%x%x' % [h, l])] = -i.chr + end + TBLDECWWWCOMP_['+'] = ' ' + TBLDECWWWCOMP_.freeze + + # Returns a URL-encoded string derived from the given string +str+. + # + # The returned string: + # + # - Preserves: + # + # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>. + # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>, + # and <tt>'0'..'9'</tt>. + # + # Example: + # + # Gem::URI.encode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # - Converts: + # + # - Character <tt>' '</tt> to character <tt>'+'</tt>. + # - Any other character to "percent notation"; + # the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>. + # + # Example: + # + # Gem::URI.encode_www_form_component('Here are some punctuation characters: ,;?:') + # # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A" + # + # Encoding: + # + # - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored. + # - Otherwise +str+ is converted first to Encoding::UTF_8 + # (with suitable character replacements), + # and then to encoding +enc+. + # + # In either case, the returned string has forced encoding Encoding::US_ASCII. + # + # Related: Gem::URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>). + def self.encode_www_form_component(str, enc=nil) + _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc) + end + + # Returns a string decoded from the given \URL-encoded string +str+. + # + # The given string is first encoded as Encoding::ASCII-8BIT (using String#b), + # then decoded (as below), and finally force-encoded to the given encoding +enc+. + # + # The returned string: + # + # - Preserves: + # + # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>. + # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>, + # and <tt>'0'..'9'</tt>. + # + # Example: + # + # Gem::URI.decode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # - Converts: + # + # - Character <tt>'+'</tt> to character <tt>' '</tt>. + # - Each "percent notation" to an ASCII character. + # + # Example: + # + # Gem::URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A') + # # => "Here are some punctuation characters: ,;?:" + # + # Related: Gem::URI.decode_uri_component (preserves <tt>'+'</tt>). + def self.decode_www_form_component(str, enc=Encoding::UTF_8) + _decode_uri_component(/\+|%\h\h/, str, enc) + end + + # Like Gem::URI.encode_www_form_component, except that <tt>' '</tt> (space) + # is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>). + def self.encode_uri_component(str, enc=nil) + _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc) + end + + # Like Gem::URI.decode_www_form_component, except that <tt>'+'</tt> is preserved. + def self.decode_uri_component(str, enc=Encoding::UTF_8) + _decode_uri_component(/%\h\h/, str, enc) + end + + def self._encode_uri_component(regexp, table, str, enc) + str = str.to_s.dup + if str.encoding != Encoding::ASCII_8BIT + if enc && enc != Encoding::ASCII_8BIT + str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) + str.encode!(enc, fallback: ->(x){"&##{x.ord};"}) + end + str.force_encoding(Encoding::ASCII_8BIT) + end + str.gsub!(regexp, table) + str.force_encoding(Encoding::US_ASCII) + end + private_class_method :_encode_uri_component + + def self._decode_uri_component(regexp, str, enc) + raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str) + str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc) + end + private_class_method :_decode_uri_component + + # Returns a URL-encoded string derived from the given + # {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes] + # +enum+. + # + # The result is suitable for use as form data + # for an \HTTP request whose <tt>Content-Type</tt> is + # <tt>'application/x-www-form-urlencoded'</tt>. + # + # The returned string consists of the elements of +enum+, + # each converted to one or more URL-encoded strings, + # and all joined with character <tt>'&'</tt>. + # + # Simple examples: + # + # Gem::URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]]) + # # => "foo=0&bar=1&baz=2" + # Gem::URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # The returned string is formed using method Gem::URI.encode_www_form_component, + # which converts certain characters: + # + # Gem::URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@') + # # => "f%23o=%2F&b-r=%24&b+z=%40" + # + # When +enum+ is Array-like, each element +ele+ is converted to a field: + # + # - If +ele+ is an array of two or more elements, + # the field is formed from its first two elements + # (and any additional elements are ignored): + # + # name = Gem::URI.encode_www_form_component(ele[0], enc) + # value = Gem::URI.encode_www_form_component(ele[1], enc) + # "#{name}=#{value}" + # + # Examples: + # + # Gem::URI.encode_www_form([%w[foo bar], %w[baz bat bah]]) + # # => "foo=bar&baz=bat" + # Gem::URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']]) + # # => "foo=0&bar=baz" + # + # - If +ele+ is an array of one element, + # the field is formed from <tt>ele[0]</tt>: + # + # Gem::URI.encode_www_form_component(ele[0]) + # + # Example: + # + # Gem::URI.encode_www_form([['foo'], [:bar], [0]]) + # # => "foo&bar&0" + # + # - Otherwise the field is formed from +ele+: + # + # Gem::URI.encode_www_form_component(ele) + # + # Example: + # + # Gem::URI.encode_www_form(['foo', :bar, 0]) + # # => "foo&bar&0" + # + # The elements of an Array-like +enum+ may be mixture: + # + # Gem::URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat]) + # # => "foo=0&bar=1&baz&bat" + # + # When +enum+ is Hash-like, + # each +key+/+value+ pair is converted to one or more fields: + # + # - If +value+ is + # {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects], + # each element +ele+ in +value+ is paired with +key+ to form a field: + # + # name = Gem::URI.encode_www_form_component(key, enc) + # value = Gem::URI.encode_www_form_component(ele, enc) + # "#{name}=#{value}" + # + # Example: + # + # Gem::URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]}) + # # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2" + # + # - Otherwise, +key+ and +value+ are paired to form a field: + # + # name = Gem::URI.encode_www_form_component(key, enc) + # value = Gem::URI.encode_www_form_component(value, enc) + # "#{name}=#{value}" + # + # Example: + # + # Gem::URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # The elements of a Hash-like +enum+ may be mixture: + # + # Gem::URI.encode_www_form({foo: [0, 1], bar: 2}) + # # => "foo=0&foo=1&bar=2" + # + def self.encode_www_form(enum, enc=nil) + enum.map do |k,v| + if v.nil? + encode_www_form_component(k, enc) + elsif v.respond_to?(:to_ary) + v.to_ary.map do |w| + str = encode_www_form_component(k, enc) + unless w.nil? + str << '=' + str << encode_www_form_component(w, enc) + end + end.join('&') + else + str = encode_www_form_component(k, enc) + str << '=' + str << encode_www_form_component(v, enc) + end + end.join('&') + end + + # Returns name/value pairs derived from the given string +str+, + # which must be an ASCII string. + # + # The method may be used to decode the body of Net::HTTPResponse object +res+ + # for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>. + # + # The returned data is an array of 2-element subarrays; + # each subarray is a name/value pair (both are strings). + # Each returned string has encoding +enc+, + # and has had invalid characters removed via + # {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub]. + # + # A simple example: + # + # Gem::URI.decode_www_form('foo=0&bar=1&baz') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] + # + # The returned strings have certain conversions, + # similar to those performed in Gem::URI.decode_www_form_component: + # + # Gem::URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40') + # # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]] + # + # The given string may contain consecutive separators: + # + # Gem::URI.decode_www_form('foo=0&&bar=1&&baz=2') + # # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]] + # + # A different separator may be specified: + # + # Gem::URI.decode_www_form('foo=0--bar=1--baz', separator: '--') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] + # + def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false) + raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only? + ary = [] + return ary if str.empty? + enc = Encoding.find(enc) + str.b.each_line(separator) do |string| + string.chomp!(separator) + key, sep, val = string.partition('=') + if isindex + if sep.empty? + val = key + key = +'' + end + isindex = false + end + + if use__charset_ and key == '_charset_' and e = get_encoding(val) + enc = e + use__charset_ = false + end + + key.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) + if val + val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) + else + val = +'' + end + + ary << [key, val] + end + ary.each do |k, v| + k.force_encoding(enc) + k.scrub! + v.force_encoding(enc) + v.scrub! + end + ary + end + + private +=begin command for WEB_ENCODINGS_ + curl https://encoding.spec.whatwg.org/encodings.json| + ruby -rjson -e 'H={} + h={ + "shift_jis"=>"Windows-31J", + "euc-jp"=>"cp51932", + "iso-2022-jp"=>"cp50221", + "x-mac-cyrillic"=>"macCyrillic", + } + JSON($<.read).map{|x|x["encodings"]}.flatten.each{|x| + Encoding.find(n=h.fetch(n=x["name"].downcase,n))rescue next + x["labels"].each{|y|H[y]=n} + } + puts "{" + H.each{|k,v|puts %[ #{k.dump}=>#{v.dump},]} + puts "}" +' +=end + WEB_ENCODINGS_ = { + "unicode-1-1-utf-8"=>"utf-8", + "utf-8"=>"utf-8", + "utf8"=>"utf-8", + "866"=>"ibm866", + "cp866"=>"ibm866", + "csibm866"=>"ibm866", + "ibm866"=>"ibm866", + "csisolatin2"=>"iso-8859-2", + "iso-8859-2"=>"iso-8859-2", + "iso-ir-101"=>"iso-8859-2", + "iso8859-2"=>"iso-8859-2", + "iso88592"=>"iso-8859-2", + "iso_8859-2"=>"iso-8859-2", + "iso_8859-2:1987"=>"iso-8859-2", + "l2"=>"iso-8859-2", + "latin2"=>"iso-8859-2", + "csisolatin3"=>"iso-8859-3", + "iso-8859-3"=>"iso-8859-3", + "iso-ir-109"=>"iso-8859-3", + "iso8859-3"=>"iso-8859-3", + "iso88593"=>"iso-8859-3", + "iso_8859-3"=>"iso-8859-3", + "iso_8859-3:1988"=>"iso-8859-3", + "l3"=>"iso-8859-3", + "latin3"=>"iso-8859-3", + "csisolatin4"=>"iso-8859-4", + "iso-8859-4"=>"iso-8859-4", + "iso-ir-110"=>"iso-8859-4", + "iso8859-4"=>"iso-8859-4", + "iso88594"=>"iso-8859-4", + "iso_8859-4"=>"iso-8859-4", + "iso_8859-4:1988"=>"iso-8859-4", + "l4"=>"iso-8859-4", + "latin4"=>"iso-8859-4", + "csisolatincyrillic"=>"iso-8859-5", + "cyrillic"=>"iso-8859-5", + "iso-8859-5"=>"iso-8859-5", + "iso-ir-144"=>"iso-8859-5", + "iso8859-5"=>"iso-8859-5", + "iso88595"=>"iso-8859-5", + "iso_8859-5"=>"iso-8859-5", + "iso_8859-5:1988"=>"iso-8859-5", + "arabic"=>"iso-8859-6", + "asmo-708"=>"iso-8859-6", + "csiso88596e"=>"iso-8859-6", + "csiso88596i"=>"iso-8859-6", + "csisolatinarabic"=>"iso-8859-6", + "ecma-114"=>"iso-8859-6", + "iso-8859-6"=>"iso-8859-6", + "iso-8859-6-e"=>"iso-8859-6", + "iso-8859-6-i"=>"iso-8859-6", + "iso-ir-127"=>"iso-8859-6", + "iso8859-6"=>"iso-8859-6", + "iso88596"=>"iso-8859-6", + "iso_8859-6"=>"iso-8859-6", + "iso_8859-6:1987"=>"iso-8859-6", + "csisolatingreek"=>"iso-8859-7", + "ecma-118"=>"iso-8859-7", + "elot_928"=>"iso-8859-7", + "greek"=>"iso-8859-7", + "greek8"=>"iso-8859-7", + "iso-8859-7"=>"iso-8859-7", + "iso-ir-126"=>"iso-8859-7", + "iso8859-7"=>"iso-8859-7", + "iso88597"=>"iso-8859-7", + "iso_8859-7"=>"iso-8859-7", + "iso_8859-7:1987"=>"iso-8859-7", + "sun_eu_greek"=>"iso-8859-7", + "csiso88598e"=>"iso-8859-8", + "csisolatinhebrew"=>"iso-8859-8", + "hebrew"=>"iso-8859-8", + "iso-8859-8"=>"iso-8859-8", + "iso-8859-8-e"=>"iso-8859-8", + "iso-ir-138"=>"iso-8859-8", + "iso8859-8"=>"iso-8859-8", + "iso88598"=>"iso-8859-8", + "iso_8859-8"=>"iso-8859-8", + "iso_8859-8:1988"=>"iso-8859-8", + "visual"=>"iso-8859-8", + "csisolatin6"=>"iso-8859-10", + "iso-8859-10"=>"iso-8859-10", + "iso-ir-157"=>"iso-8859-10", + "iso8859-10"=>"iso-8859-10", + "iso885910"=>"iso-8859-10", + "l6"=>"iso-8859-10", + "latin6"=>"iso-8859-10", + "iso-8859-13"=>"iso-8859-13", + "iso8859-13"=>"iso-8859-13", + "iso885913"=>"iso-8859-13", + "iso-8859-14"=>"iso-8859-14", + "iso8859-14"=>"iso-8859-14", + "iso885914"=>"iso-8859-14", + "csisolatin9"=>"iso-8859-15", + "iso-8859-15"=>"iso-8859-15", + "iso8859-15"=>"iso-8859-15", + "iso885915"=>"iso-8859-15", + "iso_8859-15"=>"iso-8859-15", + "l9"=>"iso-8859-15", + "iso-8859-16"=>"iso-8859-16", + "cskoi8r"=>"koi8-r", + "koi"=>"koi8-r", + "koi8"=>"koi8-r", + "koi8-r"=>"koi8-r", + "koi8_r"=>"koi8-r", + "koi8-ru"=>"koi8-u", + "koi8-u"=>"koi8-u", + "dos-874"=>"windows-874", + "iso-8859-11"=>"windows-874", + "iso8859-11"=>"windows-874", + "iso885911"=>"windows-874", + "tis-620"=>"windows-874", + "windows-874"=>"windows-874", + "cp1250"=>"windows-1250", + "windows-1250"=>"windows-1250", + "x-cp1250"=>"windows-1250", + "cp1251"=>"windows-1251", + "windows-1251"=>"windows-1251", + "x-cp1251"=>"windows-1251", + "ansi_x3.4-1968"=>"windows-1252", + "ascii"=>"windows-1252", + "cp1252"=>"windows-1252", + "cp819"=>"windows-1252", + "csisolatin1"=>"windows-1252", + "ibm819"=>"windows-1252", + "iso-8859-1"=>"windows-1252", + "iso-ir-100"=>"windows-1252", + "iso8859-1"=>"windows-1252", + "iso88591"=>"windows-1252", + "iso_8859-1"=>"windows-1252", + "iso_8859-1:1987"=>"windows-1252", + "l1"=>"windows-1252", + "latin1"=>"windows-1252", + "us-ascii"=>"windows-1252", + "windows-1252"=>"windows-1252", + "x-cp1252"=>"windows-1252", + "cp1253"=>"windows-1253", + "windows-1253"=>"windows-1253", + "x-cp1253"=>"windows-1253", + "cp1254"=>"windows-1254", + "csisolatin5"=>"windows-1254", + "iso-8859-9"=>"windows-1254", + "iso-ir-148"=>"windows-1254", + "iso8859-9"=>"windows-1254", + "iso88599"=>"windows-1254", + "iso_8859-9"=>"windows-1254", + "iso_8859-9:1989"=>"windows-1254", + "l5"=>"windows-1254", + "latin5"=>"windows-1254", + "windows-1254"=>"windows-1254", + "x-cp1254"=>"windows-1254", + "cp1255"=>"windows-1255", + "windows-1255"=>"windows-1255", + "x-cp1255"=>"windows-1255", + "cp1256"=>"windows-1256", + "windows-1256"=>"windows-1256", + "x-cp1256"=>"windows-1256", + "cp1257"=>"windows-1257", + "windows-1257"=>"windows-1257", + "x-cp1257"=>"windows-1257", + "cp1258"=>"windows-1258", + "windows-1258"=>"windows-1258", + "x-cp1258"=>"windows-1258", + "x-mac-cyrillic"=>"macCyrillic", + "x-mac-ukrainian"=>"macCyrillic", + "chinese"=>"gbk", + "csgb2312"=>"gbk", + "csiso58gb231280"=>"gbk", + "gb2312"=>"gbk", + "gb_2312"=>"gbk", + "gb_2312-80"=>"gbk", + "gbk"=>"gbk", + "iso-ir-58"=>"gbk", + "x-gbk"=>"gbk", + "gb18030"=>"gb18030", + "big5"=>"big5", + "big5-hkscs"=>"big5", + "cn-big5"=>"big5", + "csbig5"=>"big5", + "x-x-big5"=>"big5", + "cseucpkdfmtjapanese"=>"cp51932", + "euc-jp"=>"cp51932", + "x-euc-jp"=>"cp51932", + "csiso2022jp"=>"cp50221", + "iso-2022-jp"=>"cp50221", + "csshiftjis"=>"Windows-31J", + "ms932"=>"Windows-31J", + "ms_kanji"=>"Windows-31J", + "shift-jis"=>"Windows-31J", + "shift_jis"=>"Windows-31J", + "sjis"=>"Windows-31J", + "windows-31j"=>"Windows-31J", + "x-sjis"=>"Windows-31J", + "cseuckr"=>"euc-kr", + "csksc56011987"=>"euc-kr", + "euc-kr"=>"euc-kr", + "iso-ir-149"=>"euc-kr", + "korean"=>"euc-kr", + "ks_c_5601-1987"=>"euc-kr", + "ks_c_5601-1989"=>"euc-kr", + "ksc5601"=>"euc-kr", + "ksc_5601"=>"euc-kr", + "windows-949"=>"euc-kr", + "utf-16be"=>"utf-16be", + "utf-16"=>"utf-16le", + "utf-16le"=>"utf-16le", + } # :nodoc: + Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor) + + # :nodoc: + # return encoding or nil + # http://encoding.spec.whatwg.org/#concept-encoding-get + def self.get_encoding(label) + Encoding.find(WEB_ENCODINGS_[label.to_str.strip.downcase]) rescue nil + end +end # module Gem::URI + +module Gem + + # + # Returns a \Gem::URI object derived from the given +uri+, + # which may be a \Gem::URI string or an existing \Gem::URI object: + # + # # Returns a new Gem::URI. + # uri = Gem::URI('http://github.com/ruby/ruby') + # # => #<Gem::URI::HTTP http://github.com/ruby/ruby> + # # Returns the given Gem::URI. + # Gem::URI(uri) + # # => #<Gem::URI::HTTP http://github.com/ruby/ruby> + # + def URI(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + Gem::URI.parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + module_function :URI +end diff --git a/lib/rubygems/vendor/uri/lib/uri/file.rb b/lib/rubygems/vendor/uri/lib/uri/file.rb new file mode 100644 index 0000000000..d419b26055 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/file.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require_relative 'generic' + +module Gem::URI + + # + # The "file" Gem::URI is defined by RFC8089. + # + class File < Generic + # A Default port of nil for Gem::URI::File. + DEFAULT_PORT = nil + + # + # An Array of the available components for Gem::URI::File. + # + COMPONENT = [ + :scheme, + :host, + :path + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::File object from components, with syntax checking. + # + # The components accepted are +host+ and +path+. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order <code>[host, path]</code>. + # + # A path from e.g. the File class should be escaped before + # being passed. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri1 = Gem::URI::File.build(['host.example.com', '/path/file.zip']) + # uri1.to_s # => "file://host.example.com/path/file.zip" + # + # uri2 = Gem::URI::File.build({:host => 'host.example.com', + # :path => '/ruby/src'}) + # uri2.to_s # => "file://host.example.com/ruby/src" + # + # uri3 = Gem::URI::File.build({:path => Gem::URI::escape('/path/my file.txt')}) + # uri3.to_s # => "file:///path/my%20file.txt" + # + def self.build(args) + tmp = Util::make_components_hash(self, args) + super(tmp) + end + + # Protected setter for the host component +v+. + # + # See also Gem::URI::Generic.host=. + # + def set_host(v) + v = "" if v.nil? || v == "localhost" + @host = v + end + + # do nothing + def set_port(v) + end + + # raise InvalidURIError + def check_userinfo(user) + raise Gem::URI::InvalidURIError, "can not set userinfo for file Gem::URI" + end + + # raise InvalidURIError + def check_user(user) + raise Gem::URI::InvalidURIError, "can not set user for file Gem::URI" + end + + # raise InvalidURIError + def check_password(user) + raise Gem::URI::InvalidURIError, "can not set password for file Gem::URI" + end + + # do nothing + def set_userinfo(v) + end + + # do nothing + def set_user(v) + end + + # do nothing + def set_password(v) + end + end + + register_scheme 'FILE', File +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ftp.rb b/lib/rubygems/vendor/uri/lib/uri/ftp.rb new file mode 100644 index 0000000000..100498ffb2 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ftp.rb @@ -0,0 +1,267 @@ +# frozen_string_literal: false +# = uri/ftp.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # FTP Gem::URI syntax is defined by RFC1738 section 3.2. + # + # This class will be redesigned because of difference of implementations; + # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it + # is a good summary about the de facto spec. + # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04 + # + class FTP < Generic + # A Default port of 21 for Gem::URI::FTP. + DEFAULT_PORT = 21 + + # + # An Array of the available components for Gem::URI::FTP. + # + COMPONENT = [ + :scheme, + :userinfo, :host, :port, + :path, :typecode + ].freeze + + # + # Typecode is "a", "i", or "d". + # + # * "a" indicates a text file (the FTP command was ASCII) + # * "i" indicates a binary file (FTP command IMAGE) + # * "d" indicates the contents of a directory should be displayed + # + TYPECODE = ['a', 'i', 'd'].freeze + + # Typecode prefix ";type=". + TYPECODE_PREFIX = ';type='.freeze + + def self.new2(user, password, host, port, path, + typecode = nil, arg_check = true) # :nodoc: + # Do not use this method! Not tested. [Bug #7301] + # This methods remains just for compatibility, + # Keep it undocumented until the active maintainer is assigned. + typecode = nil if typecode.size == 0 + if typecode && !TYPECODE.include?(typecode) + raise ArgumentError, + "bad typecode is specified: #{typecode}" + end + + # do escape + + self.new('ftp', + [user, password], + host, port, nil, + typecode ? path + TYPECODE_PREFIX + typecode : path, + nil, nil, nil, arg_check) + end + + # + # == Description + # + # Creates a new Gem::URI::FTP object from components, with syntax checking. + # + # The components accepted are +userinfo+, +host+, +port+, +path+, and + # +typecode+. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order <code>[userinfo, host, port, path, typecode]</code>. + # + # If the path supplied is absolute, it will be escaped in order to + # make it absolute in the Gem::URI. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri1 = Gem::URI::FTP.build(['user:password', 'ftp.example.com', nil, + # '/path/file.zip', 'i']) + # uri1.to_s # => "ftp://user:[email protected]/%2Fpath/file.zip;type=i" + # + # uri2 = Gem::URI::FTP.build({:host => 'ftp.example.com', + # :path => 'ruby/src'}) + # uri2.to_s # => "ftp://ftp.example.com/ruby/src" + # + def self.build(args) + + # Fix the incoming path to be generic URL syntax + # FTP path -> URL path + # foo/bar /foo/bar + # /foo/bar /%2Ffoo/bar + # + if args.kind_of?(Array) + args[3] = '/' + args[3].sub(/^\//, '%2F') + else + args[:path] = '/' + args[:path].sub(/^\//, '%2F') + end + + tmp = Util::make_components_hash(self, args) + + if tmp[:typecode] + if tmp[:typecode].size == 1 + tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] + end + tmp[:path] << tmp[:typecode] + end + + return super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::FTP object from generic URL components with no + # syntax checking. + # + # Unlike build(), this method does not escape the path component as + # required by RFC1738; instead it is treated as per RFC2396. + # + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+, and +fragment+, in that order. + # + def initialize(scheme, + userinfo, host, port, registry, + path, opaque, + query, + fragment, + parser = nil, + arg_check = false) + raise InvalidURIError unless path + path = path.sub(/^\//,'') + path.sub!(/^%2F/,'/') + super(scheme, userinfo, host, port, registry, path, opaque, + query, fragment, parser, arg_check) + @typecode = nil + if tmp = @path.index(TYPECODE_PREFIX) + typecode = @path[tmp + TYPECODE_PREFIX.size..-1] + @path = @path[0..tmp - 1] + + if arg_check + self.typecode = typecode + else + self.set_typecode(typecode) + end + end + end + + # typecode accessor. + # + # See Gem::URI::FTP::COMPONENT. + attr_reader :typecode + + # Validates typecode +v+, + # returns +true+ or +false+. + # + def check_typecode(v) + if TYPECODE.include?(v) + return true + else + raise InvalidComponentError, + "bad typecode(expected #{TYPECODE.join(', ')}): #{v}" + end + end + private :check_typecode + + # Private setter for the typecode +v+. + # + # See also Gem::URI::FTP.typecode=. + # + def set_typecode(v) + @typecode = v + end + protected :set_typecode + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the typecode +v+ + # (with validation). + # + # See also Gem::URI::FTP.check_typecode. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("ftp://[email protected]/my_file.img") + # #=> #<Gem::URI::FTP ftp://[email protected]/my_file.img> + # uri.typecode = "i" + # uri + # #=> #<Gem::URI::FTP ftp://[email protected]/my_file.img;type=i> + # + def typecode=(typecode) + check_typecode(typecode) + set_typecode(typecode) + typecode + end + + def merge(oth) # :nodoc: + tmp = super(oth) + if self != tmp + tmp.set_typecode(oth.typecode) + end + + return tmp + end + + # Returns the path from an FTP Gem::URI. + # + # RFC 1738 specifically states that the path for an FTP Gem::URI does not + # include the / which separates the Gem::URI path from the Gem::URI host. Example: + # + # <code>ftp://ftp.example.com/pub/ruby</code> + # + # The above Gem::URI indicates that the client should connect to + # ftp.example.com then cd to pub/ruby from the initial login directory. + # + # If you want to cd to an absolute directory, you must include an + # escaped / (%2F) in the path. Example: + # + # <code>ftp://ftp.example.com/%2Fpub/ruby</code> + # + # This method will then return "/pub/ruby". + # + def path + return @path.sub(/^\//,'').sub(/^%2F/,'/') + end + + # Private setter for the path of the Gem::URI::FTP. + def set_path(v) + super("/" + v.sub(/^\//, "%2F")) + end + protected :set_path + + # Returns a String representation of the Gem::URI::FTP. + def to_s + save_path = nil + if @typecode + save_path = @path + @path = @path + TYPECODE_PREFIX + @typecode + end + str = super + if @typecode + @path = save_path + end + + return str + end + end + + register_scheme 'FTP', FTP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/generic.rb b/lib/rubygems/vendor/uri/lib/uri/generic.rb new file mode 100644 index 0000000000..72c52aa8ee --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/generic.rb @@ -0,0 +1,1588 @@ +# frozen_string_literal: true + +# = uri/generic.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'common' +autoload :IPSocket, 'socket' +autoload :IPAddr, 'ipaddr' + +module Gem::URI + + # + # Base class for all Gem::URI classes. + # Implements generic Gem::URI syntax as per RFC 2396. + # + class Generic + include Gem::URI + + # + # A Default port of nil for Gem::URI::Generic. + # + DEFAULT_PORT = nil + + # + # Returns default port. + # + def self.default_port + self::DEFAULT_PORT + end + + # + # Returns default port. + # + def default_port + self.class.default_port + end + + # + # An Array of the available components for Gem::URI::Generic. + # + COMPONENT = [ + :scheme, + :userinfo, :host, :port, :registry, + :path, :opaque, + :query, + :fragment + ].freeze + + # + # Components of the Gem::URI in the order. + # + def self.component + self::COMPONENT + end + + USE_REGISTRY = false # :nodoc: + + def self.use_registry # :nodoc: + self::USE_REGISTRY + end + + # + # == Synopsis + # + # See ::new. + # + # == Description + # + # At first, tries to create a new Gem::URI::Generic instance using + # Gem::URI::Generic::build. But, if exception Gem::URI::InvalidComponentError is raised, + # then it does Gem::URI::Escape.escape all Gem::URI components and tries again. + # + def self.build2(args) + begin + return self.build(args) + rescue InvalidComponentError + if args.kind_of?(Array) + return self.build(args.collect{|x| + if x.is_a?(String) + DEFAULT_PARSER.escape(x) + else + x + end + }) + elsif args.kind_of?(Hash) + tmp = {} + args.each do |key, value| + tmp[key] = if value + DEFAULT_PARSER.escape(value) + else + value + end + end + return self.build(tmp) + end + end + end + + # + # == Synopsis + # + # See ::new. + # + # == Description + # + # Creates a new Gem::URI::Generic instance from components of Gem::URI::Generic + # with check. Components are: scheme, userinfo, host, port, registry, path, + # opaque, query, and fragment. You can provide arguments either by an Array or a Hash. + # See ::new for hash keys to use or for order of array items. + # + def self.build(args) + if args.kind_of?(Array) && + args.size == ::Gem::URI::Generic::COMPONENT.size + tmp = args.dup + elsif args.kind_of?(Hash) + tmp = ::Gem::URI::Generic::COMPONENT.collect do |c| + if args.include?(c) + args[c] + else + nil + end + end + else + component = self.class.component rescue ::Gem::URI::Generic::COMPONENT + raise ArgumentError, + "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})" + end + + tmp << nil + tmp << true + return self.new(*tmp) + end + + # + # == Args + # + # +scheme+:: + # Protocol scheme, i.e. 'http','ftp','mailto' and so on. + # +userinfo+:: + # User name and password, i.e. 'sdmitry:bla'. + # +host+:: + # Server host name. + # +port+:: + # Server port. + # +registry+:: + # Registry of naming authorities. + # +path+:: + # Path on server. + # +opaque+:: + # Opaque part. + # +query+:: + # Query data. + # +fragment+:: + # Part of the Gem::URI after '#' character. + # +parser+:: + # Parser for internal use [Gem::URI::DEFAULT_PARSER by default]. + # +arg_check+:: + # Check arguments [false by default]. + # + # == Description + # + # Creates a new Gem::URI::Generic instance from ``generic'' components without check. + # + def initialize(scheme, + userinfo, host, port, registry, + path, opaque, + query, + fragment, + parser = DEFAULT_PARSER, + arg_check = false) + @scheme = nil + @user = nil + @password = nil + @host = nil + @port = nil + @path = nil + @query = nil + @opaque = nil + @fragment = nil + @parser = parser == DEFAULT_PARSER ? nil : parser + + if arg_check + self.scheme = scheme + self.userinfo = userinfo + self.hostname = host + self.port = port + self.path = path + self.query = query + self.opaque = opaque + self.fragment = fragment + else + self.set_scheme(scheme) + self.set_userinfo(userinfo) + self.set_host(host) + self.set_port(port) + self.set_path(path) + self.query = query + self.set_opaque(opaque) + self.fragment=(fragment) + end + if registry + raise InvalidURIError, + "the scheme #{@scheme} does not accept registry part: #{registry} (or bad hostname?)" + end + + @scheme&.freeze + self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2) + self.set_port(self.default_port) if self.default_port && !@port + end + + # + # Returns the scheme component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").scheme #=> "http" + # + attr_reader :scheme + + # Returns the host component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").host #=> "foo" + # + # It returns nil if no host component exists. + # + # Gem::URI("mailto:[email protected]").host #=> nil + # + # The component does not contain the port number. + # + # Gem::URI("http://foo:8080/bar/baz").host #=> "foo" + # + # Since IPv6 addresses are wrapped with brackets in URIs, + # this method returns IPv6 addresses wrapped with brackets. + # This form is not appropriate to pass to socket methods such as TCPSocket.open. + # If unwrapped host names are required, use the #hostname method. + # + # Gem::URI("http://[::1]/bar/baz").host #=> "[::1]" + # Gem::URI("http://[::1]/bar/baz").hostname #=> "::1" + # + attr_reader :host + + # Returns the port component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").port #=> 80 + # Gem::URI("http://foo:8080/bar/baz").port #=> 8080 + # + attr_reader :port + + def registry # :nodoc: + nil + end + + # Returns the path component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").path #=> "/bar/baz" + # + attr_reader :path + + # Returns the query component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar" + # + attr_reader :query + + # Returns the opaque part of the Gem::URI. + # + # Gem::URI("mailto:[email protected]").opaque #=> "[email protected]" + # Gem::URI("http://foo/bar/baz").opaque #=> nil + # + # The portion of the path that does not make use of the slash '/'. + # The path typically refers to an absolute path or an opaque part. + # (See RFC2396 Section 3 and 5.2.) + # + attr_reader :opaque + + # Returns the fragment component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies" + # + attr_reader :fragment + + # Returns the parser to be used. + # + # Unless a Gem::URI::Parser is defined, DEFAULT_PARSER is used. + # + def parser + if !defined?(@parser) || !@parser + DEFAULT_PARSER + else + @parser || DEFAULT_PARSER + end + end + + # Replaces self by other Gem::URI object. + # + def replace!(oth) + if self.class != oth.class + raise ArgumentError, "expected #{self.class} object" + end + + component.each do |c| + self.__send__("#{c}=", oth.__send__(c)) + end + end + private :replace! + + # + # Components of the Gem::URI in the order. + # + def component + self.class.component + end + + # + # Checks the scheme +v+ component against the Gem::URI::Parser Regexp for :SCHEME. + # + def check_scheme(v) + if v && parser.regexp[:SCHEME] !~ v + raise InvalidComponentError, + "bad component(expected scheme component): #{v}" + end + + return true + end + private :check_scheme + + # Protected setter for the scheme component +v+. + # + # See also Gem::URI::Generic.scheme=. + # + def set_scheme(v) + @scheme = v&.downcase + end + protected :set_scheme + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the scheme component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_scheme. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.scheme = "https" + # uri.to_s #=> "https://my.example.com" + # + def scheme=(v) + check_scheme(v) + set_scheme(v) + v + end + + # + # Checks the +user+ and +password+. + # + # If +password+ is not provided, then +user+ is + # split, using Gem::URI::Generic.split_userinfo, to + # pull +user+ and +password. + # + # See also Gem::URI::Generic.check_user, Gem::URI::Generic.check_password. + # + def check_userinfo(user, password = nil) + if !password + user, password = split_userinfo(user) + end + check_user(user) + check_password(password, user) + + return true + end + private :check_userinfo + + # + # Checks the user +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :USERINFO. + # + # Can not have a registry or opaque component defined, + # with a user component defined. + # + def check_user(v) + if @opaque + raise InvalidURIError, + "can not set user with opaque" + end + + return v unless v + + if parser.regexp[:USERINFO] !~ v + raise InvalidComponentError, + "bad component(expected userinfo component or user component): #{v}" + end + + return true + end + private :check_user + + # + # Checks the password +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :USERINFO. + # + # Can not have a registry or opaque component defined, + # with a user component defined. + # + def check_password(v, user = @user) + if @opaque + raise InvalidURIError, + "can not set password with opaque" + end + return v unless v + + if !user + raise InvalidURIError, + "password component depends user component" + end + + if parser.regexp[:USERINFO] !~ v + raise InvalidComponentError, + "bad password component" + end + + return true + end + private :check_password + + # + # Sets userinfo, argument is string like 'name:pass'. + # + def userinfo=(userinfo) + if userinfo.nil? + return nil + end + check_userinfo(*userinfo) + set_userinfo(*userinfo) + # returns userinfo + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the +user+ component + # (with validation). + # + # See also Gem::URI::Generic.check_user. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://john:[email protected]") + # uri.user = "sam" + # uri.to_s #=> "http://sam:[email protected]" + # + def user=(user) + check_user(user) + set_user(user) + # returns user + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the +password+ component + # (with validation). + # + # See also Gem::URI::Generic.check_password. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://john:[email protected]") + # uri.password = "V3ry_S3nsit1ve" + # uri.to_s #=> "http://john:[email protected]" + # + def password=(password) + check_password(password) + set_password(password) + # returns password + end + + # Protected setter for the +user+ component, and +password+ if available + # (with validation). + # + # See also Gem::URI::Generic.userinfo=. + # + def set_userinfo(user, password = nil) + unless password + user, password = split_userinfo(user) + end + @user = user + @password = password if password + + [@user, @password] + end + protected :set_userinfo + + # Protected setter for the user component +v+. + # + # See also Gem::URI::Generic.user=. + # + def set_user(v) + set_userinfo(v, @password) + v + end + protected :set_user + + # Protected setter for the password component +v+. + # + # See also Gem::URI::Generic.password=. + # + def set_password(v) + @password = v + # returns v + end + protected :set_password + + # Returns the userinfo +ui+ as <code>[user, password]</code> + # if properly formatted as 'user:password'. + def split_userinfo(ui) + return nil, nil unless ui + user, password = ui.split(':', 2) + + return user, password + end + private :split_userinfo + + # Escapes 'user:password' +v+ based on RFC 1738 section 3.1. + def escape_userpass(v) + parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/ + end + private :escape_userpass + + # Returns the userinfo, either as 'user' or 'user:password'. + def userinfo + if @user.nil? + nil + elsif @password.nil? + @user + else + @user + ':' + @password + end + end + + # Returns the user component (without Gem::URI decoding). + def user + @user + end + + # Returns the password component (without Gem::URI decoding). + def password + @password + end + + # Returns the user component after Gem::URI decoding. + def decoded_user + Gem::URI.decode_uri_component(@user) if @user + end + + # Returns the password component after Gem::URI decoding. + def decoded_password + Gem::URI.decode_uri_component(@password) if @password + end + + # + # Checks the host +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :HOST. + # + # Can not have a registry or opaque component defined, + # with a host component defined. + # + def check_host(v) + return v unless v + + if @opaque + raise InvalidURIError, + "can not set host with registry or opaque" + elsif parser.regexp[:HOST] !~ v + raise InvalidComponentError, + "bad component(expected host component): #{v}" + end + + return true + end + private :check_host + + # Protected setter for the host component +v+. + # + # See also Gem::URI::Generic.host=. + # + def set_host(v) + @host = v + end + protected :set_host + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the host component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_host. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.host = "foo.com" + # uri.to_s #=> "http://foo.com" + # + def host=(v) + check_host(v) + set_host(v) + v + end + + # Extract the host part of the Gem::URI and unwrap brackets for IPv6 addresses. + # + # This method is the same as Gem::URI::Generic#host except + # brackets for IPv6 (and future IP) addresses are removed. + # + # uri = Gem::URI("http://[::1]/bar") + # uri.hostname #=> "::1" + # uri.host #=> "[::1]" + # + def hostname + v = self.host + v&.start_with?('[') && v.end_with?(']') ? v[1..-2] : v + end + + # Sets the host part of the Gem::URI as the argument with brackets for IPv6 addresses. + # + # This method is the same as Gem::URI::Generic#host= except + # the argument can be a bare IPv6 address. + # + # uri = Gem::URI("http://foo/bar") + # uri.hostname = "::1" + # uri.to_s #=> "http://[::1]/bar" + # + # If the argument seems to be an IPv6 address, + # it is wrapped with brackets. + # + def hostname=(v) + v = "[#{v}]" if !(v&.start_with?('[') && v&.end_with?(']')) && v&.index(':') + self.host = v + end + + # + # Checks the port +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :PORT. + # + # Can not have a registry or opaque component defined, + # with a port component defined. + # + def check_port(v) + return v unless v + + if @opaque + raise InvalidURIError, + "can not set port with registry or opaque" + elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v + raise InvalidComponentError, + "bad component(expected port component): #{v.inspect}" + end + + return true + end + private :check_port + + # Protected setter for the port component +v+. + # + # See also Gem::URI::Generic.port=. + # + def set_port(v) + v = v.empty? ? nil : v.to_i unless !v || v.kind_of?(Integer) + @port = v + end + protected :set_port + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the port component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_port. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.port = 8080 + # uri.to_s #=> "http://my.example.com:8080" + # + def port=(v) + check_port(v) + set_port(v) + port + end + + def check_registry(v) # :nodoc: + raise InvalidURIError, "can not set registry" + end + private :check_registry + + def set_registry(v) #:nodoc: + raise InvalidURIError, "can not set registry" + end + protected :set_registry + + def registry=(v) + raise InvalidURIError, "can not set registry" + end + + # + # Checks the path +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp + # for :ABS_PATH and :REL_PATH. + # + # Can not have a opaque component defined, + # with a path component defined. + # + def check_path(v) + # raise if both hier and opaque are not nil, because: + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + if v && @opaque + raise InvalidURIError, + "path conflicts with opaque" + end + + # If scheme is ftp, path may be relative. + # See RFC 1738 section 3.2.2, and RFC 2396. + if @scheme && @scheme != "ftp" + if v && v != '' && parser.regexp[:ABS_PATH] !~ v + raise InvalidComponentError, + "bad component(expected absolute path component): #{v}" + end + else + if v && v != '' && parser.regexp[:ABS_PATH] !~ v && + parser.regexp[:REL_PATH] !~ v + raise InvalidComponentError, + "bad component(expected relative path component): #{v}" + end + end + + return true + end + private :check_path + + # Protected setter for the path component +v+. + # + # See also Gem::URI::Generic.path=. + # + def set_path(v) + @path = v + end + protected :set_path + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the path component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_path. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/pub/files") + # uri.path = "/faq/" + # uri.to_s #=> "http://my.example.com/faq/" + # + def path=(v) + check_path(v) + set_path(v) + v + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the query component +v+. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/?id=25") + # uri.query = "id=1" + # uri.to_s #=> "http://my.example.com/?id=1" + # + def query=(v) + return @query = nil unless v + raise InvalidURIError, "query conflicts with opaque" if @opaque + + x = v.to_str + v = x.dup if x.equal? v + v.encode!(Encoding::UTF_8) rescue nil + v.delete!("\t\r\n") + v.force_encoding(Encoding::ASCII_8BIT) + raise InvalidURIError, "invalid percent escape: #{$1}" if /(%\H\H)/n.match(v) + v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n.freeze){'%%%02X' % $&.ord} + v.force_encoding(Encoding::US_ASCII) + @query = v + end + + # + # Checks the opaque +v+ component for RFC2396 compliance and + # against the Gem::URI::Parser Regexp for :OPAQUE. + # + # Can not have a host, port, user, or path component defined, + # with an opaque component defined. + # + def check_opaque(v) + return v unless v + + # raise if both hier and opaque are not nil, because: + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + if @host || @port || @user || @path # userinfo = @user + ':' + @password + raise InvalidURIError, + "can not set opaque with host, port, userinfo or path" + elsif v && parser.regexp[:OPAQUE] !~ v + raise InvalidComponentError, + "bad component(expected opaque component): #{v}" + end + + return true + end + private :check_opaque + + # Protected setter for the opaque component +v+. + # + # See also Gem::URI::Generic.opaque=. + # + def set_opaque(v) + @opaque = v + end + protected :set_opaque + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the opaque component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_opaque. + # + def opaque=(v) + check_opaque(v) + set_opaque(v) + v + end + + # + # Checks the fragment +v+ component against the Gem::URI::Parser Regexp for :FRAGMENT. + # + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the fragment component +v+ + # (with validation). + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/?id=25#time=1305212049") + # uri.fragment = "time=1305212086" + # uri.to_s #=> "http://my.example.com/?id=25#time=1305212086" + # + def fragment=(v) + return @fragment = nil unless v + + x = v.to_str + v = x.dup if x.equal? v + v.encode!(Encoding::UTF_8) rescue nil + v.delete!("\t\r\n") + v.force_encoding(Encoding::ASCII_8BIT) + v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X' % $&.ord} + v.force_encoding(Encoding::US_ASCII) + @fragment = v + end + + # + # Returns true if Gem::URI is hierarchical. + # + # == Description + # + # Gem::URI has components listed in order of decreasing significance from left to right, + # see RFC3986 https://tools.ietf.org/html/rfc3986 1.2.3. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/") + # uri.hierarchical? + # #=> true + # uri = Gem::URI.parse("mailto:[email protected]") + # uri.hierarchical? + # #=> false + # + def hierarchical? + if @path + true + else + false + end + end + + # + # Returns true if Gem::URI has a scheme (e.g. http:// or https://) specified. + # + def absolute? + if @scheme + true + else + false + end + end + alias absolute absolute? + + # + # Returns true if Gem::URI does not have a scheme (e.g. http:// or https://) specified. + # + def relative? + !absolute? + end + + # + # Returns an Array of the path split on '/'. + # + def split_path(path) + path.split("/", -1) + end + private :split_path + + # + # Merges a base path +base+, with relative path +rel+, + # returns a modified base path. + # + def merge_path(base, rel) + + # RFC2396, Section 5.2, 5) + # RFC2396, Section 5.2, 6) + base_path = split_path(base) + rel_path = split_path(rel) + + # RFC2396, Section 5.2, 6), a) + base_path << '' if base_path.last == '..' + while i = base_path.index('..') + base_path.slice!(i - 1, 2) + end + + if (first = rel_path.first) and first.empty? + base_path.clear + rel_path.shift + end + + # RFC2396, Section 5.2, 6), c) + # RFC2396, Section 5.2, 6), d) + rel_path.push('') if rel_path.last == '.' || rel_path.last == '..' + rel_path.delete('.') + + # RFC2396, Section 5.2, 6), e) + tmp = [] + rel_path.each do |x| + if x == '..' && + !(tmp.empty? || tmp.last == '..') + tmp.pop + else + tmp << x + end + end + + add_trailer_slash = !tmp.empty? + if base_path.empty? + base_path = [''] # keep '/' for root directory + elsif add_trailer_slash + base_path.pop + end + while x = tmp.shift + if x == '..' + # RFC2396, Section 4 + # a .. or . in an absolute path has no special meaning + base_path.pop if base_path.size > 1 + else + # if x == '..' + # valid absolute (but abnormal) path "/../..." + # else + # valid absolute path + # end + base_path << x + tmp.each {|t| base_path << t} + add_trailer_slash = false + break + end + end + base_path.push('') if add_trailer_slash + + return base_path.join('/') + end + private :merge_path + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Destructive form of #merge. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.merge!("/main.rbx?page=1") + # uri.to_s # => "http://my.example.com/main.rbx?page=1" + # + def merge!(oth) + t = merge(oth) + if self == t + nil + else + replace!(t) + self + end + end + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Merges two URIs. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.merge("/main.rbx?page=1") + # # => "http://my.example.com/main.rbx?page=1" + # + def merge(oth) + rel = parser.__send__(:convert_to_uri, oth) + + if rel.absolute? + #raise BadURIError, "both Gem::URI are absolute" if absolute? + # hmm... should return oth for usability? + return rel + end + + unless self.absolute? + raise BadURIError, "both Gem::URI are relative" + end + + base = self.dup + + authority = rel.userinfo || rel.host || rel.port + + # RFC2396, Section 5.2, 2) + if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query + base.fragment=(rel.fragment) if rel.fragment + return base + end + + base.query = nil + base.fragment=(nil) + + # RFC2396, Section 5.2, 4) + if !authority + base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path + else + # RFC2396, Section 5.2, 4) + base.set_path(rel.path) if rel.path + end + + # RFC2396, Section 5.2, 7) + base.set_userinfo(rel.userinfo) if rel.userinfo + base.set_host(rel.host) if rel.host + base.set_port(rel.port) if rel.port + base.query = rel.query if rel.query + base.fragment=(rel.fragment) if rel.fragment + + return base + end # merge + alias + merge + + # :stopdoc: + def route_from_path(src, dst) + case dst + when src + # RFC2396, Section 4.2 + return '' + when %r{(?:\A|/)\.\.?(?:/|\z)} + # dst has abnormal absolute path, + # like "/./", "/../", "/x/../", ... + return dst.dup + end + + src_path = src.scan(%r{[^/]*/}) + dst_path = dst.scan(%r{[^/]*/?}) + + # discard same parts + while !dst_path.empty? && dst_path.first == src_path.first + src_path.shift + dst_path.shift + end + + tmp = dst_path.join + + # calculate + if src_path.empty? + if tmp.empty? + return './' + elsif dst_path.first.include?(':') # (see RFC2396 Section 5) + return './' + tmp + else + return tmp + end + end + + return '../' * src_path.size + tmp + end + private :route_from_path + # :startdoc: + + # :stopdoc: + def route_from0(oth) + oth = parser.__send__(:convert_to_uri, oth) + if self.relative? + raise BadURIError, + "relative Gem::URI: #{self}" + end + if oth.relative? + raise BadURIError, + "relative Gem::URI: #{oth}" + end + + if self.scheme != oth.scheme + return self, self.dup + end + rel = Gem::URI::Generic.new(nil, # it is relative Gem::URI + self.userinfo, self.host, self.port, + nil, self.path, self.opaque, + self.query, self.fragment, parser) + + if rel.userinfo != oth.userinfo || + rel.host.to_s.downcase != oth.host.to_s.downcase || + rel.port != oth.port + + if self.userinfo.nil? && self.host.nil? + return self, self.dup + end + + rel.set_port(nil) if rel.port == oth.default_port + return rel, rel + end + rel.set_userinfo(nil) + rel.set_host(nil) + rel.set_port(nil) + + if rel.path && rel.path == oth.path + rel.set_path('') + rel.query = nil if rel.query == oth.query + return rel, rel + elsif rel.opaque && rel.opaque == oth.opaque + rel.set_opaque('') + rel.query = nil if rel.query == oth.query + return rel, rel + end + + # you can modify `rel', but can not `oth'. + return oth, rel + end + private :route_from0 + # :startdoc: + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Calculates relative path from oth to self. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://my.example.com/main.rbx?page=1') + # uri.route_from('http://my.example.com') + # #=> #<Gem::URI::Generic /main.rbx?page=1> + # + def route_from(oth) + # you can modify `rel', but can not `oth'. + begin + oth, rel = route_from0(oth) + rescue + raise $!.class, $!.message + end + if oth == rel + return rel + end + + rel.set_path(route_from_path(oth.path, self.path)) + if rel.path == './' && self.query + # "./?foo" -> "?foo" + rel.set_path('') + end + + return rel + end + + alias - route_from + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Calculates relative path to oth from self. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://my.example.com') + # uri.route_to('http://my.example.com/main.rbx?page=1') + # #=> #<Gem::URI::Generic /main.rbx?page=1> + # + def route_to(oth) + parser.__send__(:convert_to_uri, oth).route_from(self) + end + + # + # Returns normalized Gem::URI. + # + # require 'rubygems/vendor/uri/lib/uri' + # + # Gem::URI("HTTP://my.EXAMPLE.com").normalize + # #=> #<Gem::URI::HTTP http://my.example.com/> + # + # Normalization here means: + # + # * scheme and host are converted to lowercase, + # * an empty path component is set to "/". + # + def normalize + uri = dup + uri.normalize! + uri + end + + # + # Destructive version of #normalize. + # + def normalize! + if path&.empty? + set_path('/') + end + if scheme && scheme != scheme.downcase + set_scheme(self.scheme.downcase) + end + if host && host != host.downcase + set_host(self.host.downcase) + end + end + + # + # Constructs String from Gem::URI. + # + def to_s + str = ''.dup + if @scheme + str << @scheme + str << ':' + end + + if @opaque + str << @opaque + else + if @host || %w[file postgres].include?(@scheme) + str << '//' + end + if self.userinfo + str << self.userinfo + str << '@' + end + if @host + str << @host + end + if @port && @port != self.default_port + str << ':' + str << @port.to_s + end + str << @path + if @query + str << '?' + str << @query + end + end + if @fragment + str << '#' + str << @fragment + end + str + end + alias to_str to_s + + # + # Compares two URIs. + # + def ==(oth) + if self.class == oth.class + self.normalize.component_ary == oth.normalize.component_ary + else + false + end + end + + def hash + self.component_ary.hash + end + + def eql?(oth) + self.class == oth.class && + parser == oth.parser && + self.component_ary.eql?(oth.component_ary) + end + +=begin + +--- Gem::URI::Generic#===(oth) + +=end +# def ===(oth) +# raise NotImplementedError +# end + +=begin +=end + + + # Returns an Array of the components defined from the COMPONENT Array. + def component_ary + component.collect do |x| + self.__send__(x) + end + end + protected :component_ary + + # == Args + # + # +components+:: + # Multiple Symbol arguments defined in Gem::URI::HTTP. + # + # == Description + # + # Selects specified components from Gem::URI. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://myuser:[email protected]/test.rbx') + # uri.select(:userinfo, :host, :path) + # # => ["myuser:mypass", "my.example.com", "/test.rbx"] + # + def select(*components) + components.collect do |c| + if component.include?(c) + self.__send__(c) + else + raise ArgumentError, + "expected of components of #{self.class} (#{self.class.component.join(', ')})" + end + end + end + + def inspect + "#<#{self.class} #{self}>" + end + + # + # == Args + # + # +v+:: + # Gem::URI or String + # + # == Description + # + # Attempts to parse other Gem::URI +oth+, + # returns [parsed_oth, self]. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.coerce("http://foo.com") + # #=> [#<Gem::URI::HTTP http://foo.com>, #<Gem::URI::HTTP http://my.example.com>] + # + def coerce(oth) + case oth + when String + oth = parser.parse(oth) + else + super + end + + return oth, self + end + + # Returns a proxy Gem::URI. + # The proxy Gem::URI is obtained from environment variables such as http_proxy, + # ftp_proxy, no_proxy, etc. + # If there is no proper proxy, nil is returned. + # + # If the optional parameter +env+ is specified, it is used instead of ENV. + # + # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.) + # are examined, too. + # + # But http_proxy and HTTP_PROXY is treated specially under CGI environment. + # It's because HTTP_PROXY may be set by Proxy: header. + # So HTTP_PROXY is not used. + # http_proxy is not used too if the variable is case insensitive. + # CGI_HTTP_PROXY can be used instead. + def find_proxy(env=ENV) + raise BadURIError, "relative Gem::URI: #{self}" if self.relative? + name = self.scheme.downcase + '_proxy' + proxy_uri = nil + if name == 'http_proxy' && env.include?('REQUEST_METHOD') # CGI? + # HTTP_PROXY conflicts with *_proxy for proxy settings and + # HTTP_* for header information in CGI. + # So it should be careful to use it. + pairs = env.reject {|k, v| /\Ahttp_proxy\z/i !~ k } + case pairs.length + when 0 # no proxy setting anyway. + proxy_uri = nil + when 1 + k, _ = pairs.shift + if k == 'http_proxy' && env[k.upcase] == nil + # http_proxy is safe to use because ENV is case sensitive. + proxy_uri = env[name] + else + proxy_uri = nil + end + else # http_proxy is safe to use because ENV is case sensitive. + proxy_uri = env.to_hash[name] + end + if !proxy_uri + # Use CGI_HTTP_PROXY. cf. libwww-perl. + proxy_uri = env["CGI_#{name.upcase}"] + end + elsif name == 'http_proxy' + if RUBY_ENGINE == 'jruby' && p_addr = ENV_JAVA['http.proxyHost'] + p_port = ENV_JAVA['http.proxyPort'] + if p_user = ENV_JAVA['http.proxyUser'] + p_pass = ENV_JAVA['http.proxyPass'] + proxy_uri = "http://#{p_user}:#{p_pass}@#{p_addr}:#{p_port}" + else + proxy_uri = "http://#{p_addr}:#{p_port}" + end + else + unless proxy_uri = env[name] + if proxy_uri = env[name.upcase] + warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1 + end + end + end + else + proxy_uri = env[name] || env[name.upcase] + end + + if proxy_uri.nil? || proxy_uri.empty? + return nil + end + + if self.hostname + begin + addr = IPSocket.getaddress(self.hostname) + return nil if /\A127\.|\A::1\z/ =~ addr + rescue SocketError + end + end + + name = 'no_proxy' + if no_proxy = env[name] || env[name.upcase] + return nil unless Gem::URI::Generic.use_proxy?(self.hostname, addr, self.port, no_proxy) + end + Gem::URI.parse(proxy_uri) + end + + def self.use_proxy?(hostname, addr, port, no_proxy) # :nodoc: + hostname = hostname.downcase + dothostname = ".#{hostname}" + no_proxy.scan(/([^:,\s]+)(?::(\d+))?/) {|p_host, p_port| + if !p_port || port == p_port.to_i + if p_host.start_with?('.') + return false if hostname.end_with?(p_host.downcase) + else + return false if dothostname.end_with?(".#{p_host.downcase}") + end + if addr + begin + return false if IPAddr.new(p_host).include?(addr) + rescue IPAddr::InvalidAddressError + next + end + end + end + } + true + end + end +end diff --git a/lib/rubygems/vendor/uri/lib/uri/http.rb b/lib/rubygems/vendor/uri/lib/uri/http.rb new file mode 100644 index 0000000000..bef43490a3 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/http.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: false +# = uri/http.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # The syntax of HTTP URIs is defined in RFC1738 section 3.3. + # + # Note that the Ruby Gem::URI library allows HTTP URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See <URL:http://support.microsoft.com/kb/834489>. + # + class HTTP < Generic + # A Default port of 80 for Gem::URI::HTTP. + DEFAULT_PORT = 80 + + # An Array of the available components for Gem::URI::HTTP. + COMPONENT = %i[ + scheme + userinfo host port + path + query + fragment + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::HTTP object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, query, and + # fragment. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order <code>[userinfo, host, port, path, query, fragment]</code>. + # + # Example: + # + # uri = Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = Gem::URI::HTTP.build([nil, "www.example.com", nil, "/path", + # "query", 'fragment']) + # + # Currently, if passed userinfo components this method generates + # invalid HTTP URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for an HTTP request, as required by Net::HTTP::Get. + # + # If the Gem::URI contains a query, the full path is Gem::URI#path + '?' + Gem::URI#query. + # Otherwise, the path is simply Gem::URI#path. + # + # Example: + # + # uri = Gem::URI::HTTP.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + + # + # == Description + # + # Returns the authority for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2. + # + # + # Example: + # + # Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').authority #=> "www.example.com" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').authority #=> "www.example.com:8000" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').authority #=> "www.example.com" + # + def authority + if port == default_port + host + else + "#{host}:#{port}" + end + end + + # + # == Description + # + # Returns the origin for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc6454. + # + # + # Example: + # + # Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').origin #=> "http://www.example.com" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').origin #=> "http://www.example.com:8000" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').origin #=> "http://www.example.com" + # Gem::URI::HTTPS.build(host: 'www.example.com', path: '/foo/bar').origin #=> "https://www.example.com" + # + def origin + "#{scheme}://#{authority}" + end + end + + register_scheme 'HTTP', HTTP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/https.rb b/lib/rubygems/vendor/uri/lib/uri/https.rb new file mode 100644 index 0000000000..6e8e732e1d --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/https.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: false +# = uri/https.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'http' + +module Gem::URI + + # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather + # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs; + # see Gem::URI::HTTP. + class HTTPS < HTTP + # A Default port of 443 for Gem::URI::HTTPS + DEFAULT_PORT = 443 + end + + register_scheme 'HTTPS', HTTPS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ldap.rb b/lib/rubygems/vendor/uri/lib/uri/ldap.rb new file mode 100644 index 0000000000..1a08b5ab7e --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ldap.rb @@ -0,0 +1,261 @@ +# frozen_string_literal: false +# = uri/ldap.rb +# +# Author:: +# Takaaki Tateishi <[email protected]> +# Akira Yamada <[email protected]> +# License:: +# Gem::URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada. +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # LDAP Gem::URI SCHEMA (described in RFC2255). + #-- + # ldap://<host>/<dn>[?<attrs>[?<scope>[?<filter>[?<extensions>]]]] + #++ + class LDAP < Generic + + # A Default port of 389 for Gem::URI::LDAP. + DEFAULT_PORT = 389 + + # An Array of the available components for Gem::URI::LDAP. + COMPONENT = [ + :scheme, + :host, :port, + :dn, + :attributes, + :scope, + :filter, + :extensions, + ].freeze + + # Scopes available for the starting point. + # + # * SCOPE_BASE - the Base DN + # * SCOPE_ONE - one level under the Base DN, not including the base DN and + # not including any entries under this + # * SCOPE_SUB - subtrees, all entries at all levels + # + SCOPE = [ + SCOPE_ONE = 'one', + SCOPE_SUB = 'sub', + SCOPE_BASE = 'base', + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::LDAP object from components, with syntax checking. + # + # The components accepted are host, port, dn, attributes, + # scope, filter, and extensions. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order <code>[host, port, dn, attributes, scope, filter, extensions]</code>. + # + # Example: + # + # uri = Gem::URI::LDAP.build({:host => 'ldap.example.com', + # :dn => '/dc=example'}) + # + # uri = Gem::URI::LDAP.build(["ldap.example.com", nil, + # "/dc=example;dc=com", "query", nil, nil, nil]) + # + def self.build(args) + tmp = Util::make_components_hash(self, args) + + if tmp[:dn] + tmp[:path] = tmp[:dn] + end + + query = [] + [:extensions, :filter, :scope, :attributes].collect do |x| + next if !tmp[x] && query.size == 0 + query.unshift(tmp[x]) + end + + tmp[:query] = query.join('?') + + return super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::LDAP object from generic Gem::URI components as per + # RFC 2396. No LDAP-specific syntax checking is performed. + # + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+, and +fragment+, in that order. + # + # Example: + # + # uri = Gem::URI::LDAP.new("ldap", nil, "ldap.example.com", nil, nil, + # "/dc=example;dc=com", nil, "query", nil) + # + # See also Gem::URI::Generic.new. + # + def initialize(*arg) + super(*arg) + + if @fragment + raise InvalidURIError, 'bad LDAP URL' + end + + parse_dn + parse_query + end + + # Private method to cleanup +dn+ from using the +path+ component attribute. + def parse_dn + raise InvalidURIError, 'bad LDAP URL' unless @path + @dn = @path[1..-1] + end + private :parse_dn + + # Private method to cleanup +attributes+, +scope+, +filter+, and +extensions+ + # from using the +query+ component attribute. + def parse_query + @attributes = nil + @scope = nil + @filter = nil + @extensions = nil + + if @query + attrs, scope, filter, extensions = @query.split('?') + + @attributes = attrs if attrs && attrs.size > 0 + @scope = scope if scope && scope.size > 0 + @filter = filter if filter && filter.size > 0 + @extensions = extensions if extensions && extensions.size > 0 + end + end + private :parse_query + + # Private method to assemble +query+ from +attributes+, +scope+, +filter+, and +extensions+. + def build_path_query + @path = '/' + @dn + + query = [] + [@extensions, @filter, @scope, @attributes].each do |x| + next if !x && query.size == 0 + query.unshift(x) + end + @query = query.join('?') + end + private :build_path_query + + # Returns dn. + def dn + @dn + end + + # Private setter for dn +val+. + def set_dn(val) + @dn = val + build_path_query + @dn + end + protected :set_dn + + # Setter for dn +val+. + def dn=(val) + set_dn(val) + val + end + + # Returns attributes. + def attributes + @attributes + end + + # Private setter for attributes +val+. + def set_attributes(val) + @attributes = val + build_path_query + @attributes + end + protected :set_attributes + + # Setter for attributes +val+. + def attributes=(val) + set_attributes(val) + val + end + + # Returns scope. + def scope + @scope + end + + # Private setter for scope +val+. + def set_scope(val) + @scope = val + build_path_query + @scope + end + protected :set_scope + + # Setter for scope +val+. + def scope=(val) + set_scope(val) + val + end + + # Returns filter. + def filter + @filter + end + + # Private setter for filter +val+. + def set_filter(val) + @filter = val + build_path_query + @filter + end + protected :set_filter + + # Setter for filter +val+. + def filter=(val) + set_filter(val) + val + end + + # Returns extensions. + def extensions + @extensions + end + + # Private setter for extensions +val+. + def set_extensions(val) + @extensions = val + build_path_query + @extensions + end + protected :set_extensions + + # Setter for extensions +val+. + def extensions=(val) + set_extensions(val) + val + end + + # Checks if Gem::URI has a path. + # For Gem::URI::LDAP this will return +false+. + def hierarchical? + false + end + end + + register_scheme 'LDAP', LDAP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ldaps.rb b/lib/rubygems/vendor/uri/lib/uri/ldaps.rb new file mode 100644 index 0000000000..b7a5b50e27 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ldaps.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: false +# = uri/ldap.rb +# +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'ldap' + +module Gem::URI + + # The default port for LDAPS URIs is 636, and the scheme is 'ldaps:' rather + # than 'ldap:'. Other than that, LDAPS URIs are identical to LDAP URIs; + # see Gem::URI::LDAP. + class LDAPS < LDAP + # A Default port of 636 for Gem::URI::LDAPS + DEFAULT_PORT = 636 + end + + register_scheme 'LDAPS', LDAPS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/mailto.rb b/lib/rubygems/vendor/uri/lib/uri/mailto.rb new file mode 100644 index 0000000000..7ae544d194 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/mailto.rb @@ -0,0 +1,293 @@ +# frozen_string_literal: false +# = uri/mailto.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # RFC6068, the mailto URL scheme. + # + class MailTo < Generic + include RFC2396_REGEXP + + # A Default port of nil for Gem::URI::MailTo. + DEFAULT_PORT = nil + + # An Array of the available components for Gem::URI::MailTo. + COMPONENT = [ :scheme, :to, :headers ].freeze + + # :stopdoc: + # "hname" and "hvalue" are encodings of an RFC 822 header name and + # value, respectively. As with "to", all URL reserved characters must + # be encoded. + # + # "#mailbox" is as specified in RFC 822 [RFC822]. This means that it + # consists of zero or more comma-separated mail addresses, possibly + # including "phrase" and "comment" components. Note that all URL + # reserved characters in "to" must be encoded: in particular, + # parentheses, commas, and the percent sign ("%"), which commonly occur + # in the "mailbox" syntax. + # + # Within mailto URLs, the characters "?", "=", "&" are reserved. + + # ; RFC 6068 + # hfields = "?" hfield *( "&" hfield ) + # hfield = hfname "=" hfvalue + # hfname = *qchar + # hfvalue = *qchar + # qchar = unreserved / pct-encoded / some-delims + # some-delims = "!" / "$" / "'" / "(" / ")" / "*" + # / "+" / "," / ";" / ":" / "@" + # + # ; RFC3986 + # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + # pct-encoded = "%" HEXDIG HEXDIG + HEADER_REGEXP = /\A(?<hfield>(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g<hfield>)*\z/ + # practical regexp for email address + # https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address + EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/ + # :startdoc: + + # + # == Description + # + # Creates a new Gem::URI::MailTo object from components, with syntax checking. + # + # Components can be provided as an Array or Hash. If an Array is used, + # the components must be supplied as <code>[to, headers]</code>. + # + # If a Hash is used, the keys are the component names preceded by colons. + # + # The headers can be supplied as a pre-encoded string, such as + # <code>"subject=subscribe&cc=address"</code>, or as an Array of Arrays + # like <code>[['subject', 'subscribe'], ['cc', 'address']]</code>. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # m1 = Gem::URI::MailTo.build(['[email protected]', 'subject=Ruby']) + # m1.to_s # => "mailto:[email protected]?subject=Ruby" + # + # m2 = Gem::URI::MailTo.build(['[email protected]', [['Subject', 'Ruby'], ['Cc', '[email protected]']]]) + # m2.to_s # => "mailto:[email protected]?Subject=Ruby&[email protected]" + # + # m3 = Gem::URI::MailTo.build({:to => '[email protected]', :headers => [['subject', 'subscribe']]}) + # m3.to_s # => "mailto:[email protected]?subject=subscribe" + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + + case tmp[:to] + when Array + tmp[:opaque] = tmp[:to].join(',') + when String + tmp[:opaque] = tmp[:to].dup + else + tmp[:opaque] = '' + end + + if tmp[:headers] + query = + case tmp[:headers] + when Array + tmp[:headers].collect { |x| + if x.kind_of?(Array) + x[0] + '=' + x[1..-1].join + else + x.to_s + end + }.join('&') + when Hash + tmp[:headers].collect { |h,v| + h + '=' + v + }.join('&') + else + tmp[:headers].to_s + end + unless query.empty? + tmp[:opaque] << '?' << query + end + end + + super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::MailTo object from generic URL components with + # no syntax checking. + # + # This method is usually called from Gem::URI::parse, which checks + # the validity of each component. + # + def initialize(*arg) + super(*arg) + + @to = nil + @headers = [] + + # The RFC3986 parser does not normally populate opaque + @opaque = "?#{@query}" if @query && !@opaque + + unless @opaque + raise InvalidComponentError, + "missing opaque part for mailto URL" + end + to, header = @opaque.split('?', 2) + # allow semicolon as a addr-spec separator + # http://support.microsoft.com/kb/820868 + unless /\A(?:[^@,;]+@[^@,;]+(?:\z|[,;]))*\z/ =~ to + raise InvalidComponentError, + "unrecognised opaque part for mailtoURL: #{@opaque}" + end + + if arg[10] # arg_check + self.to = to + self.headers = header + else + set_to(to) + set_headers(header) + end + end + + # The primary e-mail address of the URL, as a String. + attr_reader :to + + # E-mail headers set by the URL, as an Array of Arrays. + attr_reader :headers + + # Checks the to +v+ component. + def check_to(v) + return true unless v + return true if v.size == 0 + + v.split(/[,;]/).each do |addr| + # check url safety as path-rootless + if /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*\z/ !~ addr + raise InvalidComponentError, + "an address in 'to' is invalid as Gem::URI #{addr.dump}" + end + + # check addr-spec + # don't s/\+/ /g + addr.gsub!(/%\h\h/, Gem::URI::TBLDECWWWCOMP_) + if EMAIL_REGEXP !~ addr + raise InvalidComponentError, + "an address in 'to' is invalid as uri-escaped addr-spec #{addr.dump}" + end + end + + true + end + private :check_to + + # Private setter for to +v+. + def set_to(v) + @to = v + end + protected :set_to + + # Setter for to +v+. + def to=(v) + check_to(v) + set_to(v) + v + end + + # Checks the headers +v+ component against either + # * HEADER_REGEXP + def check_headers(v) + return true unless v + return true if v.size == 0 + if HEADER_REGEXP !~ v + raise InvalidComponentError, + "bad component(expected opaque component): #{v}" + end + + true + end + private :check_headers + + # Private setter for headers +v+. + def set_headers(v) + @headers = [] + if v + v.split('&').each do |x| + @headers << x.split(/=/, 2) + end + end + end + protected :set_headers + + # Setter for headers +v+. + def headers=(v) + check_headers(v) + set_headers(v) + v + end + + # Constructs String from Gem::URI. + def to_s + @scheme + ':' + + if @to + @to + else + '' + end + + if @headers.size > 0 + '?' + @headers.collect{|x| x.join('=')}.join('&') + else + '' + end + + if @fragment + '#' + @fragment + else + '' + end + end + + # Returns the RFC822 e-mail text equivalent of the URL, as a String. + # + # Example: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("mailto:[email protected]?Subject=subscribe&cc=myaddr") + # uri.to_mailtext + # # => "To: [email protected]\nSubject: subscribe\nCc: myaddr\n\n\n" + # + def to_mailtext + to = Gem::URI.decode_www_form_component(@to) + head = '' + body = '' + @headers.each do |x| + case x[0] + when 'body' + body = Gem::URI.decode_www_form_component(x[1]) + when 'to' + to << ', ' + Gem::URI.decode_www_form_component(x[1]) + else + head << Gem::URI.decode_www_form_component(x[0]).capitalize + ': ' + + Gem::URI.decode_www_form_component(x[1]) + "\n" + end + end + + "To: #{to} +#{head} +#{body} +" + end + alias to_rfc822text to_mailtext + end + + register_scheme 'MAILTO', MailTo +end diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb new file mode 100644 index 0000000000..735a269f2c --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb @@ -0,0 +1,539 @@ +# frozen_string_literal: false +#-- +# = uri/common.rb +# +# Author:: Akira Yamada <[email protected]> +# License:: +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +module Gem::URI + # + # Includes Gem::URI::REGEXP::PATTERN + # + module RFC2396_REGEXP + # + # Patterns used to parse Gem::URI's + # + module PATTERN + # :stopdoc: + + # RFC 2396 (Gem::URI Generic Syntax) + # RFC 2732 (IPv6 Literal Addresses in URL's) + # RFC 2373 (IPv6 Addressing Architecture) + + # alpha = lowalpha | upalpha + ALPHA = "a-zA-Z" + # alphanum = alpha | digit + ALNUM = "#{ALPHA}\\d" + + # hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | + # "a" | "b" | "c" | "d" | "e" | "f" + HEX = "a-fA-F\\d" + # escaped = "%" hex hex + ESCAPED = "%[#{HEX}]{2}" + # mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | + # "(" | ")" + # unreserved = alphanum | mark + UNRESERVED = "\\-_.!~*'()#{ALNUM}" + # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + # "$" | "," + # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + # "$" | "," | "[" | "]" (RFC 2732) + RESERVED = ";/?:@&=+$,\\[\\]" + + # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)" + # toplabel = alpha | alpha *( alphanum | "-" ) alphanum + TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)" + # hostname = *( domainlabel "." ) toplabel [ "." ] + HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?" + + # :startdoc: + end # PATTERN + + # :startdoc: + end # REGEXP + + # Class that parses String's into Gem::URI's. + # + # It contains a Hash set of patterns and Regexp's that match and validate. + # + class RFC2396_Parser + include RFC2396_REGEXP + + # + # == Synopsis + # + # Gem::URI::Parser.new([opts]) + # + # == Args + # + # The constructor accepts a hash as options for parser. + # Keys of options are pattern names of Gem::URI components + # and values of options are pattern strings. + # The constructor generates set of regexps for parsing URIs. + # + # You can use the following keys: + # + # * :ESCAPED (Gem::URI::PATTERN::ESCAPED in default) + # * :UNRESERVED (Gem::URI::PATTERN::UNRESERVED in default) + # * :DOMLABEL (Gem::URI::PATTERN::DOMLABEL in default) + # * :TOPLABEL (Gem::URI::PATTERN::TOPLABEL in default) + # * :HOSTNAME (Gem::URI::PATTERN::HOSTNAME in default) + # + # == Examples + # + # p = Gem::URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})") + # u = p.parse("http://example.jp/%uABCD") #=> #<Gem::URI::HTTP http://example.jp/%uABCD> + # Gem::URI.parse(u.to_s) #=> raises Gem::URI::InvalidURIError + # + # s = "http://example.com/ABCD" + # u1 = p.parse(s) #=> #<Gem::URI::HTTP http://example.com/ABCD> + # u2 = Gem::URI.parse(s) #=> #<Gem::URI::HTTP http://example.com/ABCD> + # u1 == u2 #=> true + # u1.eql?(u2) #=> false + # + def initialize(opts = {}) + @pattern = initialize_pattern(opts) + @pattern.each_value(&:freeze) + @pattern.freeze + + @regexp = initialize_regexp(@pattern) + @regexp.each_value(&:freeze) + @regexp.freeze + end + + # The Hash of patterns. + # + # See also Gem::URI::Parser.initialize_pattern. + attr_reader :pattern + + # The Hash of Regexp. + # + # See also Gem::URI::Parser.initialize_regexp. + attr_reader :regexp + + # Returns a split Gem::URI against +regexp[:ABS_URI]+. + def split(uri) + case uri + when '' + # null uri + + when @regexp[:ABS_URI] + scheme, opaque, userinfo, host, port, + registry, path, query, fragment = $~[1..-1] + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + # opaque_part = uric_no_slash *uric + + # abs_path = "/" path_segments + # net_path = "//" authority [ abs_path ] + + # authority = server | reg_name + # server = [ [ userinfo "@" ] hostport ] + + if !scheme + raise InvalidURIError, + "bad Gem::URI(absolute but no scheme): #{uri}" + end + if !opaque && (!path && (!host && !registry)) + raise InvalidURIError, + "bad Gem::URI(absolute but no path): #{uri}" + end + + when @regexp[:REL_URI] + scheme = nil + opaque = nil + + userinfo, host, port, registry, + rel_segment, abs_path, query, fragment = $~[1..-1] + if rel_segment && abs_path + path = rel_segment + abs_path + elsif rel_segment + path = rel_segment + elsif abs_path + path = abs_path + end + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + + # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + + # net_path = "//" authority [ abs_path ] + # abs_path = "/" path_segments + # rel_path = rel_segment [ abs_path ] + + # authority = server | reg_name + # server = [ [ userinfo "@" ] hostport ] + + else + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri}" + end + + path = '' if !path && !opaque # (see RFC2396 Section 5.2) + ret = [ + scheme, + userinfo, host, port, # X + registry, # X + path, # Y + opaque, # Y + query, + fragment + ] + return ret + end + + # + # == Args + # + # +uri+:: + # String + # + # == Description + # + # Parses +uri+ and constructs either matching Gem::URI scheme object + # (File, FTP, HTTP, HTTPS, LDAP, LDAPS, or MailTo) or Gem::URI::Generic. + # + # == Usage + # + # p = Gem::URI::Parser.new + # p.parse("ldap://ldap.example.com/dc=example?user=john") + # #=> #<Gem::URI::LDAP ldap://ldap.example.com/dc=example?user=john> + # + def parse(uri) + Gem::URI.for(*self.split(uri), self) + end + + # + # == Args + # + # +uris+:: + # an Array of Strings + # + # == Description + # + # Attempts to parse and merge a set of URIs. + # + def join(*uris) + uris[0] = convert_to_uri(uris[0]) + uris.inject :merge + end + + # + # :call-seq: + # extract( str ) + # extract( str, schemes ) + # extract( str, schemes ) {|item| block } + # + # == Args + # + # +str+:: + # String to search + # +schemes+:: + # Patterns to apply to +str+ + # + # == Description + # + # Attempts to parse and merge a set of URIs. + # If no +block+ given, then returns the result, + # else it calls +block+ for each element in result. + # + # See also Gem::URI::Parser.make_regexp. + # + def extract(str, schemes = nil) + if block_given? + str.scan(make_regexp(schemes)) { yield $& } + nil + else + result = [] + str.scan(make_regexp(schemes)) { result.push $& } + result + end + end + + # Returns Regexp that is default +self.regexp[:ABS_URI_REF]+, + # unless +schemes+ is provided. Then it is a Regexp.union with +self.pattern[:X_ABS_URI]+. + def make_regexp(schemes = nil) + unless schemes + @regexp[:ABS_URI_REF] + else + /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x + end + end + + # + # :call-seq: + # escape( str ) + # escape( str, unsafe ) + # + # == Args + # + # +str+:: + # String to make safe + # +unsafe+:: + # Regexp to apply. Defaults to +self.regexp[:UNSAFE]+ + # + # == Description + # + # Constructs a safe String from +str+, removing unsafe characters, + # replacing them with codes. + # + def escape(str, unsafe = @regexp[:UNSAFE]) + unless unsafe.kind_of?(Regexp) + # perhaps unsafe is String object + unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false) + end + str.gsub(unsafe) do + us = $& + tmp = '' + us.each_byte do |uc| + tmp << sprintf('%%%02X', uc) + end + tmp + end.force_encoding(Encoding::US_ASCII) + end + + # + # :call-seq: + # unescape( str ) + # unescape( str, escaped ) + # + # == Args + # + # +str+:: + # String to remove escapes from + # +escaped+:: + # Regexp to apply. Defaults to +self.regexp[:ESCAPED]+ + # + # == Description + # + # Removes escapes from +str+. + # + def unescape(str, escaped = @regexp[:ESCAPED]) + enc = str.encoding + enc = Encoding::UTF_8 if enc == Encoding::US_ASCII + str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) } + end + + @@to_s = Kernel.instance_method(:to_s) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end + end + + private + + # Constructs the default Hash of patterns. + def initialize_pattern(opts = {}) + ret = {} + ret[:ESCAPED] = escaped = (opts.delete(:ESCAPED) || PATTERN::ESCAPED) + ret[:UNRESERVED] = unreserved = opts.delete(:UNRESERVED) || PATTERN::UNRESERVED + ret[:RESERVED] = reserved = opts.delete(:RESERVED) || PATTERN::RESERVED + ret[:DOMLABEL] = opts.delete(:DOMLABEL) || PATTERN::DOMLABEL + ret[:TOPLABEL] = opts.delete(:TOPLABEL) || PATTERN::TOPLABEL + ret[:HOSTNAME] = hostname = opts.delete(:HOSTNAME) + + # RFC 2396 (Gem::URI Generic Syntax) + # RFC 2732 (IPv6 Literal Addresses in URL's) + # RFC 2373 (IPv6 Addressing Architecture) + + # uric = reserved | unreserved | escaped + ret[:URIC] = uric = "(?:[#{unreserved}#{reserved}]|#{escaped})" + # uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | + # "&" | "=" | "+" | "$" | "," + ret[:URIC_NO_SLASH] = uric_no_slash = "(?:[#{unreserved};?:@&=+$,]|#{escaped})" + # query = *uric + ret[:QUERY] = query = "#{uric}*" + # fragment = *uric + ret[:FRAGMENT] = fragment = "#{uric}*" + + # hostname = *( domainlabel "." ) toplabel [ "." ] + # reg-name = *( unreserved / pct-encoded / sub-delims ) # RFC3986 + unless hostname + ret[:HOSTNAME] = hostname = "(?:[a-zA-Z0-9\\-.]|%\\h\\h)+" + end + + # RFC 2373, APPENDIX B: + # IPv6address = hexpart [ ":" IPv4address ] + # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT + # hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] + # hexseq = hex4 *( ":" hex4) + # hex4 = 1*4HEXDIG + # + # XXX: This definition has a flaw. "::" + IPv4address must be + # allowed too. Here is a replacement. + # + # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT + ret[:IPV4ADDR] = ipv4addr = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}" + # hex4 = 1*4HEXDIG + hex4 = "[#{PATTERN::HEX}]{1,4}" + # lastpart = hex4 | IPv4address + lastpart = "(?:#{hex4}|#{ipv4addr})" + # hexseq1 = *( hex4 ":" ) hex4 + hexseq1 = "(?:#{hex4}:)*#{hex4}" + # hexseq2 = *( hex4 ":" ) lastpart + hexseq2 = "(?:#{hex4}:)*#{lastpart}" + # IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ] + ret[:IPV6ADDR] = ipv6addr = "(?:#{hexseq2}|(?:#{hexseq1})?::(?:#{hexseq2})?)" + + # IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT + # unused + + # ipv6reference = "[" IPv6address "]" (RFC 2732) + ret[:IPV6REF] = ipv6ref = "\\[#{ipv6addr}\\]" + + # host = hostname | IPv4address + # host = hostname | IPv4address | IPv6reference (RFC 2732) + ret[:HOST] = host = "(?:#{hostname}|#{ipv4addr}|#{ipv6ref})" + # port = *digit + ret[:PORT] = port = '\d*' + # hostport = host [ ":" port ] + ret[:HOSTPORT] = hostport = "#{host}(?::#{port})?" + + # userinfo = *( unreserved | escaped | + # ";" | ":" | "&" | "=" | "+" | "$" | "," ) + ret[:USERINFO] = userinfo = "(?:[#{unreserved};:&=+$,]|#{escaped})*" + + # pchar = unreserved | escaped | + # ":" | "@" | "&" | "=" | "+" | "$" | "," + pchar = "(?:[#{unreserved}:@&=+$,]|#{escaped})" + # param = *pchar + param = "#{pchar}*" + # segment = *pchar *( ";" param ) + segment = "#{pchar}*(?:;#{param})*" + # path_segments = segment *( "/" segment ) + ret[:PATH_SEGMENTS] = path_segments = "#{segment}(?:/#{segment})*" + + # server = [ [ userinfo "@" ] hostport ] + server = "(?:#{userinfo}@)?#{hostport}" + # reg_name = 1*( unreserved | escaped | "$" | "," | + # ";" | ":" | "@" | "&" | "=" | "+" ) + ret[:REG_NAME] = reg_name = "(?:[#{unreserved}$,;:@&=+]|#{escaped})+" + # authority = server | reg_name + authority = "(?:#{server}|#{reg_name})" + + # rel_segment = 1*( unreserved | escaped | + # ";" | "@" | "&" | "=" | "+" | "$" | "," ) + ret[:REL_SEGMENT] = rel_segment = "(?:[#{unreserved};@&=+$,]|#{escaped})+" + + # scheme = alpha *( alpha | digit | "+" | "-" | "." ) + ret[:SCHEME] = scheme = "[#{PATTERN::ALPHA}][\\-+.#{PATTERN::ALPHA}\\d]*" + + # abs_path = "/" path_segments + ret[:ABS_PATH] = abs_path = "/#{path_segments}" + # rel_path = rel_segment [ abs_path ] + ret[:REL_PATH] = rel_path = "#{rel_segment}(?:#{abs_path})?" + # net_path = "//" authority [ abs_path ] + ret[:NET_PATH] = net_path = "//#{authority}(?:#{abs_path})?" + + # hier_part = ( net_path | abs_path ) [ "?" query ] + ret[:HIER_PART] = hier_part = "(?:#{net_path}|#{abs_path})(?:\\?(?:#{query}))?" + # opaque_part = uric_no_slash *uric + ret[:OPAQUE_PART] = opaque_part = "#{uric_no_slash}#{uric}*" + + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + ret[:ABS_URI] = abs_uri = "#{scheme}:(?:#{hier_part}|#{opaque_part})" + # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + ret[:REL_URI] = rel_uri = "(?:#{net_path}|#{abs_path}|#{rel_path})(?:\\?#{query})?" + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + ret[:URI_REF] = "(?:#{abs_uri}|#{rel_uri})?(?:##{fragment})?" + + ret[:X_ABS_URI] = " + (#{scheme}): (?# 1: scheme) + (?: + (#{opaque_part}) (?# 2: opaque) + | + (?:(?: + //(?: + (?:(?:(#{userinfo})@)? (?# 3: userinfo) + (?:(#{host})(?::(\\d*))?))? (?# 4: host, 5: port) + | + (#{reg_name}) (?# 6: registry) + ) + | + (?!//)) (?# XXX: '//' is the mark for hostport) + (#{abs_path})? (?# 7: path) + )(?:\\?(#{query}))? (?# 8: query) + ) + (?:\\#(#{fragment}))? (?# 9: fragment) + " + + ret[:X_REL_URI] = " + (?: + (?: + // + (?: + (?:(#{userinfo})@)? (?# 1: userinfo) + (#{host})?(?::(\\d*))? (?# 2: host, 3: port) + | + (#{reg_name}) (?# 4: registry) + ) + ) + | + (#{rel_segment}) (?# 5: rel_segment) + )? + (#{abs_path})? (?# 6: abs_path) + (?:\\?(#{query}))? (?# 7: query) + (?:\\#(#{fragment}))? (?# 8: fragment) + " + + ret + end + + # Constructs the default Hash of Regexp's. + def initialize_regexp(pattern) + ret = {} + + # for Gem::URI::split + ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) + ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) + + # for Gem::URI::extract + ret[:URI_REF] = Regexp.new(pattern[:URI_REF]) + ret[:ABS_URI_REF] = Regexp.new(pattern[:X_ABS_URI], Regexp::EXTENDED) + ret[:REL_URI_REF] = Regexp.new(pattern[:X_REL_URI], Regexp::EXTENDED) + + # for Gem::URI::escape/unescape + ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED]) + ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]") + + # for Generic#initialize + ret[:SCHEME] = Regexp.new("\\A#{pattern[:SCHEME]}\\z") + ret[:USERINFO] = Regexp.new("\\A#{pattern[:USERINFO]}\\z") + ret[:HOST] = Regexp.new("\\A#{pattern[:HOST]}\\z") + ret[:PORT] = Regexp.new("\\A#{pattern[:PORT]}\\z") + ret[:OPAQUE] = Regexp.new("\\A#{pattern[:OPAQUE_PART]}\\z") + ret[:REGISTRY] = Regexp.new("\\A#{pattern[:REG_NAME]}\\z") + ret[:ABS_PATH] = Regexp.new("\\A#{pattern[:ABS_PATH]}\\z") + ret[:REL_PATH] = Regexp.new("\\A#{pattern[:REL_PATH]}\\z") + ret[:QUERY] = Regexp.new("\\A#{pattern[:QUERY]}\\z") + ret[:FRAGMENT] = Regexp.new("\\A#{pattern[:FRAGMENT]}\\z") + + ret + end + + def convert_to_uri(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + + end # class Parser +end # module Gem::URI diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb new file mode 100644 index 0000000000..728bb55674 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb @@ -0,0 +1,183 @@ +# frozen_string_literal: true +module Gem::URI + class RFC3986_Parser # :nodoc: + # Gem::URI defined in RFC3986 + HOST = %r[ + (?<IP-literal>\[(?: + (?<IPv6address> + (?:\h{1,4}:){6} + (?<ls32>\h{1,4}:\h{1,4} + | (?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d) + \.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>) + ) + | ::(?:\h{1,4}:){5}\g<ls32> + | \h{1,4}?::(?:\h{1,4}:){4}\g<ls32> + | (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32> + | (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32> + | (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32> + | (?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32> + | (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4} + | (?:(?:\h{1,4}:){,6}\h{1,4})?:: + ) + | (?<IPvFuture>v\h++\.[!$&-.0-9:;=A-Z_a-z~]++) + )\]) + | \g<IPv4address> + | (?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+) + ]x + + USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/ + + SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source + SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source + SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source + FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source + + RFC3986_URI = %r[\A + (?<seg>#{SEG}){0} + (?<Gem::URI> + (?<scheme>#{SCHEME}): + (?<hier-part>// + (?<authority> + (?:(?<userinfo>#{USERINFO.source})@)? + (?<host>#{HOST.source.delete(" \n")}) + (?::(?<port>\d*+))? + ) + (?<path-abempty>(?:/\g<seg>*+)?) + | (?<path-absolute>/((?!/)\g<seg>++)?) + | (?<path-rootless>(?!/)\g<seg>++) + | (?<path-empty>) + ) + (?:\?(?<query>[^\#]*+))? + (?:\#(?<fragment>#{FRAGMENT}))? + )\z]x + + RFC3986_relative_ref = %r[\A + (?<seg>#{SEG}){0} + (?<relative-ref> + (?<relative-part>// + (?<authority> + (?:(?<userinfo>#{USERINFO.source})@)? + (?<host>#{HOST.source.delete(" \n")}(?<!/))? + (?::(?<port>\d*+))? + ) + (?<path-abempty>(?:/\g<seg>*+)?) + | (?<path-absolute>/\g<seg>*+) + | (?<path-noscheme>#{SEG_NC}++(?:/\g<seg>*+)?) + | (?<path-empty>) + ) + (?:\?(?<query>[^#]*+))? + (?:\#(?<fragment>#{FRAGMENT}))? + )\z]x + attr_reader :regexp + + def initialize + @regexp = default_regexp.each_value(&:freeze).freeze + end + + def split(uri) #:nodoc: + begin + uri = uri.to_str + rescue NoMethodError + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}" + end + uri.ascii_only? or + raise InvalidURIError, "Gem::URI must be ascii only #{uri.dump}" + if m = RFC3986_URI.match(uri) + query = m["query"] + scheme = m["scheme"] + opaque = m["path-rootless"] + if opaque + opaque << "?#{query}" if query + [ scheme, + nil, # userinfo + nil, # host + nil, # port + nil, # registry + nil, # path + opaque, + nil, # query + m["fragment"] + ] + else # normal + [ scheme, + m["userinfo"], + m["host"], + m["port"], + nil, # registry + (m["path-abempty"] || + m["path-absolute"] || + m["path-empty"]), + nil, # opaque + query, + m["fragment"] + ] + end + elsif m = RFC3986_relative_ref.match(uri) + [ nil, # scheme + m["userinfo"], + m["host"], + m["port"], + nil, # registry, + (m["path-abempty"] || + m["path-absolute"] || + m["path-noscheme"] || + m["path-empty"]), + nil, # opaque + m["query"], + m["fragment"] + ] + else + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}" + end + end + + def parse(uri) # :nodoc: + Gem::URI.for(*self.split(uri), self) + end + + + def join(*uris) # :nodoc: + uris[0] = convert_to_uri(uris[0]) + uris.inject :merge + end + + @@to_s = Kernel.instance_method(:to_s) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end + end + + private + + def default_regexp # :nodoc: + { + SCHEME: %r[\A#{SCHEME}\z]o, + USERINFO: %r[\A#{USERINFO}\z]o, + HOST: %r[\A#{HOST}\z]o, + ABS_PATH: %r[\A/#{SEG}*+\z]o, + REL_PATH: %r[\A(?!/)#{SEG}++\z]o, + QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z], + FRAGMENT: %r[\A#{FRAGMENT}\z]o, + OPAQUE: %r[\A(?:[^/].*)?\z], + PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/, + } + end + + def convert_to_uri(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + + end # class Parser +end # module Gem::URI diff --git a/lib/rubygems/vendor/uri/lib/uri/version.rb b/lib/rubygems/vendor/uri/lib/uri/version.rb new file mode 100644 index 0000000000..3c80c334d4 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/version.rb @@ -0,0 +1,6 @@ +module Gem::URI + # :stopdoc: + VERSION_CODE = '001300'.freeze + VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze + # :startdoc: +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ws.rb b/lib/rubygems/vendor/uri/lib/uri/ws.rb new file mode 100644 index 0000000000..0dd2a7a1bb --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ws.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: false +# = uri/ws.rb +# +# Author:: Matt Muller <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # The syntax of WS URIs is defined in RFC6455 section 3. + # + # Note that the Ruby Gem::URI library allows WS URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See <URL:http://support.microsoft.com/kb/834489>. + # + class WS < Generic + # A Default port of 80 for Gem::URI::WS. + DEFAULT_PORT = 80 + + # An Array of the available components for Gem::URI::WS. + COMPONENT = %i[ + scheme + userinfo host port + path + query + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::WS object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, and query. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order <code>[userinfo, host, port, path, query]</code>. + # + # Example: + # + # uri = Gem::URI::WS.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = Gem::URI::WS.build([nil, "www.example.com", nil, "/path", "query"]) + # + # Currently, if passed userinfo components this method generates + # invalid WS URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for a WS Gem::URI, as required by Net::HTTP::Get. + # + # If the Gem::URI contains a query, the full path is Gem::URI#path + '?' + Gem::URI#query. + # Otherwise, the path is simply Gem::URI#path. + # + # Example: + # + # uri = Gem::URI::WS.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + end + + register_scheme 'WS', WS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/wss.rb b/lib/rubygems/vendor/uri/lib/uri/wss.rb new file mode 100644 index 0000000000..0b91d334bb --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/wss.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: false +# = uri/wss.rb +# +# Author:: Matt Muller <[email protected]> +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'ws' + +module Gem::URI + + # The default port for WSS URIs is 443, and the scheme is 'wss:' rather + # than 'ws:'. Other than that, WSS URIs are identical to WS URIs; + # see Gem::URI::WS. + class WSS < WS + # A Default port of 443 for Gem::URI::WSS + DEFAULT_PORT = 443 + end + + register_scheme 'WSS', WSS +end diff --git a/lib/rubygems/vendored_molinillo.rb b/lib/rubygems/vendored_molinillo.rb new file mode 100644 index 0000000000..45906c0e5c --- /dev/null +++ b/lib/rubygems/vendored_molinillo.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "vendor/molinillo/lib/molinillo" diff --git a/lib/rubygems/vendored_net_http.rb b/lib/rubygems/vendored_net_http.rb new file mode 100644 index 0000000000..a84c52a947 --- /dev/null +++ b/lib/rubygems/vendored_net_http.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby 3.3 and RubyGems 3.5 is already load Gem::Timeout from lib/rubygems/net/http.rb +# We should avoid to load it again +require_relative "vendor/net-http/lib/net/http" unless defined?(Gem::Net::HTTP) diff --git a/lib/rubygems/vendored_optparse.rb b/lib/rubygems/vendored_optparse.rb new file mode 100644 index 0000000000..a5611d32f0 --- /dev/null +++ b/lib/rubygems/vendored_optparse.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "vendor/optparse/lib/optparse" diff --git a/lib/rubygems/vendored_timeout.rb b/lib/rubygems/vendored_timeout.rb new file mode 100644 index 0000000000..45541928e6 --- /dev/null +++ b/lib/rubygems/vendored_timeout.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby 3.3 and RubyGems 3.5 is already load Gem::Timeout from lib/rubygems/timeout.rb +# We should avoid to load it again +require_relative "vendor/timeout/lib/timeout" unless defined?(Gem::Timeout) diff --git a/lib/rubygems/vendored_tsort.rb b/lib/rubygems/vendored_tsort.rb new file mode 100644 index 0000000000..c3d815650d --- /dev/null +++ b/lib/rubygems/vendored_tsort.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "vendor/tsort/lib/tsort" diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index 947fda0911..128becc1ce 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -58,6 +58,8 @@ module Gem str.split(/\r?\n/) do |line| if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures + val = strip_comment(val) + convert_to_backward_compatible_key!(key) depth = indent.size / 2 if quote.empty? && val.empty? @@ -72,6 +74,8 @@ module Gem end elsif match = ARRAY_REGEX.match(line) _, val = match.captures + val = strip_comment(val) + last_hash[last_empty_key] = [] unless last_hash[last_empty_key].is_a?(Array) last_hash[last_empty_key].push(val) @@ -80,6 +84,14 @@ module Gem res end + def strip_comment(val) + if val.include?("#") && !val.start_with?("#") + val.split("#", 2).first.strip + else + val + end + end + # for settings' keys def convert_to_backward_compatible_key!(key) key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) |