summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base64.gemspec2
-rw-r--r--lib/base64.rb6
-rw-r--r--lib/benchmark/version.rb2
-rw-r--r--lib/bundler.rb32
-rw-r--r--lib/bundler/cli.rb15
-rw-r--r--lib/bundler/cli/exec.rb7
-rw-r--r--lib/bundler/cli/gem.rb36
-rw-r--r--lib/bundler/cli/info.rb15
-rw-r--r--lib/bundler/cli/install.rb12
-rw-r--r--lib/bundler/cli/list.rb8
-rw-r--r--lib/bundler/cli/remove.rb3
-rw-r--r--lib/bundler/definition.rb66
-rw-r--r--lib/bundler/dsl.rb2
-rw-r--r--lib/bundler/endpoint_specification.rb8
-rw-r--r--lib/bundler/errors.rb2
-rw-r--r--lib/bundler/fetcher.rb3
-rw-r--r--lib/bundler/gem_helper.rb21
-rw-r--r--lib/bundler/gemdeps.rb29
-rw-r--r--lib/bundler/installer.rb4
-rw-r--r--lib/bundler/installer/standalone.rb21
-rw-r--r--lib/bundler/lockfile_parser.rb1
-rw-r--r--lib/bundler/man/bundle-add.12
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.12
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.12
-rw-r--r--lib/bundler/man/bundle-config.14
-rw-r--r--lib/bundler/man/bundle-config.1.ronn4
-rw-r--r--lib/bundler/man/bundle-doctor.12
-rw-r--r--lib/bundler/man/bundle-exec.12
-rw-r--r--lib/bundler/man/bundle-gem.12
-rw-r--r--lib/bundler/man/bundle-info.12
-rw-r--r--lib/bundler/man/bundle-init.12
-rw-r--r--lib/bundler/man/bundle-inject.12
-rw-r--r--lib/bundler/man/bundle-install.14
-rw-r--r--lib/bundler/man/bundle-install.1.ronn4
-rw-r--r--lib/bundler/man/bundle-list.12
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.12
-rw-r--r--lib/bundler/man/bundle-outdated.12
-rw-r--r--lib/bundler/man/bundle-platform.12
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.14
-rw-r--r--lib/bundler/man/bundle-update.1.ronn3
-rw-r--r--lib/bundler/man/bundle-viz.12
-rw-r--r--lib/bundler/man/bundle.12
-rw-r--r--lib/bundler/man/gemfile.52
-rw-r--r--lib/bundler/plugin.rb29
-rw-r--r--lib/bundler/plugin/installer.rb2
-rw-r--r--lib/bundler/psyched_yaml.rb14
-rw-r--r--lib/bundler/resolver.rb27
-rw-r--r--lib/bundler/rubygems_ext.rb4
-rw-r--r--lib/bundler/rubygems_integration.rb18
-rw-r--r--lib/bundler/runtime.rb23
-rw-r--r--lib/bundler/settings.rb14
-rw-r--r--lib/bundler/setup.rb4
-rw-r--r--lib/bundler/source.rb4
-rw-r--r--lib/bundler/source/git.rb22
-rw-r--r--lib/bundler/source/rubygems.rb35
-rw-r--r--lib/bundler/source/rubygems_aggregate.rb4
-rw-r--r--lib/bundler/source_list.rb15
-rw-r--r--lib/bundler/spec_set.rb48
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt15
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt4
-rw-r--r--lib/cgi.rb2
-rw-r--r--lib/cgi/util.rb11
-rw-r--r--lib/debug.gemspec22
-rw-r--r--lib/debug.rb1106
-rw-r--r--lib/drb/drb.gemspec4
-rw-r--r--lib/drb/version.rb2
-rw-r--r--lib/error_highlight/base.rb20
-rw-r--r--lib/error_highlight/core_ext.rb2
-rw-r--r--lib/fileutils.rb12
-rw-r--r--lib/find.gemspec2
-rw-r--r--lib/ipaddr.rb132
-rw-r--r--lib/irb.rb17
-rw-r--r--lib/irb/cmd/help.rb3
-rw-r--r--lib/irb/cmd/show_source.rb5
-rw-r--r--lib/irb/completion.rb74
-rw-r--r--lib/irb/context.rb46
-rw-r--r--lib/irb/init.rb9
-rw-r--r--lib/irb/input-method.rb99
-rw-r--r--lib/irb/irb.gemspec2
-rw-r--r--lib/irb/lc/help-message11
-rw-r--r--lib/irb/lc/ja/help-message2
-rw-r--r--lib/irb/ruby-lex.rb38
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb3
-rw-r--r--lib/logger/logger.gemspec2
-rw-r--r--lib/logger/version.rb2
-rw-r--r--lib/mkmf.rb29
-rw-r--r--lib/open-uri.gemspec2
-rw-r--r--lib/ostruct.rb12
-rw-r--r--lib/racc/info.rb2
-rw-r--r--lib/racc/racc.gemspec2
-rw-r--r--lib/rdoc/any_method.rb5
-rw-r--r--lib/rdoc/cross_reference.rb2
-rw-r--r--lib/rdoc/generator/darkfish.rb4
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml4
-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttfbin71200 -> 138268 bytes
-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttfbin71692 -> 138680 bytes
-rw-r--r--lib/rdoc/markdown.rb79
-rw-r--r--lib/rdoc/markdown/literals.rb15
-rw-r--r--lib/rdoc/markup/pre_process.rb2
-rw-r--r--lib/rdoc/options.rb31
-rw-r--r--lib/rdoc/parser/c.rb30
-rw-r--r--lib/rdoc/rd/block_parser.rb2
-rw-r--r--lib/rdoc/rd/inline_parser.rb2
-rw-r--r--lib/rdoc/rdoc.gemspec1
-rw-r--r--lib/rdoc/rdoc.rb33
-rw-r--r--lib/rdoc/text.rb16
-rw-r--r--lib/reline.rb138
-rw-r--r--lib/reline/ansi.rb23
-rw-r--r--lib/reline/config.rb32
-rw-r--r--lib/reline/general_io.rb1
-rw-r--r--lib/reline/key_stroke.rb77
-rw-r--r--lib/reline/line_editor.rb640
-rw-r--r--lib/reline/terminfo.rb30
-rw-r--r--lib/reline/unicode.rb35
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/reline/windows.rb88
-rw-r--r--lib/rubygems.rb72
-rw-r--r--lib/rubygems/command_manager.rb6
-rw-r--r--lib/rubygems/commands/build_command.rb6
-rw-r--r--lib/rubygems/commands/cert_command.rb4
-rw-r--r--lib/rubygems/commands/check_command.rb8
-rw-r--r--lib/rubygems/commands/cleanup_command.rb6
-rw-r--r--lib/rubygems/commands/contents_command.rb4
-rw-r--r--lib/rubygems/commands/dependency_command.rb6
-rw-r--r--lib/rubygems/commands/environment_command.rb2
-rw-r--r--lib/rubygems/commands/fetch_command.rb6
-rw-r--r--lib/rubygems/commands/generate_index_command.rb4
-rw-r--r--lib/rubygems/commands/help_command.rb2
-rw-r--r--lib/rubygems/commands/info_command.rb4
-rw-r--r--lib/rubygems/commands/install_command.rb23
-rw-r--r--lib/rubygems/commands/list_command.rb4
-rw-r--r--lib/rubygems/commands/lock_command.rb2
-rw-r--r--lib/rubygems/commands/mirror_command.rb2
-rw-r--r--lib/rubygems/commands/open_command.rb4
-rw-r--r--lib/rubygems/commands/outdated_command.rb8
-rw-r--r--lib/rubygems/commands/owner_command.rb8
-rw-r--r--lib/rubygems/commands/pristine_command.rb10
-rw-r--r--lib/rubygems/commands/push_command.rb8
-rw-r--r--lib/rubygems/commands/query_command.rb6
-rw-r--r--lib/rubygems/commands/rdoc_command.rb6
-rw-r--r--lib/rubygems/commands/search_command.rb4
-rw-r--r--lib/rubygems/commands/server_command.rb6
-rw-r--r--lib/rubygems/commands/setup_command.rb28
-rw-r--r--lib/rubygems/commands/signin_command.rb4
-rw-r--r--lib/rubygems/commands/signout_command.rb2
-rw-r--r--lib/rubygems/commands/sources_command.rb8
-rw-r--r--lib/rubygems/commands/specification_command.rb8
-rw-r--r--lib/rubygems/commands/stale_command.rb2
-rw-r--r--lib/rubygems/commands/uninstall_command.rb6
-rw-r--r--lib/rubygems/commands/unpack_command.rb10
-rw-r--r--lib/rubygems/commands/update_command.rb18
-rw-r--r--lib/rubygems/commands/which_command.rb2
-rw-r--r--lib/rubygems/commands/yank_command.rb8
-rw-r--r--lib/rubygems/config_file.rb2
-rw-r--r--lib/rubygems/defaults.rb24
-rw-r--r--lib/rubygems/dependency_installer.rb16
-rw-r--r--lib/rubygems/dependency_list.rb2
-rw-r--r--lib/rubygems/doctor.rb4
-rw-r--r--lib/rubygems/errors.rb3
-rw-r--r--lib/rubygems/exceptions.rb4
-rw-r--r--lib/rubygems/gem_runner.rb6
-rw-r--r--lib/rubygems/gemcutter_utilities.rb4
-rw-r--r--lib/rubygems/indexer.rb4
-rw-r--r--lib/rubygems/install_default_message.rb4
-rw-r--r--lib/rubygems/install_message.rb4
-rw-r--r--lib/rubygems/install_update_options.rb4
-rw-r--r--lib/rubygems/installer.rb25
-rw-r--r--lib/rubygems/local_remote_options.rb2
-rw-r--r--lib/rubygems/mock_gem_ui.rb2
-rw-r--r--lib/rubygems/name_tuple.rb5
-rw-r--r--lib/rubygems/package.rb82
-rw-r--r--lib/rubygems/package/tar_reader.rb2
-rw-r--r--lib/rubygems/package_task.rb4
-rw-r--r--lib/rubygems/path_support.rb7
-rw-r--r--lib/rubygems/platform.rb7
-rw-r--r--lib/rubygems/query_utils.rb8
-rw-r--r--lib/rubygems/rdoc.rb2
-rw-r--r--lib/rubygems/remote_fetcher.rb33
-rw-r--r--lib/rubygems/request.rb12
-rw-r--r--lib/rubygems/request_set.rb8
-rw-r--r--lib/rubygems/request_set/lockfile.rb2
-rw-r--r--lib/rubygems/request_set/lockfile/tokenizer.rb2
-rw-r--r--lib/rubygems/requirement.rb2
-rw-r--r--lib/rubygems/resolver.rb62
-rw-r--r--lib/rubygems/resolver/git_specification.rb2
-rw-r--r--lib/rubygems/resolver/installer_set.rb8
-rw-r--r--lib/rubygems/resolver/molinillo.rb2
-rw-r--r--lib/rubygems/resolver/set.rb1
-rw-r--r--lib/rubygems/resolver/specification.rb2
-rw-r--r--lib/rubygems/s3_uri_signer.rb6
-rw-r--r--lib/rubygems/security.rb10
-rw-r--r--lib/rubygems/security/policy.rb2
-rw-r--r--lib/rubygems/security/signer.rb2
-rw-r--r--lib/rubygems/security_option.rb4
-rw-r--r--lib/rubygems/server.rb4
-rw-r--r--lib/rubygems/source.rb14
-rw-r--r--lib/rubygems/spec_fetcher.rb10
-rw-r--r--lib/rubygems/specification.rb26
-rw-r--r--lib/rubygems/specification_policy.rb4
-rw-r--r--lib/rubygems/uninstaller.rb12
-rw-r--r--lib/rubygems/uri.rb111
-rw-r--r--lib/rubygems/uri_parser.rb42
-rw-r--r--lib/rubygems/user_interaction.rb4
-rw-r--r--lib/rubygems/util.rb2
-rw-r--r--lib/rubygems/util/licenses.rb2
-rw-r--r--lib/rubygems/validator.rb4
-rw-r--r--lib/rubygems/version_option.rb2
-rw-r--r--lib/securerandom.rb2
-rw-r--r--lib/set.rb11
-rw-r--r--lib/tempfile.gemspec2
-rw-r--r--lib/tempfile.rb6
-rw-r--r--lib/time.gemspec2
-rw-r--r--lib/timeout.rb2
-rw-r--r--lib/un.gemspec5
-rw-r--r--lib/un.rb39
-rw-r--r--lib/yaml/yaml.gemspec2
223 files changed, 2320 insertions, 2307 deletions
diff --git a/lib/base64.gemspec b/lib/base64.gemspec
index 1863a3fd3d..daa0b7fa14 100644
--- a/lib/base64.gemspec
+++ b/lib/base64.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "base64"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Yusuke Endoh"]
spec.email = ["mame@ruby-lang.org"]
diff --git a/lib/base64.rb b/lib/base64.rb
index 5c8df841f1..693aa1f519 100644
--- a/lib/base64.rb
+++ b/lib/base64.rb
@@ -82,8 +82,8 @@ module Base64
# You can remove the padding by setting +padding+ as false.
def urlsafe_encode64(bin, padding: true)
str = strict_encode64(bin)
+ str.chomp!("==") or str.chomp!("=") unless padding
str.tr!("+/", "-_")
- str.delete!("=") unless padding
str
end
@@ -99,9 +99,11 @@ module Base64
# NOTE: RFC 4648 does say nothing about unpadded input, but says that
# "the excess pad characters MAY also be ignored", so it is inferred that
# unpadded input is also acceptable.
- str = str.tr("-_", "+/")
if !str.end_with?("=") && str.length % 4 != 0
str = str.ljust((str.length + 3) & ~3, "=")
+ str.tr!("-_", "+/")
+ else
+ str = str.tr("-_", "+/")
end
strict_decode64(str)
end
diff --git a/lib/benchmark/version.rb b/lib/benchmark/version.rb
index 90d1a3900c..90ae2754e4 100644
--- a/lib/benchmark/version.rb
+++ b/lib/benchmark/version.rb
@@ -1,3 +1,3 @@
module Benchmark
- VERSION = "0.1.1"
+ VERSION = "0.2.0"
end
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 791831d0e7..f2d874bdf3 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -636,15 +636,19 @@ EOF
@rubygems = nil
end
+ def configure_gem_home_and_path(path = bundle_path)
+ configure_gem_path
+ configure_gem_home(path)
+ Bundler.rubygems.clear_paths
+ end
+
private
def eval_yaml_gemspec(path, contents)
require_relative "bundler/psyched_yaml"
- # If the YAML is invalid, Syck raises an ArgumentError, and Psych
- # raises a Psych::SyntaxError. See psyched_yaml.rb for more info.
Gem::Specification.from_yaml(contents)
- rescue YamlLibrarySyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
+ rescue ::Psych::SyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
eval_gemspec(path, contents)
end
@@ -656,29 +660,17 @@ EOF
raise GemspecError, Dsl::DSLError.new(msg, path, e.backtrace, contents)
end
- def configure_gem_home_and_path
- configure_gem_path
- configure_gem_home
- bundle_path
- end
-
- def configure_gem_path(env = ENV)
- blank_home = env["GEM_HOME"].nil? || env["GEM_HOME"].empty?
- if !use_system_gems?
+ def configure_gem_path
+ unless use_system_gems?
# this needs to be empty string to cause
# PathSupport.split_gem_path to only load up the
# Bundler --path setting as the GEM_PATH.
- env["GEM_PATH"] = ""
- elsif blank_home
- possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
- paths = possibles.flatten.compact.uniq.reject(&:empty?)
- env["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
+ Bundler::SharedHelpers.set_env "GEM_PATH", ""
end
end
- def configure_gem_home
- Bundler::SharedHelpers.set_env "GEM_HOME", File.expand_path(bundle_path, root)
- Bundler.rubygems.clear_paths
+ def configure_gem_home(path)
+ Bundler::SharedHelpers.set_env "GEM_HOME", path.to_s
end
def tmp_home_path
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index aa94ad2da0..d5de72e5d4 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -73,14 +73,6 @@ module Bundler
Bundler.ui = UI::Shell.new(options)
Bundler.ui.level = "debug" if options["verbose"]
unprinted_warnings.each {|w| Bundler.ui.warn(w) }
-
- if ENV["RUBYGEMS_GEMDEPS"] && !ENV["RUBYGEMS_GEMDEPS"].empty?
- Bundler.ui.warn(
- "The RUBYGEMS_GEMDEPS environment variable is set. This enables RubyGems' " \
- "experimental Gemfile mode, which may conflict with Bundler and cause unexpected errors. " \
- "To remove this warning, unset RUBYGEMS_GEMDEPS.", :wrap => true
- )
- end
end
check_unknown_options!(:except => [:config, :exec])
@@ -192,6 +184,7 @@ module Bundler
method_option "install", :type => :boolean, :banner =>
"Runs 'bundle install' after removing the gems from the Gemfile"
def remove(*gems)
+ SharedHelpers.major_deprecation(2, "The `--install` flag has been deprecated. `bundle install` is triggered by default.") if ARGV.include?("--install")
require_relative "cli/remove"
Remove.new(gems, options).run
end
@@ -469,7 +462,7 @@ module Bundler
map aliases_for("cache")
desc "exec [OPTIONS]", "Run the command in context of the bundle"
- method_option :keep_file_descriptors, :type => :boolean, :default => false
+ method_option :keep_file_descriptors, :type => :boolean, :default => true
method_option :gemfile, :type => :string, :required => false
long_desc <<-D
Exec runs a command, providing it access to the gems in the bundle. While using
@@ -477,6 +470,10 @@ module Bundler
into the system wide RubyGems repository.
D
def exec(*args)
+ if ARGV.include?("--no-keep-file-descriptors")
+ SharedHelpers.major_deprecation(2, "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to")
+ end
+
require_relative "cli/exec"
Exec.new(options, args).run
end
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 318d57fb06..42b602a055 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -12,12 +12,7 @@ module Bundler
@options = options
@cmd = args.shift
@args = args
-
- if !Bundler.current_ruby.jruby?
- @args << { :close_others => !options.keep_file_descriptors? }
- elsif options.keep_file_descriptors?
- Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec."
- end
+ @args << { :close_others => !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
end
def run
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index c9794c4003..e917ceb7d4 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -68,7 +68,7 @@ module Bundler
:bundler_version => bundler_dependency_version,
:git => use_git,
:github_username => github_username.empty? ? "[USERNAME]" : github_username,
- :required_ruby_version => Gem.ruby_version < Gem::Version.new("2.4.a") ? "2.3.0" : "2.4.0",
+ :required_ruby_version => required_ruby_version,
}
ensure_safe_gem_name(name, constant_array)
@@ -166,11 +166,11 @@ module Bundler
config[:linter] = ask_and_set_linter
case config[:linter]
when "rubocop"
- config[:linter_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.81.0" : "1.7"
+ config[:linter_version] = rubocop_version
Bundler.ui.info "RuboCop enabled in config"
templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
when "standard"
- config[:linter_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.2.5" : "1.0"
+ config[:linter_version] = standard_version
Bundler.ui.info "Standard enabled in config"
templates.merge!("standard.yml.tt" => ".standard.yml")
end
@@ -185,14 +185,15 @@ module Bundler
)
end
- if File.exist?(target) && !File.directory?(target)
+ if target.exist? && !target.directory?
Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
end
if use_git
Bundler.ui.info "Initializing git repo in #{target}"
- `git init #{target}`
+ require "shellwords"
+ `git init #{target.to_s.shellescape}`
config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
end
@@ -402,5 +403,30 @@ module Bundler
def open_editor(editor, file)
thor.run(%(#{editor} "#{file}"))
end
+
+ def required_ruby_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "2.3.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "2.4.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.6.a") then "2.5.0"
+ else
+ "2.6.0"
+ end
+ end
+
+ def rubocop_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.81.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.12"
+ else
+ "1.21"
+ end
+ end
+
+ def standard_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.2.5"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.0"
+ else
+ "1.3"
+ end
+ end
end
end
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 3111b64a33..3afed89ceb 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -40,12 +40,13 @@ module Bundler
end
def print_gem_path(spec)
- if spec.name == "bundler"
+ name = spec.name
+ if name == "bundler"
path = File.expand_path("../../../..", __FILE__)
else
path = spec.full_gem_path
- unless File.directory?(path)
- return Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at: #{path}"
+ if spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}"
end
end
@@ -54,8 +55,9 @@ module Bundler
def print_gem_info(spec)
metadata = spec.metadata
+ name = spec.name
gem_info = String.new
- gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n"
+ gem_info << " * #{name} (#{spec.version}#{spec.git_version})\n"
gem_info << "\tSummary: #{spec.summary}\n" if spec.summary
gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage
gem_info << "\tDocumentation: #{metadata["documentation_uri"]}\n" if metadata.key?("documentation_uri")
@@ -67,6 +69,11 @@ module Bundler
gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri")
gem_info << "\tPath: #{spec.full_gem_path}\n"
gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
+
+ if spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}"
+ end
+
Bundler.ui.info gem_info
end
end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index e4f59e4437..4c1915fea6 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -60,7 +60,7 @@ module Bundler
installer = Installer.install(Bundler.root, definition, options)
Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
- Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
+ Bundler.load.cache(nil, options[:local]) if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
end
Bundler.ui.confirm "Bundle complete! #{dependencies_count_for(definition)}, #{gems_installed_for(definition)}."
@@ -83,15 +83,9 @@ module Bundler
end
Bundler::CLI::Common.output_fund_metadata_summary
- rescue GemNotFound => e
- if options[:local] && Bundler.app_cache.exist?
- Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory."
- end
-
- raise e
- rescue Gem::InvalidSpecificationException => e
+ rescue Gem::InvalidSpecificationException
Bundler.ui.warn "You have one or more invalid gemspecs that need to be fixed."
- raise e
+ raise
end
private
diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb
index 66abd32650..f56bf5b86a 100644
--- a/lib/bundler/cli/list.rb
+++ b/lib/bundler/cli/list.rb
@@ -16,7 +16,13 @@ module Bundler
specs = if @only_group.any? || @without_group.any?
filtered_specs_by_groups
else
- Bundler.load.specs
+ begin
+ Bundler.load.specs
+ rescue GemNotFound => e
+ Bundler.ui.error e.message
+ Bundler.ui.warn "Install missing gems with `bundle install`."
+ exit 1
+ end
end.reject {|s| s.name == "bundler" }.sort_by(&:name)
return Bundler.ui.info "No gems in the Gemfile" if specs.empty?
diff --git a/lib/bundler/cli/remove.rb b/lib/bundler/cli/remove.rb
index cd6a2cec28..44a4d891dd 100644
--- a/lib/bundler/cli/remove.rb
+++ b/lib/bundler/cli/remove.rb
@@ -11,8 +11,7 @@ module Bundler
raise InvalidOption, "Please specify gems to remove." if @gems.empty?
Injector.remove(@gems, {})
-
- Installer.install(Bundler.root, Bundler.definition) if @options["install"]
+ Installer.install(Bundler.root, Bundler.definition)
end
end
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 81cd94eb5f..da180ce255 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -78,7 +78,6 @@ module Bundler
@lockfile_contents = String.new
@locked_bundler_version = nil
@locked_ruby_version = nil
- @locked_specs_incomplete_for_platform = false
@new_platform = nil
if lockfile && File.exist?(lockfile)
@@ -138,12 +137,14 @@ module Bundler
@unlock[:gems] ||= @dependencies.map(&:name)
else
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
- @unlock[:gems] = @locked_specs.for(eager_unlock, false, false, false).map(&:name)
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
end
@dependency_changes = converge_dependencies
@local_changes = converge_locals
+ @locked_specs_incomplete_for_platform = !@locked_specs.for(expand_dependencies(requested_dependencies & locked_dependencies), true, true)
+
@requires = compute_requires
end
@@ -190,15 +191,7 @@ module Bundler
#
# @return [Bundler::SpecSet]
def specs
- @specs ||= add_bundler_to(resolve.materialize(requested_dependencies))
- rescue GemNotFound => e # Handle yanked gem
- gem_name, gem_version = extract_gem_info(e)
- locked_gem = @locked_specs[gem_name].last
- raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
- raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
- "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
- "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
- "removed in order to install."
+ @specs ||= materialize(requested_dependencies)
end
def new_specs
@@ -210,9 +203,7 @@ module Bundler
end
def missing_specs
- missing = []
- resolve.materialize(requested_dependencies, missing)
- missing
+ resolve.materialize(requested_dependencies).missing_specs
end
def missing_specs?
@@ -243,10 +234,14 @@ module Bundler
end
end
+ def locked_dependencies
+ @locked_deps.values
+ end
+
def specs_for(groups)
groups = requested_groups if groups.empty?
deps = dependencies_for(groups)
- add_bundler_to(resolve.materialize(expand_dependencies(deps)))
+ materialize(expand_dependencies(deps))
end
def dependencies_for(groups)
@@ -384,8 +379,8 @@ module Bundler
new_sources = gemfile_sources - @locked_sources
deleted_sources = @locked_sources - gemfile_sources
- new_deps = @dependencies - @locked_deps.values
- deleted_deps = @locked_deps.values - @dependencies
+ new_deps = @dependencies - locked_dependencies
+ deleted_deps = locked_dependencies - @dependencies
# Check if it is possible that the source is only changed thing
if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
@@ -496,7 +491,23 @@ module Bundler
private
- def add_bundler_to(specs)
+ def materialize(dependencies)
+ specs = resolve.materialize(dependencies)
+ missing_specs = specs.missing_specs
+
+ if missing_specs.any?
+ missing_specs.each do |s|
+ locked_gem = @locked_specs[s.name].last
+ next if locked_gem.nil? || locked_gem.version != s.version || !@remote
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
+ "removed in order to install."
+ end
+
+ raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
+ end
+
unless specs["bundler"].any?
bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
specs["bundler"] = bundler
@@ -506,7 +517,7 @@ module Bundler
end
def precompute_source_requirements_for_indirect_dependencies?
- sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
+ @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
def current_ruby_platform_locked?
@@ -561,7 +572,7 @@ module Bundler
def dependencies_for_source_changed?(source, locked_source = source)
deps_for_source = @dependencies.select {|s| s.source == source }
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
deps_for_source.uniq.sort != locked_deps_for_source.sort
end
@@ -645,7 +656,7 @@ module Bundler
def converge_dependencies
frozen = Bundler.frozen_bundle?
- (@dependencies + @locked_deps.values).each do |dep|
+ (@dependencies + locked_dependencies).each do |dep|
locked_source = @locked_deps[dep.name]
# This is to make sure that if bundler is installing in deployment mode and
# after locked_source and sources don't match, we still use locked_source.
@@ -715,7 +726,7 @@ module Bundler
@locked_specs.each do |s|
# Replace the locked dependency's source with the equivalent source from the Gemfile
dep = @dependencies.find {|d| s.satisfies?(d) }
- s.source = (dep && dep.source) || sources.get(s.source)
+ s.source = (dep && dep.source) || sources.get(s.source) unless multisource_allowed?
# Don't add a spec to the list if its source is expired. For example,
# if you change a Git gem to RubyGems.
@@ -733,7 +744,7 @@ module Bundler
# if we won't need the source (according to the lockfile),
# don't error if the path/git source isn't available
next if @locked_specs.
- for(requested_dependencies, false, true, false).
+ for(requested_dependencies, false, true).
none? {|locked_spec| locked_spec.source == s.source }
raise
@@ -752,8 +763,7 @@ module Bundler
end
resolve = SpecSet.new(converged)
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
- resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
+ resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
diff = nil
# Now, we unlock any sources that do not have anymore gems pinned to it
@@ -857,12 +867,6 @@ module Bundler
current == proposed
end
- def extract_gem_info(error)
- # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
- # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
- error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
- end
-
def compute_requires
dependencies.reduce({}) do |requires, dep|
next requires unless dep.should_include?
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 3517a109ed..ed7b3e2d6b 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -457,7 +457,7 @@ repo_name ||= user_name
def implicit_global_source_warning
Bundler::SharedHelpers.major_deprecation 2, "This Gemfile does not include an explicit global source. " \
"Not using an explicit global source may result in a different lockfile being generated depending on " \
- "the gems you have installed locally before bundler is run." \
+ "the gems you have installed locally before bundler is run. " \
"Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"."
end
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 476151ae56..6cf597b943 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -3,7 +3,6 @@
module Bundler
# used for Creating Specifications from the Gemcutter Endpoint
class EndpointSpecification < Gem::Specification
- ILLFORMED_MESSAGE = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'.freeze
include MatchPlatform
attr_reader :name, :version, :platform, :required_rubygems_version, :required_ruby_version, :checksum
@@ -129,13 +128,6 @@ module Bundler
def build_dependency(name, requirements)
Gem::Dependency.new(name, requirements)
- rescue ArgumentError => e
- raise unless e.message.include?(ILLFORMED_MESSAGE)
- puts # we shouldn't print the error message on the "fetching info" status line
- raise GemspecError,
- "Unfortunately, the gem #{name} (#{version}) has an invalid " \
- "gemspec.\nPlease ask the gem author to yank the bad version to fix " \
- "this issue. For more information, see http://bit.ly/syck-defaultkey."
end
end
end
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index 11763b4e88..565aaeeb9d 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -122,7 +122,7 @@ module Bundler
class VirtualProtocolError < BundlerError
def message
- "There was an error relating to virtualization and file access." \
+ "There was an error relating to virtualization and file access. " \
"It is likely that you need to grant access to or mount some file system correctly."
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index d237837948..6dd6d089eb 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -28,7 +28,8 @@ module Bundler
" is a chance you are experiencing a man-in-the-middle attack, but" \
" most likely your system doesn't have the CA certificates needed" \
" for verification. For information about OpenSSL certificates, see" \
- " http://bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile" \
+ " https://railsapps.github.io/openssl-certificate-verify-failed.html." \
+ " To connect without using SSL, edit your Gemfile" \
" sources and change 'https' to 'http'."
end
end
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 6096adfa27..9af8501525 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -76,7 +76,7 @@ module Bundler
tag_version { git_push(args[:remote]) } unless already_tagged?
end
- task "release:rubygem_push" do
+ task "release:rubygem_push" => "build" do
rubygem_push(built_gem_path) if gem_push?
end
@@ -98,10 +98,7 @@ module Bundler
built_gem_path ||= build_gem
cmd = [*gem_command, "install", built_gem_path.to_s]
cmd << "--local" if local
- _, status = sh_with_status(cmd)
- unless status.success?
- raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output"
- end
+ sh(cmd)
Bundler.ui.confirm "#{name} (#{version}) installed."
end
@@ -132,8 +129,8 @@ module Bundler
def git_push(remote = nil)
remote ||= default_remote
- perform_git_push "#{remote} refs/heads/#{current_branch}"
- perform_git_push "#{remote} refs/tags/#{version_tag}"
+ sh(%W[git push #{remote} refs/heads/#{current_branch}])
+ sh(%W[git push #{remote} refs/tags/#{version_tag}])
Bundler.ui.confirm "Pushed git commits and release tag."
end
@@ -161,13 +158,6 @@ module Bundler
allowed_push_host || env_rubygems_host || "rubygems.org"
end
- def perform_git_push(options = "")
- cmd = "git push #{options}"
- out, status = sh_with_status(cmd.shellsplit)
- return if status.success?
- raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n"
- end
-
def already_tagged?
return false unless sh(%w[git tag]).split(/\n/).include?(version_tag)
Bundler.ui.confirm "Tag #{version_tag} has already been created."
@@ -218,8 +208,7 @@ module Bundler
def sh(cmd, &block)
out, status = sh_with_status(cmd, &block)
unless status.success?
- cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin)
- raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out)
+ raise("Running `#{cmd.shelljoin}` failed with the following output:\n\n#{out}\n")
end
out
end
diff --git a/lib/bundler/gemdeps.rb b/lib/bundler/gemdeps.rb
deleted file mode 100644
index cd4b25d0e6..0000000000
--- a/lib/bundler/gemdeps.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class Gemdeps
- def initialize(runtime)
- @runtime = runtime
- end
-
- def requested_specs
- @runtime.requested_specs
- end
-
- def specs
- @runtime.specs
- end
-
- def dependencies
- @runtime.dependencies
- end
-
- def current_dependencies
- @runtime.current_dependencies
- end
-
- def requires
- @runtime.requires
- end
- end
-end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 2624ac4b18..49ff177c0f 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "rubygems/dependency_installer"
require_relative "worker"
require_relative "installer/parallel_installer"
require_relative "installer/standalone"
@@ -219,9 +218,6 @@ module Bundler
return jobs
end
- # Parallelization has some issues on Windows, so it's not yet the default
- return 1 if Gem.win_platform?
-
Bundler.settings.processor_count
end
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index f16135cb48..e8494b4bcd 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -12,12 +12,13 @@ module Bundler
end
File.open File.join(bundler_path, "setup.rb"), "w" do |file|
file.puts "require 'rbconfig'"
- file.puts "ruby_engine = RUBY_ENGINE"
- file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
- file.puts "path = File.expand_path('..', __FILE__)"
file.puts reverse_rubygems_kernel_mixin
paths.each do |path|
- file.puts %($:.unshift File.expand_path("\#{path}/#{path}"))
+ if Pathname.new(path).absolute?
+ file.puts %($:.unshift "#{path}")
+ else
+ file.puts %($:.unshift File.expand_path("\#{__dir__}/#{path}"))
+ end
end
end
end
@@ -28,14 +29,14 @@ module Bundler
@specs.map do |spec|
next if spec.name == "bundler"
Array(spec.require_paths).map do |path|
- gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}')
+ gem_path(path, spec).sub(version_dir, '#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}')
# This is a static string intentionally. It's interpolated at a later time.
end
- end.flatten
+ end.flatten.compact
end
def version_dir
- "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}"
+ "#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}"
end
def bundler_path
@@ -44,7 +45,11 @@ module Bundler
def gem_path(path, spec)
full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path)
- Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
+ if spec.source.instance_of?(Source::Path)
+ full_path
+ else
+ Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
+ end
rescue TypeError
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
raise Gem::InvalidSpecificationException.new(error_message)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index afc21fd006..8d0e44d0ae 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -195,6 +195,7 @@ module Bundler
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
@current_spec = LazySpecification.new(name, version, platform)
@current_spec.source = @current_source
+ @current_source.add_dependency_names(name)
@specs[@current_spec.identifier] = @current_spec
elsif spaces.size == 6
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
index 4945747f42..0cac84bbe8 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-ADD" "1" "June 2021" "" ""
+.TH "BUNDLE\-ADD" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index dd43180b19..017e302fec 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-BINSTUBS" "1" "June 2021" "" ""
+.TH "BUNDLE\-BINSTUBS" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 22ce1dfc76..cfb4b84720 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CACHE" "1" "June 2021" "" ""
+.TH "BUNDLE\-CACHE" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index 6e1b38ab05..bc8f4772f6 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CHECK" "1" "June 2021" "" ""
+.TH "BUNDLE\-CHECK" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index eb658e1c73..814d28e454 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CLEAN" "1" "June 2021" "" ""
+.TH "BUNDLE\-CLEAN" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 323fcc8121..06f2a7bb73 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CONFIG" "1" "June 2021" "" ""
+.TH "BUNDLE\-CONFIG" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
@@ -211,7 +211,7 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
.
.IP "\(bu" 4
-\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to 1 on Windows, and to the the number of processors on other platforms\.
+\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to the number of available processors\.
.
.IP "\(bu" 4
\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 05ba0dc255..96374d9f2b 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -208,8 +208,8 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`):
Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`.
* `jobs` (`BUNDLE_JOBS`):
- The number of gems Bundler can install in parallel. Defaults to 1 on Windows,
- and to the the number of processors on other platforms.
+ The number of gems Bundler can install in parallel. Defaults to the number of
+ available processors.
* `no_install` (`BUNDLE_NO_INSTALL`):
Whether `bundle package` should skip installing gems.
* `no_prune` (`BUNDLE_NO_PRUNE`):
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 84d1f4c9df..5509d315c0 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-DOCTOR" "1" "June 2021" "" ""
+.TH "BUNDLE\-DOCTOR" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index b3c60fbbfd..627ba57ec4 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-EXEC" "1" "June 2021" "" ""
+.TH "BUNDLE\-EXEC" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 3f711c2bed..0190cefa3b 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-GEM" "1" "June 2021" "" ""
+.TH "BUNDLE\-GEM" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index 337e7bdd38..5a1ff7757d 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INFO" "1" "June 2021" "" ""
+.TH "BUNDLE\-INFO" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 0c5b8c7a39..7c72947957 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INIT" "1" "June 2021" "" ""
+.TH "BUNDLE\-INIT" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index f228ed247f..c281f212ba 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INJECT" "1" "June 2021" "" ""
+.TH "BUNDLE\-INJECT" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index ae9747bd83..8b86954996 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INSTALL" "1" "June 2021" "" ""
+.TH "BUNDLE\-INSTALL" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
@@ -63,7 +63,7 @@ The location of the Gemfile(5) which Bundler should use\. This defaults to a Gem
.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
-The maximum number of parallel download and install jobs\. The default is \fB1\fR\.
+The maximum number of parallel download and install jobs\. The default is the number of available processors\.
.
.TP
\fB\-\-local\fR
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index 5ea777f1d4..bec05187f3 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -100,8 +100,8 @@ automatically and that requires `bundler` to silently remember them. Since
to this location.
* `--jobs=[<number>]`, `-j[<number>]`:
- The maximum number of parallel download and install jobs. The default
- is `1`.
+ The maximum number of parallel download and install jobs. The default is the
+ number of available processors.
* `--local`:
Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index cce8881059..48f817ed73 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LIST" "1" "June 2021" "" ""
+.TH "BUNDLE\-LIST" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 23388daaee..623e76406b 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LOCK" "1" "June 2021" "" ""
+.TH "BUNDLE\-LOCK" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index 8cc104b81d..d1c5314ed4 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OPEN" "1" "June 2021" "" ""
+.TH "BUNDLE\-OPEN" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index bdd81a66af..d327de4ba6 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OUTDATED" "1" "June 2021" "" ""
+.TH "BUNDLE\-OUTDATED" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index dab5269c04..872afb6d58 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PLATFORM" "1" "June 2021" "" ""
+.TH "BUNDLE\-PLATFORM" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index e5b0dab334..8361597f7d 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PRISTINE" "1" "June 2021" "" ""
+.TH "BUNDLE\-PRISTINE" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index 8af691283d..548c208403 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-REMOVE" "1" "June 2021" "" ""
+.TH "BUNDLE\-REMOVE" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index c08c7205aa..8669a8add0 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-SHOW" "1" "June 2021" "" ""
+.TH "BUNDLE\-SHOW" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index 7da2ce3438..9df9c05ea7 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-UPDATE" "1" "June 2021" "" ""
+.TH "BUNDLE\-UPDATE" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
@@ -47,7 +47,7 @@ Fall back to using the single\-file index of all gems\.
.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
-Specify the number of jobs to run in parallel\. The default is \fB1\fR\.
+Specify the number of jobs to run in parallel\. The default is the number of available processors\.
.
.TP
\fB\-\-retry=[<number>]\fR
diff --git a/lib/bundler/man/bundle-update.1.ronn b/lib/bundler/man/bundle-update.1.ronn
index 3a16f29149..fe500cdc96 100644
--- a/lib/bundler/man/bundle-update.1.ronn
+++ b/lib/bundler/man/bundle-update.1.ronn
@@ -56,7 +56,8 @@ gem.
Fall back to using the single-file index of all gems.
* `--jobs=[<number>]`, `-j[<number>]`:
- Specify the number of jobs to run in parallel. The default is `1`.
+ Specify the number of jobs to run in parallel. The default is the number of
+ available processors.
* `--retry=[<number>]`:
Retry failed network or git requests for <number> times.
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index 9683f0678b..6603fad30d 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-VIZ" "1" "June 2021" "" ""
+.TH "BUNDLE\-VIZ" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index b741f7cf6a..2fe30724e6 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE" "1" "June 2021" "" ""
+.TH "BUNDLE" "1" "August 2021" "" ""
.
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index f30f71ac7c..5ef91541b0 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "GEMFILE" "5" "June 2021" "" ""
+.TH "GEMFILE" "5" "August 2021" "" ""
.
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index bfe4fd7286..158c69e1a1 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -13,6 +13,7 @@ module Bundler
class MalformattedPlugin < PluginError; end
class UndefinedCommandError < PluginError; end
class UnknownSourceError < PluginError; end
+ class PluginInstallError < PluginError; end
PLUGIN_FILE_NAME = "plugins.rb".freeze
@@ -38,12 +39,11 @@ module Bundler
specs = Installer.new.install(names, options)
save_plugins names, specs
- rescue PluginError => e
+ rescue PluginError
specs_to_delete = specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }
specs_to_delete.each_value {|spec| Bundler.rm_rf(spec.full_gem_path) }
- names_list = names.map {|name| "`#{name}`" }.join(", ")
- Bundler.ui.error "Failed to install the following plugins: #{names_list}. The underlying error was: #{e.message}.\n #{e.backtrace.join("\n ")}"
+ raise
end
# Uninstalls plugins by the given names
@@ -245,10 +245,11 @@ module Bundler
# @param [Array<String>] names of inferred source plugins that can be ignored
def save_plugins(plugins, specs, optional_plugins = [])
plugins.each do |name|
+ next if index.installed?(name)
+
spec = specs[name]
- validate_plugin! Pathname.new(spec.full_gem_path)
- installed = register_plugin(name, spec, optional_plugins.include?(name))
- Bundler.ui.info "Installed plugin #{name}" if installed
+
+ save_plugin(name, spec, optional_plugins.include?(name))
end
end
@@ -263,6 +264,22 @@ module Bundler
raise MalformattedPlugin, "#{PLUGIN_FILE_NAME} was not found in the plugin." unless plugin_file.file?
end
+ # Validates and registers a plugin.
+ #
+ # @param [String] name the name of the plugin
+ # @param [Specification] spec of installed plugin
+ # @param [Boolean] optional_plugin, removed if there is conflict with any
+ # other plugin (used for default source plugins)
+ #
+ # @raise [PluginInstallError] if validation or registration raises any error
+ def save_plugin(name, spec, optional_plugin = false)
+ validate_plugin! Pathname.new(spec.full_gem_path)
+ installed = register_plugin(name, spec, optional_plugin)
+ Bundler.ui.info "Installed plugin #{name}" if installed
+ rescue PluginError => e
+ raise PluginInstallError, "Failed to install plugin `#{spec.name}`, due to #{e.class} (#{e.message})"
+ end
+
# Runs the plugins.rb file in an isolated namespace, records the plugin
# actions it registers for and then passes the data to index to be stored.
#
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 54ce8528cf..d7411fff45 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -81,6 +81,8 @@ module Bundler
deps = names.map {|name| Dependency.new name, version }
+ Bundler.configure_gem_home_and_path(Plugin.root)
+
definition = Definition.new(nil, deps, source_list, true)
install_definition(definition)
end
diff --git a/lib/bundler/psyched_yaml.rb b/lib/bundler/psyched_yaml.rb
index 463d52dc4a..3d9893031f 100644
--- a/lib/bundler/psyched_yaml.rb
+++ b/lib/bundler/psyched_yaml.rb
@@ -1,22 +1,10 @@
# frozen_string_literal: true
-# Psych could be in the stdlib
-# but it's too late if Syck is already loaded
begin
- require "psych" unless defined?(Syck)
+ require "psych"
rescue LoadError
# Apparently Psych wasn't available. Oh well.
end
# At least load the YAML stdlib, whatever that may be
require "yaml" unless defined?(YAML.dump)
-
-module Bundler
- # On encountering invalid YAML,
- # Psych raises Psych::SyntaxError
- if defined?(::Psych::SyntaxError)
- YamlLibrarySyntaxError = ::Psych::SyntaxError
- else # Syck raises ArgumentError
- YamlLibrarySyntaxError = ::ArgumentError
- end
-end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index a78b2db157..d26e2feb10 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -255,12 +255,6 @@ module Bundler
next if name == "bundler"
next unless search_for(requirement).empty?
- cache_message = begin
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
- rescue GemfileNotFound
- nil
- end
-
if (base = @base[name]) && !base.empty?
version = base.first.version
message = "You have requested:\n" \
@@ -269,18 +263,17 @@ module Bundler
"Try running `bundle update #{name}`\n\n" \
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
- elsif source = @source_requirements[name]
+ else
+ source = source_for(name)
specs = source.specs.search(name)
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
- message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
- message << if versions_with_platforms.any?
- "The source contains the following versions of '#{name}': #{formatted_versions_with_platforms(versions_with_platforms)}"
- else
- "The source does not contain any versions of '#{name}'"
- end
- else
- message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \
- "listed in your Gemfile#{cache_message}."
+ cache_message = begin
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
+ rescue GemfileNotFound
+ nil
+ end
+ message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source.to_err}#{cache_message}.\n")
+ message << "The source contains the following versions of '#{name}': #{formatted_versions_with_platforms(versions_with_platforms)}" if versions_with_platforms.any?
end
raise GemNotFound, message
end
@@ -378,7 +371,7 @@ module Bundler
o << if metadata_requirement
"is not available in #{relevant_source}"
else
- "in #{relevant_source}.\n"
+ "in #{relevant_source.to_err}.\n"
end
end
end,
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 2613207826..5d572aa73d 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -85,6 +85,10 @@ module Gem
dependencies - development_dependencies
end
+ def deleted_gem?
+ !default_gem? && !File.directory?(full_gem_path)
+ end
+
private
def dependencies_to_gemfile(dependencies, group = nil)
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index 21ce12ecda..8589c14704 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -34,10 +34,12 @@ module Bundler
end
def build_args
+ require "rubygems/command"
Gem::Command.build_args
end
def build_args=(args)
+ require "rubygems/command"
Gem::Command.build_args = args
end
@@ -84,16 +86,12 @@ module Bundler
def spec_missing_extensions?(spec, default = true)
return spec.missing_extensions? if spec.respond_to?(:missing_extensions?)
- return false if spec_default_gem?(spec)
+ return false if spec.default_gem?
return false if spec.extensions.empty?
default
end
- def spec_default_gem?(spec)
- spec.respond_to?(:default_gem?) && spec.default_gem?
- end
-
def spec_matches_for_glob(spec, glob)
return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
@@ -117,7 +115,7 @@ module Bundler
Bundler.ui.error "#{e.class}: #{e.message}"
Bundler.ui.trace e
raise
- rescue YamlLibrarySyntaxError => e
+ rescue ::Psych::SyntaxError => e
raise YamlSyntaxError.new(e, "Your RubyGems configuration, which is " \
"usually located in ~/.gemrc, contains invalid YAML syntax.")
end
@@ -598,14 +596,6 @@ module Bundler
Gem::Specification.send(:default_stubs, "*.gemspec")
end
end
-
- def use_gemdeps(gemfile)
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile)
- require_relative "gemdeps"
- runtime = Bundler.setup
- activated_spec_names = runtime.requested_specs.map(&:to_spec).sort_by(&:name)
- [Gemdeps.new(runtime), activated_spec_names]
- end
end
def self.rubygems
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 287fa1cfe9..31e71388a6 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -22,10 +22,6 @@ module Bundler
# Activate the specs
load_paths = specs.map do |spec|
- unless spec.loaded_from
- raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it."
- end
-
check_for_activated_spec!(spec)
Bundler.rubygems.mark_loaded(spec)
@@ -104,7 +100,7 @@ module Bundler
alias_method :gems, :specs
- def cache(custom_path = nil)
+ def cache(custom_path = nil, local = false)
cache_path = Bundler.app_cache(custom_path)
SharedHelpers.filesystem_access(cache_path) do |p|
FileUtils.mkdir_p(p)
@@ -112,7 +108,20 @@ module Bundler
Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}"
- specs_to_cache = Bundler.settings[:cache_all_platforms] ? @definition.resolve.materialized_for_all_platforms : specs
+ specs_to_cache = if Bundler.settings[:cache_all_platforms]
+ @definition.resolve.materialized_for_all_platforms
+ else
+ begin
+ specs
+ rescue GemNotFound
+ if local
+ Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory."
+ end
+
+ raise
+ end
+ end
+
specs_to_cache.each do |spec|
next if spec.name == "bundler"
next if spec.source.is_a?(Source::Gemspec)
@@ -282,7 +291,7 @@ module Bundler
return unless activated_spec = Bundler.rubygems.loaded_specs(spec.name)
return if activated_spec.version == spec.version
- suggestion = if Bundler.rubygems.spec_default_gem?(activated_spec)
+ suggestion = if activated_spec.default_gem?
"Since #{spec.name} is a default gem, you can either remove your dependency on it" \
" or try updating to a newer version of bundler that supports #{spec.name} as a default gem."
else
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index de42cc16af..1ced590b6f 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -419,7 +419,15 @@ module Bundler
elsif is_credential(key)
"[REDACTED]"
elsif is_userinfo(converted)
- converted.gsub(/:.*$/, ":[REDACTED]")
+ username, pass = converted.split(":", 2)
+
+ if pass == "x-oauth-basic"
+ username = "[REDACTED]"
+ else
+ pass = "[REDACTED]"
+ end
+
+ [username, pass].join(":")
else
converted
end
@@ -428,6 +436,10 @@ module Bundler
def global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
Pathname.new(ENV["BUNDLE_CONFIG"])
+ elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
+ Pathname.new(ENV["BUNDLE_USER_CONFIG"])
+ elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty?
+ Pathname.new(ENV["BUNDLE_USER_HOME"]).join("config")
elsif Bundler.rubygems.user_home && !Bundler.rubygems.user_home.empty?
Pathname.new(Bundler.rubygems.user_home).join(".bundle/config")
end
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 27911dc1ad..32e9b2d7c0 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -9,10 +9,10 @@ if Bundler::SharedHelpers.in_bundle?
begin
Bundler.ui.silence { Bundler.setup }
rescue Bundler::BundlerError => e
- Bundler.ui.warn "\e[31m#{e.message}\e[0m"
+ Bundler.ui.error e.message
Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
if e.is_a?(Bundler::GemNotFound)
- Bundler.ui.warn "\e[33mRun `bundle install` to install missing gems.\e[0m"
+ Bundler.ui.warn "Run `bundle install` to install missing gems."
end
exit e.status_code
end
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 5388a7681e..434112ac8a 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -67,6 +67,10 @@ module Bundler
"#<#{self.class}:0x#{object_id} #{self}>"
end
+ def to_err
+ to_s
+ end
+
def path?
instance_of?(Bundler::Source::Path)
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index fb13ca0578..679fb22574 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -42,7 +42,7 @@ module Bundler
%w[ref branch tag submodules].each do |opt|
out << " #{opt}: #{options[opt]}\n" if options[opt]
end
- out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
+ out << " glob: #{@glob}\n" unless default_glob?
out << " specs:\n"
end
@@ -75,12 +75,20 @@ module Bundler
git_proxy.branch
end
- rev = " (at #{at}@#{shortref_for_display(revision)})"
+ rev = "at #{at}@#{shortref_for_display(revision)}"
rescue GitError
""
end
- "#{@safe_uri}#{rev}"
+ specifiers = [rev, glob_for_display].compact
+ suffix =
+ if specifiers.any?
+ " (#{specifiers.join(", ")})"
+ else
+ ""
+ end
+
+ "#{@safe_uri}#{suffix}"
end
def name
@@ -282,6 +290,14 @@ module Bundler
ref[0..11]
end
+ def glob_for_display
+ default_glob? ? nil : "glob: #{@glob}"
+ end
+
+ def default_glob?
+ @glob == DEFAULT_GLOB
+ end
+
def uri_hash
if uri =~ %r{^\w+://(\w+@)?}
# Downcase the domain component of the URI
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 858a69a48b..28c1ee3c96 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -29,6 +29,7 @@ module Bundler
def local_only!
@specs = nil
@allow_local = true
+ @allow_cached = false
@allow_remote = false
end
@@ -50,6 +51,7 @@ module Bundler
return if @allow_cached
@specs = nil
+ @allow_local = true
@allow_cached = true
end
@@ -96,11 +98,22 @@ module Bundler
out << " specs:\n"
end
+ def to_err
+ if remotes.empty?
+ "locally installed gems"
+ elsif @allow_remote
+ "rubygems repository #{remote_names} or installed locally"
+ elsif @allow_cached
+ "cached gems from rubygems repository #{remote_names} or installed locally"
+ else
+ "locally installed gems"
+ end
+ end
+
def to_s
if remotes.empty?
"locally installed gems"
else
- remote_names = remotes.map(&:to_s).join(", ")
"rubygems repository #{remote_names} or installed locally"
end
end
@@ -122,7 +135,7 @@ module Bundler
force = opts[:force]
ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
- if ensure_builtin_gems_cached && builtin_gem?(spec)
+ if ensure_builtin_gems_cached && spec.default_gem?
if !cached_path(spec)
cached_built_in_gem(spec) unless spec.remote
force = true
@@ -131,7 +144,7 @@ module Bundler
end
end
- if (installed?(spec) || Plugin.installed?(spec.name)) && !force
+ if installed?(spec) && !force
print_using_message "Using #{version_message(spec)}"
return nil # no post-install message
end
@@ -220,7 +233,7 @@ module Bundler
end
def cache(spec, custom_path = nil)
- if builtin_gem?(spec)
+ if spec.default_gem?
cached_path = cached_built_in_gem(spec)
else
cached_path = cached_gem(spec)
@@ -319,6 +332,10 @@ module Bundler
protected
+ def remote_names
+ remotes.map(&:to_s).join(", ")
+ end
+
def credless_remotes
remotes.map(&method(:suppress_configured_credentials))
end
@@ -462,16 +479,8 @@ module Bundler
Bundler.rm_rf(download_path) if requires_sudo?
end
- def builtin_gem?(spec)
- # Ruby 2.1, where all included gems have this summary
- return true if spec.summary =~ /is bundled with Ruby/
-
- # Ruby 2.0, where gemspecs are stored in specifications/default/
- spec.loaded_from && spec.loaded_from.include?("specifications/default/")
- end
-
def installed?(spec)
- installed_specs[spec].any?
+ installed_specs[spec].any? && !spec.deleted_gem?
end
def requires_sudo?
diff --git a/lib/bundler/source/rubygems_aggregate.rb b/lib/bundler/source/rubygems_aggregate.rb
index 685bf7e90a..09cf4002ea 100644
--- a/lib/bundler/source/rubygems_aggregate.rb
+++ b/lib/bundler/source/rubygems_aggregate.rb
@@ -16,6 +16,10 @@ module Bundler
@index
end
+ def to_err
+ to_s
+ end
+
def to_s
"any of the sources"
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index c7dfa3d797..d6310b78c0 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -121,7 +121,8 @@ module Bundler
def replace_sources!(replacement_sources)
return false if replacement_sources.empty?
- @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+ @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+ @global_rubygems_source = global_replacement_source(replacement_sources)
different_sources?(lock_sources, replacement_sources)
end
@@ -156,13 +157,21 @@ module Bundler
end
def map_sources(replacement_sources)
- [path_sources, git_sources, plugin_sources].map do |sources|
+ [@rubygems_sources, @path_sources, @git_sources, @plugin_sources].map do |sources|
sources.map do |source|
replacement_sources.find {|s| s == source } || source
end
end
end
+ def global_replacement_source(replacement_sources)
+ replacement_source = replacement_sources.find {|s| s == global_rubygems_source }
+ return global_rubygems_source unless replacement_source
+
+ replacement_source.local!
+ replacement_source
+ end
+
def different_sources?(lock_sources, replacement_sources)
!equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
end
@@ -206,7 +215,7 @@ module Bundler
end
def equal_source?(source, other_source)
- return source.include?(other_source) if source.is_a?(Source::Rubygems) && other_source.is_a?(Source::Rubygems) && !merged_gem_lockfile_sections?
+ return source.include?(other_source) if source.is_a?(Source::Rubygems) && other_source.is_a?(Source::Rubygems)
source == other_source
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 1a8906c47e..26d41cb9b8 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -11,7 +11,7 @@ module Bundler
@specs = specs
end
- def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true)
+ def for(dependencies, check = false, match_current_platform = false)
handled = []
deps = dependencies.dup
specs = []
@@ -24,7 +24,7 @@ module Bundler
specs_for_dep = spec_for_dependency(dep, match_current_platform)
if specs_for_dep.any?
- specs += specs_for_dep
+ match_current_platform ? specs += specs_for_dep : specs |= specs_for_dep
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
@@ -33,11 +33,6 @@ module Bundler
end
elsif check
return false
- elsif raise_on_missing
- others = lookup[dep.name] if match_current_platform
- message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
- message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
- raise GemNotFound, message
end
end
@@ -71,52 +66,35 @@ module Bundler
lookup.dup
end
- def materialize(deps, missing_specs = nil)
- materialized = self.for(deps, false, true, !missing_specs)
-
- materialized.group_by(&:source).each do |source, specs|
- next unless specs.any?{|s| s.is_a?(LazySpecification) }
-
- source.local!
- names = -> { specs.map(&:name).uniq }
- source.double_check_for(names)
- end
+ def materialize(deps)
+ materialized = self.for(deps, false, true)
materialized.map! do |s|
next s unless s.is_a?(LazySpecification)
- spec = s.__materialize__
- unless spec
- unless missing_specs
- raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
- end
- missing_specs << s
- end
- spec
+ s.source.local!
+ s.__materialize__ || s
end
- SpecSet.new(missing_specs ? materialized.compact : materialized)
+ SpecSet.new(materialized)
end
# Materialize for all the specs in the spec set, regardless of what platform they're for
# This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
# @return [Array<Gem::Specification>]
def materialized_for_all_platforms
- @specs.group_by(&:source).each do |source, specs|
- next unless specs.any?{|s| s.is_a?(LazySpecification) }
-
- source.local!
- source.remote!
- names = -> { specs.map(&:name).uniq }
- source.double_check_for(names)
- end
-
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
+ s.source.local!
+ s.source.remote!
spec = s.__materialize__
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
spec
end
end
+ def missing_specs
+ @specs.select {|s| s.is_a?(LazySpecification) }
+ end
+
def merge(set)
arr = sorted.dup
set.each do |set_spec|
diff --git a/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
index 654978033f..952cd649a2 100644
--- a/lib/bundler/templates/newgem/github/workflows/main.yml.tt
+++ b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
@@ -1,16 +1,27 @@
name: Ruby
-on: [push,pull_request]
+on:
+ push:
+ branches:
+ - <%= config[:git_default_branch] %>
+
+ pull_request:
jobs:
build:
runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ ruby:
+ - <%= RUBY_VERSION %>
+
steps:
- uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: <%= RUBY_VERSION %>
+ ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run the default task
run: bundle exec rake
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index eddb8b4a30..e07ec5867d 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
<%- end -%>
spec.required_ruby_version = ">= <%= config[:required_ruby_version] %>"
- spec.metadata["allowed_push_host"] = "TODO: Set to 'https://mygemserver.com'"
+ spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject do |f|
- f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
end
end
spec.bindir = "exe"
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 3b53d27a2e..b6ffbae331 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -288,7 +288,7 @@
#
class CGI
- VERSION = "0.2.0"
+ VERSION = "0.3.0"
end
require 'cgi/core'
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
index 69a252b5e3..55e61bf984 100644
--- a/lib/cgi/util.rb
+++ b/lib/cgi/util.rb
@@ -179,21 +179,12 @@ module CGI::Util
# Synonym for CGI.unescapeElement(str)
alias unescape_element unescapeElement
- # Abbreviated day-of-week names specified by RFC 822
- RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
-
- # Abbreviated month names specified by RFC 822
- RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
-
# Format a +Time+ object as a String using the format specified by RFC 1123.
#
# CGI.rfc1123_date(Time.now)
# # Sat, 01 Jan 2000 00:00:00 GMT
def rfc1123_date(time)
- t = time.clone.gmtime
- return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
- RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
- t.hour, t.min, t.sec)
+ time.getgm.strftime("%a, %d %b %Y %T GMT")
end
# Prettify (indent) an HTML string.
diff --git a/lib/debug.gemspec b/lib/debug.gemspec
deleted file mode 100644
index 71f93f7409..0000000000
--- a/lib/debug.gemspec
+++ /dev/null
@@ -1,22 +0,0 @@
-Gem::Specification.new do |spec|
- spec.name = "debug"
- spec.version = "0.1.0"
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Debugging functionality for Ruby}
- spec.description = %q{Debugging functionality for Ruby}
- spec.homepage = "https://github.com/ruby/debug"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/debug.rb b/lib/debug.rb
deleted file mode 100644
index bf53eb80a4..0000000000
--- a/lib/debug.rb
+++ /dev/null
@@ -1,1106 +0,0 @@
-# frozen_string_literal: true
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-# Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
-
-require 'continuation'
-
-require 'tracer'
-require 'pp'
-
-class Tracer # :nodoc:
- def Tracer.trace_func(*vars)
- Single.trace_func(*vars)
- end
-end
-
-SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc:
-
-##
-# This library provides debugging functionality to Ruby.
-#
-# To add a debugger to your code, start by requiring +debug+ in your
-# program:
-#
-# def say(word)
-# require 'debug'
-# puts word
-# end
-#
-# This will cause Ruby to interrupt execution and show a prompt when the +say+
-# method is run.
-#
-# Once you're inside the prompt, you can start debugging your program.
-#
-# (rdb:1) p word
-# "hello"
-#
-# == Getting help
-#
-# You can get help at any time by pressing +h+.
-#
-# (rdb:1) h
-# Debugger help v.-0.002b
-# Commands
-# b[reak] [file:|class:]<line|method>
-# b[reak] [class.]<line|method>
-# set breakpoint to some position
-# wat[ch] <expression> set watchpoint to some expression
-# cat[ch] (<exception>|off) set catchpoint to an exception
-# b[reak] list breakpoints
-# cat[ch] show catchpoint
-# del[ete][ nnn] delete some or all breakpoints
-# disp[lay] <expression> add expression into display expression list
-# undisp[lay][ nnn] delete one particular or all display expressions
-# c[ont] run until program ends or hit breakpoint
-# s[tep][ nnn] step (into methods) one line or till line nnn
-# n[ext][ nnn] go over one line or till line nnn
-# w[here] display frames
-# f[rame] alias for where
-# l[ist][ (-|nn-mm)] list program, - lists backwards
-# nn-mm lists given lines
-# up[ nn] move to higher frame
-# down[ nn] move to lower frame
-# fin[ish] return to outer frame
-# tr[ace] (on|off) set trace mode of current thread
-# tr[ace] (on|off) all set trace mode of all threads
-# q[uit] exit from debugger
-# v[ar] g[lobal] show global variables
-# v[ar] l[ocal] show local variables
-# v[ar] i[nstance] <object> show instance variables of object
-# v[ar] c[onst] <object> show constants of object
-# m[ethod] i[nstance] <obj> show methods of object
-# m[ethod] <class|module> show instance methods of class or module
-# th[read] l[ist] list all threads
-# th[read] c[ur[rent]] show current thread
-# th[read] [sw[itch]] <nnn> switch thread context to nnn
-# th[read] stop <nnn> stop thread nnn
-# th[read] resume <nnn> resume thread nnn
-# p expression evaluate expression and print its value
-# h[elp] print this help
-# <everything else> evaluate
-#
-# == Usage
-#
-# The following is a list of common functionalities that the debugger
-# provides.
-#
-# === Navigating through your code
-#
-# In general, a debugger is used to find bugs in your program, which
-# often means pausing execution and inspecting variables at some point
-# in time.
-#
-# Let's look at an example:
-#
-# def my_method(foo)
-# require 'debug'
-# foo = get_foo if foo.nil?
-# raise if foo.nil?
-# end
-#
-# When you run this program, the debugger will kick in just before the
-# +foo+ assignment.
-#
-# (rdb:1) p foo
-# nil
-#
-# In this example, it'd be interesting to move to the next line and
-# inspect the value of +foo+ again. You can do that by pressing +n+:
-#
-# (rdb:1) n # goes to next line
-# (rdb:1) p foo
-# nil
-#
-# You now know that the original value of +foo+ was nil, and that it
-# still was nil after calling +get_foo+.
-#
-# Other useful commands for navigating through your code are:
-#
-# +c+::
-# Runs the program until it either exists or encounters another breakpoint.
-# You usually press +c+ when you are finished debugging your program and
-# want to resume its execution.
-# +s+::
-# Steps into method definition. In the previous example, +s+ would take you
-# inside the method definition of +get_foo+.
-# +r+::
-# Restart the program.
-# +q+::
-# Quit the program.
-#
-# === Inspecting variables
-#
-# You can use the debugger to easily inspect both local and global variables.
-# We've seen how to inspect local variables before:
-#
-# (rdb:1) p my_arg
-# 42
-#
-# You can also pretty print the result of variables or expressions:
-#
-# (rdb:1) pp %w{a very long long array containing many words}
-# ["a",
-# "very",
-# "long",
-# ...
-# ]
-#
-# You can list all local variables with +v l+:
-#
-# (rdb:1) v l
-# foo => "hello"
-#
-# Similarly, you can show all global variables with +v g+:
-#
-# (rdb:1) v g
-# all global variables
-#
-# Finally, you can omit +p+ if you simply want to evaluate a variable or
-# expression
-#
-# (rdb:1) 5**2
-# 25
-#
-# === Going beyond basics
-#
-# Ruby Debug provides more advanced functionalities like switching
-# between threads, setting breakpoints and watch expressions, and more.
-# The full list of commands is available at any time by pressing +h+.
-#
-# == Staying out of trouble
-#
-# Make sure you remove every instance of +require 'debug'+ before
-# shipping your code. Failing to do so may result in your program
-# hanging unpredictably.
-#
-# Debug is not available in safe mode.
-
-class DEBUGGER__
- MUTEX = Thread::Mutex.new # :nodoc:
-
- class Context # :nodoc:
- DEBUG_LAST_CMD = []
-
- begin
- require 'readline'
- def readline(prompt, hist)
- Readline::readline(prompt, hist)
- end
- rescue LoadError
- def readline(prompt, hist)
- STDOUT.print prompt
- STDOUT.flush
- line = STDIN.gets
- exit unless line
- line.chomp!
- line
- end
- USE_READLINE = false
- end
-
- def initialize
- if Thread.current == Thread.main
- @stop_next = 1
- else
- @stop_next = 0
- end
- @last_file = nil
- @file = nil
- @line = nil
- @no_step = nil
- @frames = []
- @finish_pos = 0
- @trace = false
- @catch = "StandardError"
- @suspend_next = false
- end
-
- def stop_next(n=1)
- @stop_next = n
- end
-
- def set_suspend
- @suspend_next = true
- end
-
- def clear_suspend
- @suspend_next = false
- end
-
- def suspend_all
- DEBUGGER__.suspend
- end
-
- def resume_all
- DEBUGGER__.resume
- end
-
- def check_suspend
- while MUTEX.synchronize {
- if @suspend_next
- DEBUGGER__.waiting.push Thread.current
- @suspend_next = false
- true
- end
- }
- end
- end
-
- def trace?
- @trace
- end
-
- def set_trace(arg)
- @trace = arg
- end
-
- def stdout
- DEBUGGER__.stdout
- end
-
- def break_points
- DEBUGGER__.break_points
- end
-
- def display
- DEBUGGER__.display
- end
-
- def context(th)
- DEBUGGER__.context(th)
- end
-
- def set_trace_all(arg)
- DEBUGGER__.set_trace(arg)
- end
-
- def set_last_thread(th)
- DEBUGGER__.set_last_thread(th)
- end
-
- def debug_eval(str, binding)
- begin
- eval(str, binding)
- rescue StandardError, ScriptError => e
- at = eval("caller(1)", binding)
- stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
- for i in at
- stdout.printf "\tfrom %s\n", i
- end
- throw :debug_error
- end
- end
-
- def debug_silent_eval(str, binding)
- begin
- eval(str, binding)
- rescue StandardError, ScriptError
- nil
- end
- end
-
- def var_list(ary, binding)
- ary.sort!
- for v in ary
- stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect
- end
- end
-
- def debug_variable_info(input, binding)
- case input
- when /^\s*g(?:lobal)?\s*$/
- var_list(global_variables, binding)
-
- when /^\s*l(?:ocal)?\s*$/
- var_list(eval("local_variables", binding), binding)
-
- when /^\s*i(?:nstance)?\s+/
- obj = debug_eval($', binding)
- var_list(obj.instance_variables, obj.instance_eval{binding()})
-
- when /^\s*c(?:onst(?:ant)?)?\s+/
- obj = debug_eval($', binding)
- unless obj.kind_of? Module
- stdout.print "Should be Class/Module: ", $', "\n"
- else
- var_list(obj.constants, obj.module_eval{binding()})
- end
- end
- end
-
- def debug_method_info(input, binding)
- case input
- when /^i(:?nstance)?\s+/
- obj = debug_eval($', binding)
-
- len = 0
- for v in obj.methods.sort
- len += v.size + 1
- if len > 70
- len = v.size + 1
- stdout.print "\n"
- end
- stdout.print v, " "
- end
- stdout.print "\n"
-
- else
- obj = debug_eval(input, binding)
- unless obj.kind_of? Module
- stdout.print "Should be Class/Module: ", input, "\n"
- else
- len = 0
- for v in obj.instance_methods(false).sort
- len += v.size + 1
- if len > 70
- len = v.size + 1
- stdout.print "\n"
- end
- stdout.print v, " "
- end
- stdout.print "\n"
- end
- end
- end
-
- def thnum
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
- unless num
- DEBUGGER__.make_thread_list
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
- end
- num
- end
-
- def debug_command(file, line, id, binding)
- MUTEX.lock
- unless defined?($debugger_restart) and $debugger_restart
- callcc{|c| $debugger_restart = c}
- end
- set_last_thread(Thread.current)
- frame_pos = 0
- binding_file = file
- binding_line = line
- previous_line = nil
- if ENV['EMACS']
- stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
- else
- stdout.printf "%s:%d:%s", binding_file, binding_line,
- line_at(binding_file, binding_line)
- end
- @frames[0] = [binding, file, line, id]
- display_expressions(binding)
- prompt = true
- while prompt and input = readline("(rdb:%d) "%thnum(), true)
- catch(:debug_error) do
- if input == ""
- next unless DEBUG_LAST_CMD[0]
- input = DEBUG_LAST_CMD[0]
- stdout.print input, "\n"
- else
- DEBUG_LAST_CMD[0] = input
- end
-
- case input
- when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
- if defined?( $2 )
- if $1 == 'on'
- set_trace_all true
- else
- set_trace_all false
- end
- elsif defined?( $1 )
- if $1 == 'on'
- set_trace true
- else
- set_trace false
- end
- end
- if trace?
- stdout.print "Trace on.\n"
- else
- stdout.print "Trace off.\n"
- end
-
- when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
- pos = $2
- if $1
- klass = debug_silent_eval($1, binding)
- file = File.expand_path($1)
- end
- if pos =~ /^\d+$/
- pname = pos
- pos = pos.to_i
- else
- pname = pos = pos.intern.id2name
- end
- break_points.push [true, 0, klass || file, pos]
- stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
-
- when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
- pos = $2.intern.id2name
- klass = debug_eval($1, binding)
- break_points.push [true, 0, klass, pos]
- stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
-
- when /^\s*wat(?:ch)?\s+(.+)$/
- exp = $1
- break_points.push [true, 1, exp]
- stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
-
- when /^\s*b(?:reak)?$/
- if break_points.find{|b| b[1] == 0}
- n = 1
- stdout.print "Breakpoints:\n"
- break_points.each do |b|
- if b[0] and b[1] == 0
- stdout.printf " %d %s:%s\n", n, b[2], b[3]
- end
- n += 1
- end
- end
- if break_points.find{|b| b[1] == 1}
- n = 1
- stdout.print "\n"
- stdout.print "Watchpoints:\n"
- for b in break_points
- if b[0] and b[1] == 1
- stdout.printf " %d %s\n", n, b[2]
- end
- n += 1
- end
- end
- if break_points.size == 0
- stdout.print "No breakpoints\n"
- else
- stdout.print "\n"
- end
-
- when /^\s*del(?:ete)?(?:\s+(\d+))?$/
- pos = $1
- unless pos
- input = readline("Clear all breakpoints? (y/n) ", false)
- if input == "y"
- for b in break_points
- b[0] = false
- end
- end
- else
- pos = pos.to_i
- if break_points[pos-1]
- break_points[pos-1][0] = false
- else
- stdout.printf "Breakpoint %d is not defined\n", pos
- end
- end
-
- when /^\s*disp(?:lay)?\s+(.+)$/
- exp = $1
- display.push [true, exp]
- stdout.printf "%d: ", display.size
- display_expression(exp, binding)
-
- when /^\s*disp(?:lay)?$/
- display_expressions(binding)
-
- when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
- pos = $1
- unless pos
- input = readline("Clear all expressions? (y/n) ", false)
- if input == "y"
- for d in display
- d[0] = false
- end
- end
- else
- pos = pos.to_i
- if display[pos-1]
- display[pos-1][0] = false
- else
- stdout.printf "Display expression %d is not defined\n", pos
- end
- end
-
- when /^\s*c(?:ont)?$/
- prompt = false
-
- when /^\s*s(?:tep)?(?:\s+(\d+))?$/
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- @stop_next = lev
- prompt = false
-
- when /^\s*n(?:ext)?(?:\s+(\d+))?$/
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- @stop_next = lev
- @no_step = @frames.size - frame_pos
- prompt = false
-
- when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
- display_frames(frame_pos)
-
- when /^\s*l(?:ist)?(?:\s+(.+))?$/
- if not $1
- b = previous_line ? previous_line + 10 : binding_line - 5
- e = b + 9
- elsif $1 == '-'
- b = previous_line ? previous_line - 10 : binding_line - 5
- e = b + 9
- else
- b, e = $1.split(/[-,]/)
- if e
- b = b.to_i
- e = e.to_i
- else
- b = b.to_i - 5
- e = b + 9
- end
- end
- previous_line = b
- display_list(b, e, binding_file, binding_line)
-
- when /^\s*up(?:\s+(\d+))?$/
- previous_line = nil
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- frame_pos += lev
- if frame_pos >= @frames.size
- frame_pos = @frames.size - 1
- stdout.print "At toplevel\n"
- end
- binding, binding_file, binding_line = @frames[frame_pos]
- stdout.print format_frame(frame_pos)
-
- when /^\s*down(?:\s+(\d+))?$/
- previous_line = nil
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- frame_pos -= lev
- if frame_pos < 0
- frame_pos = 0
- stdout.print "At stack bottom\n"
- end
- binding, binding_file, binding_line = @frames[frame_pos]
- stdout.print format_frame(frame_pos)
-
- when /^\s*fin(?:ish)?$/
- if frame_pos == @frames.size
- stdout.print "\"finish\" not meaningful in the outermost frame.\n"
- else
- @finish_pos = @frames.size - frame_pos
- frame_pos = 0
- prompt = false
- end
-
- when /^\s*cat(?:ch)?(?:\s+(.+))?$/
- if $1
- excn = $1
- if excn == 'off'
- @catch = nil
- stdout.print "Clear catchpoint.\n"
- else
- @catch = excn
- stdout.printf "Set catchpoint %s.\n", @catch
- end
- else
- if @catch
- stdout.printf "Catchpoint %s.\n", @catch
- else
- stdout.print "No catchpoint.\n"
- end
- end
-
- when /^\s*q(?:uit)?$/
- input = readline("Really quit? (y/n) ", false)
- if input == "y"
- exit! # exit -> exit!: No graceful way to stop threads...
- end
-
- when /^\s*v(?:ar)?\s+/
- debug_variable_info($', binding)
-
- when /^\s*m(?:ethod)?\s+/
- debug_method_info($', binding)
-
- when /^\s*th(?:read)?\s+/
- if DEBUGGER__.debug_thread_info($', binding) == :cont
- prompt = false
- end
-
- when /^\s*pp\s+/
- PP.pp(debug_eval($', binding), stdout)
-
- when /^\s*p\s+/
- stdout.printf "%s\n", debug_eval($', binding).inspect
-
- when /^\s*r(?:estart)?$/
- $debugger_restart.call
-
- when /^\s*h(?:elp)?$/
- debug_print_help()
-
- else
- v = debug_eval(input, binding)
- stdout.printf "%s\n", v.inspect
- end
- end
- end
- MUTEX.unlock
- resume_all
- end
-
- def debug_print_help
- stdout.print <<EOHELP
-Debugger help v.-0.002b
-Commands
- b[reak] [file:|class:]<line|method>
- b[reak] [class.]<line|method>
- set breakpoint to some position
- wat[ch] <expression> set watchpoint to some expression
- cat[ch] (<exception>|off) set catchpoint to an exception
- b[reak] list breakpoints
- cat[ch] show catchpoint
- del[ete][ nnn] delete some or all breakpoints
- disp[lay] <expression> add expression into display expression list
- undisp[lay][ nnn] delete one particular or all display expressions
- c[ont] run until program ends or hit breakpoint
- s[tep][ nnn] step (into methods) one line or till line nnn
- n[ext][ nnn] go over one line or till line nnn
- w[here] display frames
- f[rame] alias for where
- l[ist][ (-|nn-mm)] list program, - lists backwards
- nn-mm lists given lines
- up[ nn] move to higher frame
- down[ nn] move to lower frame
- fin[ish] return to outer frame
- tr[ace] (on|off) set trace mode of current thread
- tr[ace] (on|off) all set trace mode of all threads
- q[uit] exit from debugger
- v[ar] g[lobal] show global variables
- v[ar] l[ocal] show local variables
- v[ar] i[nstance] <object> show instance variables of object
- v[ar] c[onst] <object> show constants of object
- m[ethod] i[nstance] <obj> show methods of object
- m[ethod] <class|module> show instance methods of class or module
- th[read] l[ist] list all threads
- th[read] c[ur[rent]] show current thread
- th[read] [sw[itch]] <nnn> switch thread context to nnn
- th[read] stop <nnn> stop thread nnn
- th[read] resume <nnn> resume thread nnn
- pp expression evaluate expression and pretty_print its value
- p expression evaluate expression and print its value
- r[estart] restart program
- h[elp] print this help
- <everything else> evaluate
-EOHELP
- end
-
- def display_expressions(binding)
- n = 1
- for d in display
- if d[0]
- stdout.printf "%d: ", n
- display_expression(d[1], binding)
- end
- n += 1
- end
- end
-
- def display_expression(exp, binding)
- stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
- end
-
- def frame_set_pos(file, line)
- if @frames[0]
- @frames[0][1] = file
- @frames[0][2] = line
- end
- end
-
- def display_frames(pos)
- 0.upto(@frames.size - 1) do |n|
- if n == pos
- stdout.print "--> "
- else
- stdout.print " "
- end
- stdout.print format_frame(n)
- end
- end
-
- def format_frame(pos)
- _, file, line, id = @frames[pos]
- sprintf "#%d %s:%s%s\n", pos + 1, file, line,
- (id ? ":in `#{id.id2name}'" : "")
- end
-
- def script_lines(file, line)
- unless (lines = SCRIPT_LINES__[file]) and lines != true
- Tracer::Single.get_line(file, line) if File.exist?(file)
- lines = SCRIPT_LINES__[file]
- lines = nil if lines == true
- end
- lines
- end
-
- def display_list(b, e, file, line)
- if lines = script_lines(file, line)
- stdout.printf "[%d, %d] in %s\n", b, e, file
- b.upto(e) do |n|
- if n > 0 && lines[n-1]
- if n == line
- stdout.printf "=> %d %s\n", n, lines[n-1].chomp
- else
- stdout.printf " %d %s\n", n, lines[n-1].chomp
- end
- end
- end
- else
- stdout.printf "No sourcefile available for %s\n", file
- end
- end
-
- def line_at(file, line)
- lines = script_lines(file, line)
- if lines and line = lines[line-1]
- return line
- end
- return "\n"
- end
-
- def debug_funcname(id)
- if id.nil?
- "toplevel"
- else
- id.id2name
- end
- end
-
- def check_break_points(file, klass, pos, binding, id)
- return false if break_points.empty?
- n = 1
- for b in break_points
- if b[0] # valid
- if b[1] == 0 # breakpoint
- if (b[2] == file and b[3] == pos) or
- (klass and b[2] == klass and b[3] == pos)
- stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
- return true
- end
- elsif b[1] == 1 # watchpoint
- if debug_silent_eval(b[2], binding)
- stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
- return true
- end
- end
- end
- n += 1
- end
- return false
- end
-
- def excn_handle(file, line, id, binding)
- if $!.class <= SystemExit
- set_trace_func nil
- exit
- end
-
- if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
- stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
- fs = @frames.size
- tb = caller(0)[-fs..-1]
- if tb
- for i in tb
- stdout.printf "\tfrom %s\n", i
- end
- end
- suspend_all
- debug_command(file, line, id, binding)
- end
- end
-
- def trace_func(event, file, line, id, binding, klass)
- Tracer.trace_func(event, file, line, id, binding, klass) if trace?
- context(Thread.current).check_suspend
- @file = file
- @line = line
- case event
- when 'line'
- frame_set_pos(file, line)
- if !@no_step or @frames.size == @no_step
- @stop_next -= 1
- @stop_next = -1 if @stop_next < 0
- elsif @frames.size < @no_step
- @stop_next = 0 # break here before leaving...
- else
- # nothing to do. skipped.
- end
- if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
- @no_step = nil
- suspend_all
- debug_command(file, line, id, binding)
- end
-
- when 'call'
- @frames.unshift [binding, file, line, id]
- if check_break_points(file, klass, id.id2name, binding, id)
- suspend_all
- debug_command(file, line, id, binding)
- end
-
- when 'c-call'
- frame_set_pos(file, line)
-
- when 'class'
- @frames.unshift [binding, file, line, id]
-
- when 'return', 'end'
- if @frames.size == @finish_pos
- @stop_next = 1
- @finish_pos = 0
- end
- @frames.shift
-
- when 'raise'
- excn_handle(file, line, id, binding)
-
- end
- @last_file = file
- end
- end
-
- trap("INT") { DEBUGGER__.interrupt }
- @last_thread = Thread::main
- @max_thread = 1
- @thread_list = {Thread::main => 1}
- @break_points = []
- @display = []
- @waiting = []
- @stdout = STDOUT
-
- class << DEBUGGER__
- # Returns the IO used as stdout. Defaults to STDOUT
- def stdout
- @stdout
- end
-
- # Sets the IO used as stdout. Defaults to STDOUT
- def stdout=(s)
- @stdout = s
- end
-
- # Returns the display expression list
- #
- # See DEBUGGER__ for more usage
- def display
- @display
- end
-
- # Returns the list of break points where execution will be stopped.
- #
- # See DEBUGGER__ for more usage
- def break_points
- @break_points
- end
-
- # Returns the list of waiting threads.
- #
- # When stepping through the traces of a function, thread gets suspended, to
- # be resumed later.
- def waiting
- @waiting
- end
-
- def set_trace( arg )
- MUTEX.synchronize do
- make_thread_list
- for th, in @thread_list
- context(th).set_trace arg
- end
- end
- arg
- end
-
- def set_last_thread(th)
- @last_thread = th
- end
-
- def suspend
- MUTEX.synchronize do
- make_thread_list
- for th, in @thread_list
- next if th == Thread.current
- context(th).set_suspend
- end
- end
- # Schedule other threads to suspend as soon as possible.
- Thread.pass
- end
-
- def resume
- MUTEX.synchronize do
- make_thread_list
- @thread_list.each do |th,|
- next if th == Thread.current
- context(th).clear_suspend
- end
- waiting.each do |th|
- th.run
- end
- waiting.clear
- end
- # Schedule other threads to restart as soon as possible.
- Thread.pass
- end
-
- def context(thread=Thread.current)
- c = thread[:__debugger_data__]
- unless c
- thread[:__debugger_data__] = c = Context.new
- end
- c
- end
-
- def interrupt
- context(@last_thread).stop_next
- end
-
- def get_thread(num)
- th = @thread_list.key(num)
- unless th
- @stdout.print "No thread ##{num}\n"
- throw :debug_error
- end
- th
- end
-
- def thread_list(num)
- th = get_thread(num)
- if th == Thread.current
- @stdout.print "+"
- else
- @stdout.print " "
- end
- @stdout.printf "%d ", num
- @stdout.print th.inspect, "\t"
- file = context(th).instance_eval{@file}
- if file
- @stdout.print file,":",context(th).instance_eval{@line}
- end
- @stdout.print "\n"
- end
-
- # Prints all threads in @thread_list to @stdout. Returns a sorted array of
- # values from the @thread_list hash.
- #
- # While in the debugger you can list all of
- # the threads with: <b>DEBUGGER__.thread_list_all</b>
- #
- # (rdb:1) DEBUGGER__.thread_list_all
- # +1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3
- # 2 #<Thread:0x007fb23218a538 debug_me.rb.rb:3 sleep>
- # 3 #<Thread:0x007fb23218b0f0 debug_me.rb.rb:3 sleep>
- # [1, 2, 3]
- #
- # Your current thread is indicated by a <b>+</b>
- #
- # Additionally you can list all threads with <b>th l</b>
- #
- # (rdb:1) th l
- # +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3
- # 2 #<Thread:0x007f9932938230 debug_me.rb:3 sleep> debug_me.rb:3
- # 3 #<Thread:0x007f9932938e10 debug_me.rb:3 sleep> debug_me.rb:3
- #
- # See DEBUGGER__ for more usage.
-
- def thread_list_all
- for th in @thread_list.values.sort
- thread_list(th)
- end
- end
-
- def make_thread_list
- hash = {}
- for th in Thread::list
- if @thread_list.key? th
- hash[th] = @thread_list[th]
- else
- @max_thread += 1
- hash[th] = @max_thread
- end
- end
- @thread_list = hash
- end
-
- def debug_thread_info(input, binding)
- case input
- when /^l(?:ist)?/
- make_thread_list
- thread_list_all
-
- when /^c(?:ur(?:rent)?)?$/
- make_thread_list
- thread_list(@thread_list[Thread.current])
-
- when /^(?:sw(?:itch)?\s+)?(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- else
- thread_list(@thread_list[th])
- context(th).stop_next
- th.run
- return :cont
- end
-
- when /^stop\s+(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- elsif th.stop?
- @stdout.print "Already stopped.\n"
- else
- thread_list(@thread_list[th])
- context(th).suspend
- end
-
- when /^resume\s+(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- elsif !th.stop?
- @stdout.print "Already running."
- else
- thread_list(@thread_list[th])
- th.run
- end
- end
- end
- end
-
- stdout.printf "Debug.rb\n"
- stdout.printf "Emacs support available.\n\n"
- RubyVM::InstructionSequence.compile_option = {
- trace_instruction: true
- }
- set_trace_func proc { |event, file, line, id, binding, klass, *rest|
- DEBUGGER__.context.trace_func event, file, line, id, binding, klass
- }
-end
diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec
index 0ac525705b..c9d7e40a51 100644
--- a/lib/drb/drb.gemspec
+++ b/lib/drb/drb.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
spec.summary = %q{Distributed object system for Ruby}
spec.description = %q{Distributed object system for Ruby}
spec.homepage = "https://github.com/ruby/drb"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
@@ -37,8 +37,6 @@ Gem::Specification.new do |spec|
lib/drb/version.rb
lib/drb/weakidconv.rb
]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "ruby2_keywords"
diff --git a/lib/drb/version.rb b/lib/drb/version.rb
index ffba81d48e..efaccf0319 100644
--- a/lib/drb/version.rb
+++ b/lib/drb/version.rb
@@ -1,3 +1,3 @@
module DRb
- VERSION = "2.0.4"
+ VERSION = "2.1.0"
end
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
index 696df76ff9..8392979e24 100644
--- a/lib/error_highlight/base.rb
+++ b/lib/error_highlight/base.rb
@@ -148,7 +148,7 @@ module ErrorHighlight
nd_recv, mid, nd_args = @node.children
lineno = nd_recv.last_lineno
lines = @fetch[lineno, @node.last_lineno]
- if mid == :[] && lines.match(/\G\s*(\[(?:\s*\])?)/, nd_recv.last_column)
+ if mid == :[] && lines.match(/\G[\s)]*(\[(?:\s*\])?)/, nd_recv.last_column)
@beg_column = $~.begin(1)
@snippet = lines[/.*\n/]
@beg_lineno = @end_lineno = lineno
@@ -157,11 +157,11 @@ module ErrorHighlight
@end_column = $~.end(0)
end
else
- if lines.match(/\G\s*?\[\s*\]/, nd_recv.last_column)
+ if lines.match(/\G[\s)]*?\[\s*\]/, nd_recv.last_column)
@end_column = $~.end(0)
end
end
- elsif lines.match(/\G\s*?(\&?\.)(\s*?)(#{ Regexp.quote(mid) }).*\n/, nd_recv.last_column)
+ elsif lines.match(/\G[\s)]*?(\&?\.)(\s*?)(#{ Regexp.quote(mid) }).*\n/, nd_recv.last_column)
lines = $` + $&
@beg_column = $~.begin($2.include?("\n") ? 3 : 1)
@end_column = $~.end(3)
@@ -207,16 +207,16 @@ module ErrorHighlight
nd_recv, mid, nd_args = @node.children
*nd_args, _nd_last_arg, _nil = nd_args.children
fetch_line(nd_recv.last_lineno)
- if mid == :[]= && @snippet.match(/\G\s*(\[)/, nd_recv.last_column)
+ if mid == :[]= && @snippet.match(/\G[\s)]*(\[)/, nd_recv.last_column)
@beg_column = $~.begin(1)
args_last_column = $~.end(0)
if nd_args.last && nd_recv.last_lineno == nd_args.last.last_lineno
args_last_column = nd_args.last.last_column
end
- if @snippet.match(/\s*\]\s*=/, args_last_column)
+ if @snippet.match(/[\s)]*\]\s*=/, args_last_column)
@end_column = $~.end(0)
end
- elsif @snippet.match(/\G\s*(\.\s*#{ Regexp.quote(mid.to_s.sub(/=\z/, "")) }\s*=)/, nd_recv.last_column)
+ elsif @snippet.match(/\G[\s)]*(\.\s*#{ Regexp.quote(mid.to_s.sub(/=\z/, "")) }\s*=)/, nd_recv.last_column)
@beg_column = $~.begin(1)
@end_column = $~.end(1)
end
@@ -232,7 +232,7 @@ module ErrorHighlight
def spot_attrasgn_for_args
nd_recv, mid, nd_args = @node.children
fetch_line(nd_recv.last_lineno)
- if mid == :[]= && @snippet.match(/\G\s*\[/, nd_recv.last_column)
+ if mid == :[]= && @snippet.match(/\G[\s)]*\[/, nd_recv.last_column)
@beg_column = $~.end(0)
if nd_recv.last_lineno == nd_args.last_lineno
@end_column = nd_args.last_column
@@ -254,7 +254,7 @@ module ErrorHighlight
fetch_line(nd_recv.last_lineno)
if nd_arg
# binary operator
- if @snippet.match(/\G\s*(#{ Regexp.quote(op) })/, nd_recv.last_column)
+ if @snippet.match(/\G[\s)]*(#{ Regexp.quote(op) })/, nd_recv.last_column)
@beg_column = $~.begin(1)
@end_column = $~.end(1)
end
@@ -330,7 +330,7 @@ module ErrorHighlight
def spot_op_asgn1_for_name
nd_recv, op, nd_args, _nd_rhs = @node.children
fetch_line(nd_recv.last_lineno)
- if @snippet.match(/\G\s*(\[)/, nd_recv.last_column)
+ if @snippet.match(/\G[\s)]*(\[)/, nd_recv.last_column)
bracket_beg_column = $~.begin(1)
args_last_column = $~.end(0)
if nd_args && nd_recv.last_lineno == nd_args.last_lineno
@@ -377,7 +377,7 @@ module ErrorHighlight
def spot_op_asgn2_for_name
nd_recv, _qcall, attr, op, _nd_rhs = @node.children
fetch_line(nd_recv.last_lineno)
- if @snippet.match(/\G\s*(\.)\s*#{ Regexp.quote(attr) }()\s*(#{ Regexp.quote(op) })(=)/, nd_recv.last_column)
+ if @snippet.match(/\G[\s)]*(\.)\s*#{ Regexp.quote(attr) }()\s*(#{ Regexp.quote(op) })(=)/, nd_recv.last_column)
case @name
when attr
@beg_column = $~.begin(1)
diff --git a/lib/error_highlight/core_ext.rb b/lib/error_highlight/core_ext.rb
index 1e91debc0c..1ae180aeac 100644
--- a/lib/error_highlight/core_ext.rb
+++ b/lib/error_highlight/core_ext.rb
@@ -16,7 +16,7 @@ module ErrorHighlight
loc = locs.first
begin
- node = RubyVM::AbstractSyntaxTree.of(loc, save_script_lines: true)
+ node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
opts = {}
case self
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 69de458665..3333307e22 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -211,21 +211,11 @@ module FileUtils
list.each do |item|
path = remove_trailing_slash(item)
- # optimize for the most common case
- begin
- fu_mkdir path, mode
- next
- rescue SystemCallError
- next if File.directory?(path)
- end
-
stack = []
- until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/"
+ until File.directory?(path)
stack.push path
path = File.dirname(path)
- break if File.directory?(path)
end
- stack.pop if path == stack.last # root directory should exist
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
diff --git a/lib/find.gemspec b/lib/find.gemspec
index fff0f706cd..3f0aadcdae 100644
--- a/lib/find.gemspec
+++ b/lib/find.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "find"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ['Kazuki Tsujimoto']
spec.email = ['kazuki@callcc.net']
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index 7fff54b9d0..5df798f5d7 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -112,13 +112,12 @@ class IPAddr
def self.ntop(addr)
case addr.size
when 4
- s = addr.unpack('C4').join('.')
+ addr.unpack('C4').join('.')
when 16
- s = IN6FORMAT % addr.unpack('n8')
+ IN6FORMAT % addr.unpack('n8')
else
raise AddressFamilyError, "unsupported address family"
end
- return s
end
# Returns a new ipaddr built by bitwise AND.
@@ -168,34 +167,17 @@ class IPAddr
# net1 = IPAddr.new("192.168.2.0/24")
# net2 = IPAddr.new("192.168.2.100")
# net3 = IPAddr.new("192.168.3.0")
+ # net4 = IPAddr.new("192.168.2.0/16")
# p net1.include?(net2) #=> true
# p net1.include?(net3) #=> false
+ # p net1.include?(net4) #=> false
+ # p net4.include?(net1) #=> true
def include?(other)
other = coerce_other(other)
- if ipv4_mapped?
- if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
- return false
- end
- mask_addr = (@mask_addr & IN4MASK)
- addr = (@addr & IN4MASK)
- family = Socket::AF_INET
- else
- mask_addr = @mask_addr
- addr = @addr
- family = @family
- end
- if other.ipv4_mapped?
- other_addr = (other.to_i & IN4MASK)
- other_family = Socket::AF_INET
- else
- other_addr = other.to_i
- other_family = other.family
- end
-
- if family != other_family
- return false
- end
- return ((addr & mask_addr) == (other_addr & mask_addr))
+ return false unless other.family == family
+ range = to_range
+ other = other.to_range
+ range.begin <= other.begin && range.end >= other.end
end
alias === include?
@@ -232,7 +214,13 @@ class IPAddr
# Returns a string containing the IP address representation in
# canonical form.
def to_string
- return _to_string(@addr)
+ str = _to_string(@addr)
+
+ if @family == Socket::AF_INET6
+ str << zone_id.to_s
+ end
+
+ return str
end
# Returns a network byte ordered string form of the IP address.
@@ -328,9 +316,11 @@ class IPAddr
# into an IPv4-mapped IPv6 address.
def ipv4_mapped
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address"
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
end
- return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
+ clone = self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
+ clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
+ clone
end
# Returns a new ipaddr built by converting the native IPv4 address
@@ -338,7 +328,7 @@ class IPAddr
def ipv4_compat
warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address"
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
end
return self.clone.set(@addr, Socket::AF_INET6)
end
@@ -369,7 +359,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC3172.
def ip6_arpa
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address"
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
end
return _reverse + ".ip6.arpa"
end
@@ -377,7 +367,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC1886.
def ip6_int
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address"
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
end
return _reverse + ".ip6.int"
end
@@ -404,7 +394,7 @@ class IPAddr
# Returns a hash value used by Hash, Set, and Array classes
def hash
- return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
+ return ([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1)
end
# Creates a Range object for the network address.
@@ -448,7 +438,7 @@ class IPAddr
when Integer
mask!(prefix)
else
- raise InvalidPrefixError, "prefix must be an integer"
+ raise InvalidPrefixError, "prefix must be an integer: #{@addr}"
end
end
@@ -460,11 +450,42 @@ class IPAddr
af = "IPv4"
when Socket::AF_INET6
af = "IPv6"
+ zone_id = @zone_id.to_s
else
raise AddressFamilyError, "unsupported address family"
end
- return sprintf("#<%s: %s:%s/%s>", self.class.name,
- af, _to_string(@addr), _to_string(@mask_addr))
+ return sprintf("#<%s: %s:%s%s/%s>", self.class.name,
+ af, _to_string(@addr), zone_id, _to_string(@mask_addr))
+ end
+
+ # Returns the netmask in string format e.g. 255.255.0.0
+ def netmask
+ _to_string(@mask_addr)
+ end
+
+ # Returns the IPv6 zone identifier, if present.
+ # Raises InvalidAddressError if not an IPv6 address.
+ def zone_id
+ if @family == Socket::AF_INET6
+ @zone_id
+ else
+ raise InvalidAddressError, "not an IPv6 address"
+ end
+ end
+
+ # Returns the IPv6 zone identifier, if present.
+ # Raises InvalidAddressError if not an IPv6 address.
+ def zone_id=(zid)
+ if @family == Socket::AF_INET6
+ case zid
+ when nil, /\A%(\w+)\z/
+ @zone_id = zid
+ else
+ raise InvalidAddressError, "invalid zone identifier for address"
+ end
+ else
+ raise InvalidAddressError, "not an IPv6 address"
+ end
end
protected
@@ -476,11 +497,11 @@ class IPAddr
case family[0] ? family[0] : @family
when Socket::AF_INET
if addr < 0 || addr > IN4MASK
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
when Socket::AF_INET6
if addr < 0 || addr > IN6MASK
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
else
raise AddressFamilyError, "unsupported address family"
@@ -496,17 +517,20 @@ class IPAddr
def mask!(mask)
case mask
when String
- if mask =~ /\A\d+\z/
+ case mask
+ when /\A(0|[1-9]+\d*)\z/
prefixlen = mask.to_i
+ when /\A\d+\z/
+ raise InvalidPrefixError, "leading zeros in prefix"
else
m = IPAddr.new(mask)
if m.family != @family
- raise InvalidPrefixError, "address family is not same"
+ raise InvalidPrefixError, "address family is not same: #{@addr}"
end
@mask_addr = m.to_i
n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
unless ((n + 1) & n).zero?
- raise InvalidPrefixError, "invalid mask #{mask}"
+ raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}"
end
@addr &= @mask_addr
return self
@@ -517,13 +541,13 @@ class IPAddr
case @family
when Socket::AF_INET
if prefixlen < 0 || prefixlen > 32
- raise InvalidPrefixError, "invalid length"
+ raise InvalidPrefixError, "invalid length: #{@addr}"
end
masklen = 32 - prefixlen
@mask_addr = ((IN4MASK >> masklen) << masklen)
when Socket::AF_INET6
if prefixlen < 0 || prefixlen > 128
- raise InvalidPrefixError, "invalid length"
+ raise InvalidPrefixError, "invalid length: #{@addr}"
end
masklen = 128 - prefixlen
@mask_addr = ((IN6MASK >> masklen) << masklen)
@@ -567,11 +591,16 @@ class IPAddr
raise AddressFamilyError, "unsupported address family: #{family}"
end
end
- prefix, prefixlen = addr.split('/')
+ prefix, prefixlen = addr.split('/', 2)
if prefix =~ /\A\[(.*)\]\z/i
prefix = $1
family = Socket::AF_INET6
end
+ if prefix =~ /\A(.*)(%\w+)\z/
+ prefix = $1
+ zone_id = $2
+ family = Socket::AF_INET6
+ end
# It seems AI_NUMERICHOST doesn't do the job.
#Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
# Socket::AI_NUMERICHOST)
@@ -586,6 +615,7 @@ class IPAddr
@addr = in6_addr(prefix)
@family = Socket::AF_INET6
end
+ @zone_id = zone_id
if family != Socket::AF_UNSPEC && @family != family
raise AddressFamilyError, "address family mismatch"
end
@@ -594,8 +624,6 @@ class IPAddr
else
@mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
end
- rescue InvalidAddressError => e
- raise e.class, "#{e.message}: #{addr}"
end
def coerce_other(other)
@@ -618,8 +646,8 @@ class IPAddr
octets = m.captures
end
octets.inject(0) { |i, s|
- (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address"
- s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous"
+ (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
+ s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
i << 8 | n
}
end
@@ -636,19 +664,19 @@ class IPAddr
right = ''
when RE_IPV6ADDRLIKE_COMPRESSED
if $4
- left.count(':') <= 6 or raise InvalidAddressError, "invalid address"
+ left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{@addr}"
addr = in_addr($~[4,4])
left = $1
right = $3 + '0:0'
else
left.count(':') <= ($1.empty? || $2.empty? ? 8 : 7) or
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
left = $1
right = $2
addr = 0
end
else
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
l = left.split(':')
r = right.split(':')
diff --git a/lib/irb.rb b/lib/irb.rb
index 661c550486..6b296448db 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -62,8 +62,14 @@ require_relative "irb/easter-egg"
# -W[level=2] Same as `ruby -W`
# --context-mode n Set n[0-4] to method to create Binding Object,
# when new workspace was created
-# --echo Show result(default)
+# --echo Show result (default)
# --noecho Don't show result
+# --echo-on-assignment
+# Show result on assignment
+# --noecho-on-assignment
+# Don't show result on assignment
+# --truncate-echo-on-assignment
+# Show truncated result on assignment (default)
# --inspect Use `inspect' for output
# --noinspect Don't use inspect for output
# --multiline Use multiline editor module
@@ -72,6 +78,8 @@ require_relative "irb/easter-egg"
# --nosingleline Don't use singleline editor module
# --colorize Use colorization
# --nocolorize Don't use colorization
+# --autocomplete Use autocompletion
+# --noautocomplete Don't use autocompletion
# --prompt prompt-mode/--prompt-mode prompt-mode
# Switch prompt mode. Pre-defined prompt modes are
# `default', `simple', `xmp' and `inf-ruby'
@@ -114,6 +122,7 @@ require_relative "irb/easter-egg"
# IRB.conf[:USE_SINGLELINE] = nil
# IRB.conf[:USE_COLORIZE] = true
# IRB.conf[:USE_TRACER] = false
+# IRB.conf[:USE_AUTOCOMPLETE] = true
# IRB.conf[:IGNORE_SIGINT] = true
# IRB.conf[:IGNORE_EOF] = false
# IRB.conf[:PROMPT_MODE] = :DEFAULT
@@ -604,7 +613,7 @@ module IRB
ret = conv.primitive_convert(str, dst)
case ret
when :invalid_byte_sequence
- conv.insert_output(conf.primitive_errinfo[3].dump[1..-2])
+ conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
redo
when :undefined_conversion
c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
@@ -666,6 +675,8 @@ module IRB
lines = lines.reverse if order == :bottom
lines.map{ |l| l + "\n" }.join
}
+ # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
+ message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
puts message
end
print "Maybe IRB bug!\n" if irb_bug
@@ -856,7 +867,7 @@ module IRB
# If the expression is invalid, Ripper.sexp should return nil which will
# result in false being returned. Any valid expression should return an
- # s-expression where the second selement of the top level array is an
+ # s-expression where the second element of the top level array is an
# array of parsed expressions. The first element of each expression is the
# expression's type.
verbose, $VERBOSE = $VERBOSE, nil
diff --git a/lib/irb/cmd/help.rb b/lib/irb/cmd/help.rb
index 0629479e92..d82e78fb57 100644
--- a/lib/irb/cmd/help.rb
+++ b/lib/irb/cmd/help.rb
@@ -17,7 +17,8 @@ module IRB
class Help < Nop
def execute(*names)
require 'rdoc/ri/driver'
- IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new)
+ opts = RDoc::RI::Driver.process_args([])
+ IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new(opts))
rescue LoadError, SystemExit
IRB::ExtendCommand::Help.remove_method(:execute)
# raise NoMethodError in ensure
diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb
index feff8315f6..dcba1d1c71 100644
--- a/lib/irb/cmd/show_source.rb
+++ b/lib/irb/cmd/show_source.rb
@@ -61,15 +61,12 @@ module IRB
lex = RubyLex.new
lines = File.read(file).lines[(first_line - 1)..-1]
tokens = RubyLex.ripper_lex_without_warning(lines.join)
-
- code = +""
prev_tokens = []
# chunk with line number
tokens.chunk { |tok| tok[0][0] }.each do |lnum, chunk|
- code << lines[lnum]
+ code = lines[0..lnum].join
prev_tokens.concat chunk
-
continue = lex.process_continue(prev_tokens)
code_block_open = lex.check_code_block(code, prev_tokens)
if !continue && !code_block_open
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
index d1bb82122e..9121174a50 100644
--- a/lib/irb/completion.rb
+++ b/lib/irb/completion.rb
@@ -38,16 +38,48 @@ module IRB
BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
- def self.retrieve_files_to_require_from_load_path
- @@files_from_load_path ||= $LOAD_PATH.flat_map { |path|
- begin
- Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
- rescue Errno::ENOENT
- []
+ def self.absolute_path?(p) # TODO Remove this method after 2.6 EOL.
+ if File.respond_to?(:absolute_path?)
+ File.absolute_path?(p)
+ else
+ if File.absolute_path(p) == p
+ true
+ else
+ false
end
- }.uniq.map { |path|
- path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
- }
+ end
+ end
+
+ def self.retrieve_gem_and_system_load_path
+ gem_paths = Gem::Specification.latest_specs(true).map { |s|
+ s.require_paths.map { |p|
+ if absolute_path?(p)
+ p
+ else
+ File.join(s.full_gem_path, p)
+ end
+ }
+ }.flatten if defined?(Gem::Specification)
+ (gem_paths.to_a | $LOAD_PATH).sort
+ end
+
+ def self.retrieve_files_to_require_from_load_path
+ @@files_from_load_path ||=
+ (
+ shortest = []
+ rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result|
+ begin
+ names = Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
+ rescue Errno::ENOENT
+ nil
+ end
+ next if names.empty?
+ names.map! { |n| n.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '') }.sort!
+ shortest << names.shift
+ result.concat(names)
+ }
+ shortest.sort! | rest
+ )
end
def self.retrieve_files_to_require_relative_from_current_dir
@@ -160,12 +192,12 @@ module IRB
sym = $1
candidates = Symbol.all_symbols.collect do |s|
":" + s.id2name.encode(Encoding.default_external)
- rescue Encoding::UndefinedConversionError
+ rescue EncodingError
# ignore
end
candidates.grep(/^#{Regexp.quote(sym)}/)
- when /^::([A-Z][^:\.\(]*)$/
+ when /^::([A-Z][^:\.\(\)]*)$/
# Absolute Constant or class methods
receiver = $1
candidates = Object.constants.collect{|m| m.to_s}
@@ -258,7 +290,7 @@ module IRB
all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
end
- when /^([^."].*)(\.|::)([^.]*)$/
+ when /^([^.:"].*)(\.|::)([^.]*)$/
# variable.func or func.func
receiver = $1
sep = $2
@@ -296,7 +328,8 @@ module IRB
candidates.uniq!
end
if doc_namespace
- "#{rec.class.name}#{sep}#{candidates.find{ |i| i == message }}"
+ rec_class = rec.is_a?(Module) ? rec : rec.class
+ "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}"
else
select_message(receiver, message, candidates, sep)
end
@@ -315,12 +348,19 @@ module IRB
end
else
- candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s}
- candidates |= ReservedWords
-
if doc_namespace
- candidates.find{ |i| i == input }
+ vars = eval("local_variables | instance_variables", bind).collect{|m| m.to_s}
+ perfect_match_var = vars.find{|m| m.to_s == input}
+ if perfect_match_var
+ eval("#{perfect_match_var}.class.name", bind)
+ else
+ candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s}
+ candidates |= ReservedWords
+ candidates.find{ |i| i == input }
+ end
else
+ candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s}
+ candidates |= ReservedWords
candidates.grep(/^#{Regexp.quote(input)}/)
end
end
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 0d358de6ff..0a46c1b1d4 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -54,6 +54,7 @@ module IRB
@use_multiline = nil
end
@use_colorize = IRB.conf[:USE_COLORIZE]
+ @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE]
@verbose = IRB.conf[:VERBOSE]
@io = nil
@@ -124,6 +125,8 @@ module IRB
end
self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY]
+ @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS]
+
@echo = IRB.conf[:ECHO]
if @echo.nil?
@echo = true
@@ -147,18 +150,18 @@ module IRB
# The toplevel workspace, see #home_workspace
attr_reader :workspace_home
- # WorkSpace in the current context
+ # WorkSpace in the current context.
attr_accessor :workspace
- # The current thread in this context
+ # The current thread in this context.
attr_reader :thread
- # The current input method
+ # The current input method.
#
# Can be either StdioInputMethod, ReadlineInputMethod,
# ReidlineInputMethod, FileInputMethod or other specified when the
# context is created. See ::new for more # information on +input_method+.
attr_accessor :io
- # Current irb session
+ # Current irb session.
attr_accessor :irb
# A copy of the default <code>IRB.conf[:AP_NAME]</code>
attr_accessor :ap_name
@@ -185,20 +188,22 @@ module IRB
#
# A copy of the default <code>IRB.conf[:USE_COLORIZE]</code>
attr_reader :use_colorize
+ # A copy of the default <code>IRB.conf[:USE_AUTOCOMPLETE]</code>
+ attr_reader :use_autocomplete
# A copy of the default <code>IRB.conf[:INSPECT_MODE]</code>
attr_reader :inspect_mode
# A copy of the default <code>IRB.conf[:PROMPT_MODE]</code>
attr_reader :prompt_mode
- # Standard IRB prompt
+ # Standard IRB prompt.
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_i
- # IRB prompt for continuated strings
+ # IRB prompt for continuated strings.
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_s
- # IRB prompt for continuated statement (e.g. immediately after an +if+)
+ # IRB prompt for continuated statement. (e.g. immediately after an +if+)
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_c
@@ -238,6 +243,9 @@ module IRB
#
# If set to +false+, <code>^D</code> will quit irb.
attr_accessor :ignore_eof
+ # Specify the installation locations of the ri file to be displayed in the
+ # document dialog.
+ attr_accessor :extra_doc_dirs
# Whether to echo the return value to output or not.
#
# Uses <code>IRB.conf[:ECHO]</code> if available, or defaults to +true+.
@@ -249,7 +257,7 @@ module IRB
# puts "omg"
# # omg
attr_accessor :echo
- # Whether to echo for assignment expressions
+ # Whether to echo for assignment expressions.
#
# If set to +false+, the value of assignment will not be shown.
#
@@ -261,13 +269,28 @@ module IRB
#
# a = "omg"
# #=> omg
+ #
# a = "omg" * 10
# #=> omgomgomgomgomgomgomg...
+ #
# IRB.CurrentContext.echo_on_assignment = false
# a = "omg"
+ #
# IRB.CurrentContext.echo_on_assignment = true
- # a = "omg"
+ # a = "omg" * 10
# #=> omgomgomgomgomgomgomgomgomgomg
+ #
+ # To set the behaviour of showing on assignment in irb:
+ #
+ # IRB.conf[:ECHO_ON_ASSIGNMENT] = :truncate or true or false
+ #
+ # or
+ #
+ # irb_context.echo_on_assignment = :truncate or true or false
+ #
+ # or
+ #
+ # IRB.CurrentContext.echo_on_assignment = :truncate or true or false
attr_accessor :echo_on_assignment
# Whether a newline is put before multiline output.
#
@@ -311,6 +334,8 @@ module IRB
alias use_readline? use_singleline
# Alias for #use_colorize
alias use_colorize? use_colorize
+ # Alias for #use_autocomplete
+ alias use_autocomplete? use_autocomplete
# Alias for #rc
alias rc? rc
alias ignore_sigint? ignore_sigint
@@ -366,6 +391,7 @@ module IRB
@prompt_c = pconf[:PROMPT_C]
@prompt_n = pconf[:PROMPT_N]
@return_format = pconf[:RETURN]
+ @return_format = "%s\n" if @return_format == nil
if ai = pconf.include?(:AUTO_INDENT)
@auto_indent_mode = ai
else
@@ -458,6 +484,8 @@ module IRB
# Exits the current session, see IRB.irb_exit
def exit(ret = 0)
IRB.irb_exit(@irb, ret)
+ rescue UncaughtThrowError
+ super
end
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
index 5923c54a29..d2baee2017 100644
--- a/lib/irb/init.rb
+++ b/lib/irb/init.rb
@@ -45,11 +45,13 @@ module IRB # :nodoc:
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
@CONF[:USE_COLORIZE] = !ENV['NO_COLOR']
+ @CONF[:USE_AUTOCOMPLETE] = true
@CONF[:INSPECT_MODE] = true
@CONF[:USE_TRACER] = false
@CONF[:USE_LOADER] = false
@CONF[:IGNORE_SIGINT] = true
@CONF[:IGNORE_EOF] = false
+ @CONF[:EXTRA_DOC_DIRS] = []
@CONF[:ECHO] = nil
@CONF[:ECHO_ON_ASSIGNMENT] = nil
@CONF[:VERBOSE] = nil
@@ -256,6 +258,9 @@ module IRB # :nodoc:
@CONF[:USE_MULTILINE] = true
when "--nomultiline", "--noreidline"
@CONF[:USE_MULTILINE] = false
+ when /^--extra-doc-dir(?:=(.+))?/
+ opt = $1 || argv.shift
+ @CONF[:EXTRA_DOC_DIRS] << opt
when "--echo"
@CONF[:ECHO] = true
when "--noecho"
@@ -274,6 +279,10 @@ module IRB # :nodoc:
@CONF[:USE_COLORIZE] = true
when "--nocolorize"
@CONF[:USE_COLORIZE] = false
+ when "--autocomplete"
+ @CONF[:USE_AUTOCOMPLETE] = true
+ when "--noautocomplete"
+ @CONF[:USE_AUTOCOMPLETE] = false
when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
opt = $1 || argv.shift
prompt_mode = opt.upcase.tr("-", "_").intern
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
index 1854567a2d..dc95065f97 100644
--- a/lib/irb/input-method.rb
+++ b/lib/irb/input-method.rb
@@ -14,6 +14,7 @@ require_relative 'magic-file'
require_relative 'completion'
require 'io/console'
require 'reline'
+require 'rdoc'
module IRB
STDIN_FILE_NAME = "(line)" # :nodoc:
@@ -264,7 +265,8 @@ module IRB
class ReidlineInputMethod < InputMethod
include Reline
- # Creates a new input method object using Readline
+
+ # Creates a new input method object using Reline
def initialize
IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
super
@@ -294,6 +296,10 @@ module IRB
end
end
Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc
+ Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
+ if IRB.conf[:USE_AUTOCOMPLETE]
+ Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
end
def check_termination(&block)
@@ -308,6 +314,97 @@ module IRB
@auto_indent_proc = block
end
+ SHOW_DOC_DIALOG = ->() {
+ dialog.trap_key = nil
+ alt_d = [
+ [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
+ [195, 164] # The "ä" that appears when Alt+d is pressed on xterm.
+ ]
+
+ if just_cursor_moving and completion_journey_data.nil?
+ return nil
+ end
+ cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
+ return nil if result.nil? or pointer.nil? or pointer < 0
+ name = result[pointer]
+ name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true)
+
+ options = {}
+ options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
+ driver = RDoc::RI::Driver.new(options)
+
+ if key.match?(dialog.name)
+ begin
+ driver.display_names([name])
+ rescue RDoc::RI::Driver::NotFoundError
+ end
+ end
+
+ begin
+ name = driver.expand_name(name)
+ rescue RDoc::RI::Driver::NotFoundError
+ return nil
+ rescue
+ return nil # unknown error
+ end
+ doc = nil
+ used_for_class = false
+ if not name =~ /#|\./
+ found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
+ if not found.empty?
+ doc = driver.class_document(name, found, klasses, includes, extends)
+ used_for_class = true
+ end
+ end
+ unless used_for_class
+ doc = RDoc::Markup::Document.new
+ begin
+ driver.add_method(doc, name)
+ rescue RDoc::RI::Driver::NotFoundError
+ doc = nil
+ rescue
+ return nil # unknown error
+ end
+ end
+ return nil if doc.nil?
+ width = 40
+
+ right_x = cursor_pos_to_render.x + autocomplete_dialog.width
+ if right_x + width > screen_width
+ right_width = screen_width - (right_x + 1)
+ left_x = autocomplete_dialog.column - width
+ left_x = 0 if left_x < 0
+ left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
+ if right_width.positive? and left_width.positive?
+ if right_width >= left_width
+ width = right_width
+ x = right_x
+ else
+ width = left_width
+ x = left_x
+ end
+ elsif right_width.positive? and left_width <= 0
+ width = right_width
+ x = right_x
+ elsif right_width <= 0 and left_width.positive?
+ width = left_width
+ x = left_x
+ else # Both are negative width.
+ return nil
+ end
+ else
+ x = right_x
+ end
+ formatter = RDoc::Markup::ToAnsi.new
+ formatter.width = width
+ dialog.trap_key = alt_d
+ message = 'Press Alt+d to read the full document'
+ contents = [message] + doc.accept(formatter).split("\n")
+
+ y = cursor_pos_to_render.y
+ DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
+ }
+
# Reads the next line from this input method.
#
# See IO#gets for more information.
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
index 6cb3df0dc2..594fae7ff6 100644
--- a/lib/irb/irb.gemspec
+++ b/lib/irb/irb.gemspec
@@ -36,5 +36,5 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
- spec.add_dependency "reline", ">= 0.2.5"
+ spec.add_dependency "reline", ">= 0.2.8.pre.11"
end
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
index 9c3ea859ad..939dc38975 100644
--- a/lib/irb/lc/help-message
+++ b/lib/irb/lc/help-message
@@ -20,8 +20,15 @@ Usage: irb.rb [options] [programfile] [arguments]
-W[level=2] Same as `ruby -W`
--context-mode n Set n[0-4] to method to create Binding Object,
when new workspace was created
- --echo Show result(default)
+ --extra-doc-dir Add an extra doc dir for the doc dialog
+ --echo Show result (default)
--noecho Don't show result
+ --echo-on-assignment
+ Show result on assignment
+ --noecho-on-assignment
+ Don't show result on assignment
+ --truncate-echo-on-assignment
+ Show truncated result on assignment (default)
--inspect Use `inspect' for output
--noinspect Don't use inspect for output
--multiline Use multiline editor module
@@ -30,6 +37,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--nosingleline Don't use singleline editor module
--colorize Use colorization
--nocolorize Don't use colorization
+ --autocomplete Use autocompletion
+ --noautocomplete Don't use autocompletion
--prompt prompt-mode/--prompt-mode prompt-mode
Switch prompt mode. Pre-defined prompt modes are
`default', `simple', `xmp' and `inf-ruby'
diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message
index 9794a8e24e..238535afb7 100644
--- a/lib/irb/lc/ja/help-message
+++ b/lib/irb/lc/ja/help-message
@@ -29,6 +29,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--nosingleline シングルラインエディタを利用しない.
--colorize 色付けを利用する.
--nocolorize 色付けを利用しない.
+ --autocomplete オートコンプリートを利用する.
+ --noautocomplete オートコンプリートを利用しない.
--prompt prompt-mode/--prompt-mode prompt-mode
プロンプトモードを切替えます. 現在定義されているプ
ロンプトモードは, default, simple, xmp, inf-rubyが
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index f744f36155..d7ac17bd79 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -207,7 +207,7 @@ class RubyLex
last_line = lines[line_index]&.byteslice(0, byte_pointer)
code += last_line if last_line
@tokens = self.class.ripper_lex_without_warning(code, context: context)
- corresponding_token_depth = check_corresponding_token_depth
+ corresponding_token_depth = check_corresponding_token_depth(lines, line_index)
if corresponding_token_depth
corresponding_token_depth
else
@@ -477,7 +477,7 @@ class RubyLex
def take_corresponding_syntax_to_kw_do(tokens, index)
syntax_of_do = nil
- # Finding a syntax correnponding to "do".
+ # Finding a syntax corresponding to "do".
index.downto(0) do |i|
tk = tokens[i]
# In "continue", the token isn't the corresponding syntax to "do".
@@ -508,7 +508,7 @@ class RubyLex
def is_the_in_correspond_to_a_for(tokens, index)
syntax_of_in = nil
- # Finding a syntax correnponding to "do".
+ # Finding a syntax corresponding to "do".
index.downto(0) do |i|
tk = tokens[i]
# In "continue", the token isn't the corresponding syntax to "do".
@@ -603,7 +603,7 @@ class RubyLex
depth_difference
end
- def check_corresponding_token_depth
+ def check_corresponding_token_depth(lines, line_index)
corresponding_token_depth = nil
is_first_spaces_of_line = true
is_first_printable_of_line = true
@@ -611,6 +611,11 @@ class RubyLex
spaces_at_line_head = 0
open_brace_on_line = 0
in_oneliner_def = nil
+
+ if heredoc_scope?
+ return lines[line_index][/^ */].length
+ end
+
@tokens.each_with_index do |t, index|
# detecting one-liner method definition
if in_oneliner_def.nil?
@@ -708,6 +713,9 @@ class RubyLex
while i < tokens.size
t = tokens[i]
case t[1]
+ when *end_type.last
+ start_token.pop
+ end_type.pop
when :on_tstring_beg
start_token << t
end_type << [:on_tstring_end, :on_label_end]
@@ -715,10 +723,14 @@ class RubyLex
start_token << t
end_type << :on_regexp_end
when :on_symbeg
- acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int}
- if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
- start_token << t
- end_type << :on_tstring_end
+ acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int on_backtick}
+ if (i + 1) < tokens.size
+ if acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
+ start_token << t
+ end_type << :on_tstring_end
+ else
+ i += 1
+ end
end
when :on_backtick
start_token << t
@@ -729,9 +741,6 @@ class RubyLex
when :on_heredoc_beg
start_token << t
end_type << :on_heredoc_end
- when *end_type.last
- start_token.pop
- end_type.pop
end
i += 1
end
@@ -813,5 +822,12 @@ class RubyLex
end
false
end
+
+ private
+
+ def heredoc_scope?
+ heredoc_tokens = @tokens.select { |t| [:on_heredoc_beg, :on_heredoc_end].include?(t.event) }
+ heredoc_tokens[-1]&.event == :on_heredoc_beg
+ end
end
# :startdoc:
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
index 173e274cc9..df58edd4a5 100644
--- a/lib/irb/version.rb
+++ b/lib/irb/version.rb
@@ -11,7 +11,7 @@
#
module IRB # :nodoc:
- VERSION = "1.3.6"
+ VERSION = "1.3.8.pre.11"
@RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2021-06-19"
+ @LAST_UPDATE_DATE = "2021-10-09"
end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
index 78d434d106..2c4c40f348 100644
--- a/lib/irb/workspace.rb
+++ b/lib/irb/workspace.rb
@@ -12,6 +12,7 @@
require "delegate"
+IRB::TOPLEVEL_BINDING = binding
module IRB # :nodoc:
class WorkSpace
# Creates a new workspace.
@@ -57,6 +58,8 @@ EOF
__FILE__,
__LINE__ - 3)
when 4 # binding is a copy of TOPLEVEL_BINDING (default)
+ # Note that this will typically be IRB::TOPLEVEL_BINDING
+ # This is to avoid RubyGems' local variables (see issue #17623)
@binding = TOPLEVEL_BINDING.dup
end
end
diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec
index cd6d97de3d..ccd4e70db7 100644
--- a/lib/logger/logger.gemspec
+++ b/lib/logger/logger.gemspec
@@ -16,8 +16,6 @@ Gem::Specification.new do |spec|
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = ">= 2.3.0"
diff --git a/lib/logger/version.rb b/lib/logger/version.rb
index e0f71830d2..b2e6909c32 100644
--- a/lib/logger/version.rb
+++ b/lib/logger/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class Logger
- VERSION = "1.4.3"
+ VERSION = "1.4.4"
end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 04b5f26a5e..c9eac56702 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -447,7 +447,7 @@ EOM
src.sub!(/[^\n]\z/, "\\&\n")
count = 0
begin
- open(conftest_source, "wb") do |cfile|
+ File.open(conftest_source, "wb") do |cfile|
cfile.print src
end
rescue Errno::EACCES
@@ -771,11 +771,20 @@ int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const
# files.
def try_func(func, libs, headers = nil, opt = "", &b)
headers = cpp_include(headers)
+ prepare = String.new
case func
when /^&/
decltype = proc {|x|"const volatile void *#{x}"}
when /\)$/
- call = func
+ strvars = []
+ call = func.gsub(/""/) {
+ v = "s#{strvars.size + 1}"
+ strvars << v
+ v
+ }
+ unless strvars.empty?
+ prepare << "char " << strvars.map {|v| "#{v}[1024]"}.join(", ") << "; "
+ end
when nil
call = ""
else
@@ -805,26 +814,18 @@ SRC
extern int t(void);
#{MAIN_DOES_NOTHING 't'}
#{"extern void #{call};" if decltype}
-int t(void) { #{call}; return 0; }
+int t(void) { #{prepare}#{call}; return 0; }
SRC
end
# You should use +have_var+ rather than +try_var+.
def try_var(var, headers = nil, opt = "", &b)
headers = cpp_include(headers)
- try_compile(<<"SRC", opt, &b) or
-#{headers}
-/*top*/
-extern int t(void);
-#{MAIN_DOES_NOTHING 't'}
-int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
-SRC
- try_link(<<"SRC", opt, &b)
+ try_compile(<<"SRC", opt, &b)
#{headers}
/*top*/
extern int t(void);
#{MAIN_DOES_NOTHING 't'}
-extern int #{var};
int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
SRC
end
@@ -1737,7 +1738,7 @@ SRC
hdr = hdr.join("")
log_src(hdr, "#{header} is")
unless (IO.read(header) == hdr rescue false)
- open(header, "wb") do |hfile|
+ File.open(header, "wb") do |hfile|
hfile.write(hdr)
end
end
@@ -2349,7 +2350,7 @@ CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$
" #"
conf = yield(conf) if block_given?
- mfile = open("Makefile", "wb")
+ mfile = File.open("Makefile", "wb")
mfile.puts(conf)
mfile.print "
all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
diff --git a/lib/open-uri.gemspec b/lib/open-uri.gemspec
index 853049f7ec..cc41fc60cf 100644
--- a/lib/open-uri.gemspec
+++ b/lib/open-uri.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "open-uri"
- spec.version = "0.1.0"
+ spec.version = "0.2.0"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index 1203d10e47..ecfacd10fb 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -221,8 +221,14 @@ class OpenStruct
#
def new_ostruct_member!(name) # :nodoc:
unless @table.key?(name) || is_method_protected!(name)
- define_singleton_method!(name) { @table[name] }
- define_singleton_method!("#{name}=") {|x| @table[name] = x}
+ getter_proc = Proc.new { @table[name] }
+ setter_proc = Proc.new {|x| @table[name] = x}
+ if defined?(::Ractor)
+ ::Ractor.make_shareable(getter_proc)
+ ::Ractor.make_shareable(setter_proc)
+ end
+ define_singleton_method!(name, &getter_proc)
+ define_singleton_method!("#{name}=", &setter_proc)
end
end
private :new_ostruct_member!
@@ -308,7 +314,7 @@ class OpenStruct
# Finds and returns the object in nested objects
# that is specified by +name+ and +identifiers+.
# The nested objects may be instances of various classes.
- # See {Dig Methods}[rdoc-ref:doc/dig_methods.rdoc].
+ # See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
#
# Examples:
# require "ostruct"
diff --git a/lib/racc/info.rb b/lib/racc/info.rb
index f599b13cbb..bb1f100adc 100644
--- a/lib/racc/info.rb
+++ b/lib/racc/info.rb
@@ -11,7 +11,7 @@
#++
module Racc
- VERSION = '1.5.2'
+ VERSION = '1.6.0'
Version = VERSION
Copyright = 'Copyright (c) 1999-2006 Minero Aoki'
end
diff --git a/lib/racc/racc.gemspec b/lib/racc/racc.gemspec
index 20f38925a5..7ee706f63d 100644
--- a/lib/racc/racc.gemspec
+++ b/lib/racc/racc.gemspec
@@ -20,7 +20,7 @@ Racc is a LALR(1) parser generator.
DESC
s.authors = ["Minero Aoki", "Aaron Patterson"]
s.email = [nil, "aaron@tenderlovemaking.com"]
- s.homepage = "http://i.loveruby.net/en/projects/racc/"
+ s.homepage = "https://i.loveruby.net/en/projects/racc/"
s.licenses = ["Ruby", "BSD-2-Clause"]
s.executables = ["racc"]
s.files = [
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index 562e68461c..0b7dd717ab 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -26,6 +26,9 @@ class RDoc::AnyMethod < RDoc::MethodAttr
attr_accessor :c_function
+ # The section title of the method (if defined in a C file via +:category:+)
+ attr_accessor :section_title
+
# Parameters for this method
attr_accessor :params
@@ -356,6 +359,6 @@ class RDoc::AnyMethod < RDoc::MethodAttr
entry =~ /\s#{ignore}\s/
end
- matching.join "\n"
+ matching.empty? ? nil : matching.join("\n")
end
end
diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb
index 99a64cd99a..4a6abfa3ac 100644
--- a/lib/rdoc/cross_reference.rb
+++ b/lib/rdoc/cross_reference.rb
@@ -19,7 +19,7 @@ class RDoc::CrossReference
#
# See CLASS_REGEXP_STR
- METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>|\+@|-@|-|\+|\*)(?:\([\w.+*/=<>-]*\))?'
+ METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===?|\[\]=?|<<|>>|\+@|-@|-|\+|\*)(?:\([\w.+*/=<>-]*\))?'
##
# Regular expressions matching text that should potentially have
diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb
index b46861d009..60e0265e8c 100644
--- a/lib/rdoc/generator/darkfish.rb
+++ b/lib/rdoc/generator/darkfish.rb
@@ -220,8 +220,8 @@ class RDoc::Generator::Darkfish
install_rdoc_static_file @template_dir + item, "./#{item}", options
end
- @options.template_stylesheets.each do |stylesheet|
- FileUtils.cp stylesheet, '.', options
+ unless @options.template_stylesheets.empty?
+ FileUtils.cp @options.template_stylesheets, '.', **options
end
Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path|
diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml
index e61fce1b9a..4f331245c3 100644
--- a/lib/rdoc/generator/template/darkfish/_head.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_head.rhtml
@@ -15,8 +15,6 @@
<link href="<%= asset_rel_prefix %>/css/fonts.css" rel="stylesheet">
<link href="<%= asset_rel_prefix %>/css/rdoc.css" rel="stylesheet">
-<%- if @options.template_stylesheets.flatten.any? then -%>
-<%- @options.template_stylesheets.flatten.each do |stylesheet| -%>
+<%- @options.template_stylesheets.each do |stylesheet| -%>
<link href="<%= asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
-<%- end -%>
<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
index 61e3090c1c..dd00982d49 100644
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
+++ b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
index 85686d967d..1decfb95af 100644
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
+++ b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
Binary files differ
diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb
index 15beaefcca..3442f76b1b 100644
--- a/lib/rdoc/markdown.rb
+++ b/lib/rdoc/markdown.rb
@@ -344,9 +344,8 @@ class RDoc::Markdown
end
def scan(reg)
- if m = reg.match(@string[@pos..-1])
- width = m.end(0)
- @pos += width
+ if m = reg.match(@string, @pos)
+ @pos = m.end(0)
return true
end
@@ -1060,7 +1059,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:#*)/)
+ _tmp = scan(/\G(?-mix:#*)/)
unless _tmp
self.pos = _save3
break
@@ -1100,7 +1099,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:\#{1,6})/)
+ _tmp = scan(/\G(?-mix:\#{1,6})/)
if _tmp
text = get_text(_text_start)
end
@@ -1165,7 +1164,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:#*)/)
+ _tmp = scan(/\G(?-mix:#*)/)
unless _tmp
self.pos = _save3
break
@@ -1225,7 +1224,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:={1,})/)
+ _tmp = scan(/\G(?-mix:={1,})/)
unless _tmp
self.pos = _save
break
@@ -1246,7 +1245,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:-{1,})/)
+ _tmp = scan(/\G(?-mix:-{1,})/)
unless _tmp
self.pos = _save
break
@@ -2130,7 +2129,7 @@ class RDoc::Markdown
self.pos = _save
break
end
- _tmp = scan(/\A(?-mix:[+*-])/)
+ _tmp = scan(/\G(?-mix:[+*-])/)
unless _tmp
self.pos = _save
break
@@ -9385,7 +9384,7 @@ class RDoc::Markdown
self.pos = _save7
break
end
- _tmp = scan(/\A(?-mix:[^`\n]*$)/)
+ _tmp = scan(/\G(?-mix:[^`\n]*$)/)
unless _tmp
self.pos = _save7
end
@@ -9476,7 +9475,7 @@ class RDoc::Markdown
self.pos = _save15
break
end
- _tmp = scan(/\A(?-mix:[^`\n]*$)/)
+ _tmp = scan(/\G(?-mix:[^`\n]*$)/)
unless _tmp
self.pos = _save15
end
@@ -9725,7 +9724,7 @@ class RDoc::Markdown
_save3 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save3
break
@@ -9755,7 +9754,7 @@ class RDoc::Markdown
_save6 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save6
break
@@ -9818,7 +9817,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
+ _tmp = scan(/\G(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
if _tmp
text = get_text(_text_start)
end
@@ -9944,7 +9943,7 @@ class RDoc::Markdown
self.pos = _save5
break
end
- _tmp = scan(/\A(?-mix:={1,}|-{1,})/)
+ _tmp = scan(/\G(?-mix:={1,}|-{1,})/)
unless _tmp
self.pos = _save5
break
@@ -10096,7 +10095,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:\*{4,})/)
+ _tmp = scan(/\G(?-mix:\*{4,})/)
if _tmp
text = get_text(_text_start)
end
@@ -10126,7 +10125,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:\*+)/)
+ _tmp = scan(/\G(?-mix:\*+)/)
unless _tmp
self.pos = _save3
break
@@ -10173,7 +10172,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:_{4,})/)
+ _tmp = scan(/\G(?-mix:_{4,})/)
if _tmp
text = get_text(_text_start)
end
@@ -10203,7 +10202,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save3
break
@@ -11564,7 +11563,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:[A-Za-z]+)/)
+ _tmp = scan(/\G(?-mix:[A-Za-z]+)/)
unless _tmp
self.pos = _save1
break
@@ -11689,7 +11688,7 @@ class RDoc::Markdown
_save2 = self.pos
while true # sequence
- _tmp = scan(/\A(?i-mx:[\w+.\/!%~$-]+)/)
+ _tmp = scan(/\G(?i-mx:[\w+.\/!%~$-]+)/)
unless _tmp
self.pos = _save2
break
@@ -12553,7 +12552,7 @@ class RDoc::Markdown
self.pos = _save10
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save10
end
@@ -12690,7 +12689,7 @@ class RDoc::Markdown
self.pos = _save24
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save24
end
@@ -12867,7 +12866,7 @@ class RDoc::Markdown
self.pos = _save40
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save40
end
@@ -13004,7 +13003,7 @@ class RDoc::Markdown
self.pos = _save54
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save54
end
@@ -13181,7 +13180,7 @@ class RDoc::Markdown
self.pos = _save70
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save70
end
@@ -13318,7 +13317,7 @@ class RDoc::Markdown
self.pos = _save84
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save84
end
@@ -13495,7 +13494,7 @@ class RDoc::Markdown
self.pos = _save100
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save100
end
@@ -13632,7 +13631,7 @@ class RDoc::Markdown
self.pos = _save114
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save114
end
@@ -13809,7 +13808,7 @@ class RDoc::Markdown
self.pos = _save130
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save130
end
@@ -13946,7 +13945,7 @@ class RDoc::Markdown
self.pos = _save144
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save144
end
@@ -14598,7 +14597,7 @@ class RDoc::Markdown
_save = self.pos
while true # choice
- _tmp = scan(/\A(?-mix:[~*_`&\[\]()<!#\\'"])/)
+ _tmp = scan(/\G(?-mix:[~*_`&\[\]()<!#\\'"])/)
break if _tmp
self.pos = _save
_tmp = _ExtendedSpecialChar()
@@ -14703,13 +14702,13 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?i-mx:&#x)/)
+ _tmp = scan(/\G(?i-mx:&#x)/)
unless _tmp
self.pos = _save
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[0-9a-fA-F]+)/)
+ _tmp = scan(/\G(?-mix:[0-9a-fA-F]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14745,7 +14744,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[0-9]+)/)
+ _tmp = scan(/\G(?-mix:[0-9]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14781,7 +14780,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[A-Za-z0-9]+)/)
+ _tmp = scan(/\G(?-mix:[A-Za-z0-9]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14813,14 +14812,14 @@ class RDoc::Markdown
# NonindentSpace = / {0,3}/
def _NonindentSpace
- _tmp = scan(/\A(?-mix: {0,3})/)
+ _tmp = scan(/\G(?-mix: {0,3})/)
set_failed_rule :_NonindentSpace unless _tmp
return _tmp
end
# Indent = /\t| /
def _Indent
- _tmp = scan(/\A(?-mix:\t| )/)
+ _tmp = scan(/\G(?-mix:\t| )/)
set_failed_rule :_Indent unless _tmp
return _tmp
end
@@ -15762,7 +15761,7 @@ class RDoc::Markdown
self.pos = _save11
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save11
end
@@ -15843,7 +15842,7 @@ class RDoc::Markdown
self.pos = _save19
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save19
end
diff --git a/lib/rdoc/markdown/literals.rb b/lib/rdoc/markdown/literals.rb
index 31cd237f12..943c2d268a 100644
--- a/lib/rdoc/markdown/literals.rb
+++ b/lib/rdoc/markdown/literals.rb
@@ -174,9 +174,8 @@ class RDoc::Markdown::Literals
end
def scan(reg)
- if m = reg.match(@string[@pos..-1])
- width = m.end(0)
- @pos += width
+ if m = reg.match(@string, @pos)
+ @pos = m.end(0)
return true
end
@@ -366,14 +365,14 @@ class RDoc::Markdown::Literals
# Alphanumeric = /\p{Word}/
def _Alphanumeric
- _tmp = scan(/\A(?-mix:\p{Word})/)
+ _tmp = scan(/\G(?-mix:\p{Word})/)
set_failed_rule :_Alphanumeric unless _tmp
return _tmp
end
# AlphanumericAscii = /[A-Za-z0-9]/
def _AlphanumericAscii
- _tmp = scan(/\A(?-mix:[A-Za-z0-9])/)
+ _tmp = scan(/\G(?-mix:[A-Za-z0-9])/)
set_failed_rule :_AlphanumericAscii unless _tmp
return _tmp
end
@@ -387,21 +386,21 @@ class RDoc::Markdown::Literals
# Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
def _Newline
- _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
+ _tmp = scan(/\G(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
set_failed_rule :_Newline unless _tmp
return _tmp
end
# NonAlphanumeric = /\p{^Word}/
def _NonAlphanumeric
- _tmp = scan(/\A(?-mix:\p{^Word})/)
+ _tmp = scan(/\G(?-mix:\p{^Word})/)
set_failed_rule :_NonAlphanumeric unless _tmp
return _tmp
end
# Spacechar = /\t|\p{Zs}/
def _Spacechar
- _tmp = scan(/\A(?-mix:\t|\p{Zs})/)
+ _tmp = scan(/\G(?-mix:\t|\p{Zs})/)
set_failed_rule :_Spacechar unless _tmp
return _tmp
end
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index 3080ae3578..88078c9cef 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -163,6 +163,8 @@ class RDoc::Markup::PreProcess
if RDoc::Context === code_object then
section = code_object.add_section param
code_object.temporary_section = section
+ elsif RDoc::AnyMethod === code_object then
+ code_object.section_title = param
end
blankline # ignore category if we're not on an RDoc::Context
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
index 13b7ba5c6c..792b473b79 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -971,7 +971,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--template-stylesheets=FILES", PathArray,
"Set (or add to) the list of files to",
"include with the html template.") do |value|
- @template_stylesheets << value
+ @template_stylesheets.concat value
end
opt.separator nil
@@ -1282,4 +1282,33 @@ Usage: #{opt.program_name} [options] [names...]
end
end
+ ##
+ # Loads options from .rdoc_options if the file exists, otherwise creates a
+ # new RDoc::Options instance.
+
+ def self.load_options
+ options_file = File.expand_path '.rdoc_options'
+ return RDoc::Options.new unless File.exist? options_file
+
+ RDoc.load_yaml
+
+ begin
+ options = YAML.safe_load File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol]
+ rescue Psych::SyntaxError
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
+ end
+
+ return RDoc::Options.new unless options # Allow empty file.
+
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
+ RDoc::Options === options or Hash === options
+
+ if Hash === options
+ # Override the default values with the contents of YAML file.
+ options = RDoc::Options.new options
+ end
+
+ options
+ end
+
end
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 9d8db6cdee..b89aaa6dcc 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -173,6 +173,8 @@ class RDoc::Parser::C < RDoc::Parser
@classes = load_variable_map :c_class_variables
@singleton_classes = load_variable_map :c_singleton_class_variables
+ @markup = @options.markup
+
# class_variable => { function => [method, ...] }
@methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } }
@@ -439,7 +441,7 @@ class RDoc::Parser::C < RDoc::Parser
next unless cls = @classes[c]
m = @known_classes[m] || m
- comment = RDoc::Comment.new '', @top_level, :c
+ comment = new_comment '', @top_level, :c
incl = cls.add_include RDoc::Include.new(m, comment)
incl.record_location @top_level
end
@@ -521,7 +523,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*"#{Regexp.escape new_name}"\s*,
\s*"#{Regexp.escape old_name}"\s*\);%xm
- RDoc::Comment.new($1 || '', @top_level, :c)
+ new_comment($1 || '', @top_level, :c)
end
##
@@ -560,7 +562,7 @@ class RDoc::Parser::C < RDoc::Parser
''
end
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -600,7 +602,7 @@ class RDoc::Parser::C < RDoc::Parser
case type
when :func_def
- comment = RDoc::Comment.new args[0], @top_level, :c
+ comment = new_comment args[0], @top_level, :c
body = args[1]
offset, = args[2]
@@ -630,7 +632,7 @@ class RDoc::Parser::C < RDoc::Parser
body
when :macro_def
- comment = RDoc::Comment.new args[0], @top_level, :c
+ comment = new_comment args[0], @top_level, :c
body = args[1]
offset, = args[2]
@@ -737,7 +739,7 @@ class RDoc::Parser::C < RDoc::Parser
comment = ''
end
- comment = RDoc::Comment.new comment, @top_level, :c
+ comment = new_comment comment, @top_level, :c
comment.normalize
look_for_directives_in class_mod, comment
@@ -782,7 +784,7 @@ class RDoc::Parser::C < RDoc::Parser
table[const_name] ||
''
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -813,7 +815,7 @@ class RDoc::Parser::C < RDoc::Parser
return unless comment
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -947,7 +949,7 @@ class RDoc::Parser::C < RDoc::Parser
new_comment = "#{$1}#{new_comment.lstrip}"
- new_comment = RDoc::Comment.new new_comment, @top_level, :c
+ new_comment = self.new_comment(new_comment, @top_level, :c)
con = RDoc::Constant.new const_name, new_definition, new_comment
else
@@ -1028,7 +1030,12 @@ class RDoc::Parser::C < RDoc::Parser
meth_obj.record_location @top_level
+
+ if meth_obj.section_title
+ class_obj.temporary_section = class_obj.add_section(meth_obj.section_title)
+ end
class_obj.add_method meth_obj
+
@stats.add_method meth_obj
meth_obj.visibility = :private if 'private_method' == type
end
@@ -1222,4 +1229,9 @@ class RDoc::Parser::C < RDoc::Parser
@top_level
end
+ def new_comment text = nil, location = nil, language = nil
+ RDoc::Comment.new(text, location, language).tap do |comment|
+ comment.format = @markup
+ end
+ end
end
diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb
index cf30043593..462ba869a2 100644
--- a/lib/rdoc/rd/block_parser.rb
+++ b/lib/rdoc/rd/block_parser.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.1
+# This file is automatically generated by Racc 1.5.2
# from Racc grammar file "".
#
diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb
index 007327bf0e..8f4c2c31ef 100644
--- a/lib/rdoc/rd/inline_parser.rb
+++ b/lib/rdoc/rd/inline_parser.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.1
+# This file is automatically generated by Racc 1.5.2
# from Racc grammar file "".
#
diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec
index 75f8534b9e..525a15fcde 100644
--- a/lib/rdoc/rdoc.gemspec
+++ b/lib/rdoc/rdoc.gemspec
@@ -246,5 +246,4 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
s.required_rubygems_version = Gem::Requirement.new(">= 2.2")
s.add_dependency 'psych', '>= 4.0.0'
- s.add_development_dependency("gettext")
end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index 3a3defacb6..5255e043fd 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -14,7 +14,7 @@ require 'time'
# is:
#
# rdoc = RDoc::RDoc.new
-# options = rdoc.load_options # returns an RDoc::Options instance
+# options = RDoc::Options.load_options # returns an RDoc::Options instance
# # set extra options
# rdoc.document options
#
@@ -152,35 +152,6 @@ class RDoc::RDoc
end
##
- # Loads options from .rdoc_options if the file exists, otherwise creates a
- # new RDoc::Options instance.
-
- def load_options
- options_file = File.expand_path '.rdoc_options'
- return RDoc::Options.new unless File.exist? options_file
-
- RDoc.load_yaml
-
- begin
- options = YAML.safe_load File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol]
- rescue Psych::SyntaxError
- raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
- end
-
- return RDoc::Options.new unless options # Allow empty file.
-
- raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
- RDoc::Options === options or Hash === options
-
- if Hash === options
- # Override the default values with the contents of YAML file.
- options = RDoc::Options.new options
- end
-
- options
- end
-
- ##
# Create an output dir if it doesn't exist. If it does exist, but doesn't
# contain the flag file <tt>created.rid</tt> then we refuse to use it, as
# we may clobber some manually generated documentation
@@ -471,7 +442,7 @@ The internal error was:
@options = options
@options.finish
else
- @options = load_options
+ @options = RDoc::Options.load_options
@options.parse options
end
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
index c3218fdb2f..0bc4aba428 100644
--- a/lib/rdoc/text.rb
+++ b/lib/rdoc/text.rb
@@ -218,10 +218,10 @@ module RDoc::Text
when s.scan(/\.\.\.(\.?)/) then
html << s[1] << encoded[:ellipsis]
after_word = nil
- when s.scan(/\(c\)/) then
+ when s.scan(/\(c\)/i) then
html << encoded[:copyright]
after_word = nil
- when s.scan(/\(r\)/) then
+ when s.scan(/\(r\)/i) then
html << encoded[:trademark]
after_word = nil
when s.scan(/---/) then
@@ -237,10 +237,18 @@ module RDoc::Text
when s.scan(/``/) then # backtick double quote
html << encoded[:open_dquote]
after_word = nil
- when s.scan(/''/) then # tick double quote
+ when s.scan(/(?:&#39;|'){2}/) then # tick double quote
html << encoded[:close_dquote]
after_word = nil
- when s.scan(/'/) then # single quote
+ when s.scan(/`/) then # backtick
+ if insquotes or after_word
+ html << '`'
+ after_word = false
+ else
+ html << encoded[:open_squote]
+ insquotes = true
+ end
+ when s.scan(/&#39;|'/) then # single quote
if insquotes
html << encoded[:close_squote]
insquotes = false
diff --git a/lib/reline.rb b/lib/reline.rb
index d68627dca5..b872fe6945 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -16,8 +16,24 @@ module Reline
class ConfigEncodingConversionError < StandardError; end
- Key = Struct.new('Key', :char, :combined_char, :with_meta)
+ Key = Struct.new('Key', :char, :combined_char, :with_meta) do
+ def match?(other)
+ case other
+ when Reline::Key
+ (other.char.nil? or char.nil? or char == other.char) and
+ (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
+ (other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
+ when Integer, Symbol
+ (combined_char and combined_char == other) or
+ (combined_char.nil? and char and char == other)
+ else
+ false
+ end
+ end
+ alias_method :==, :match?
+ end
CursorPos = Struct.new(:x, :y)
+ DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)
class Core
ATTR_READER_NAMES = %i(
@@ -44,6 +60,7 @@ module Reline
def initialize
self.output = STDOUT
+ @dialog_proc_list = []
yield self
@completion_quote_character = nil
@bracketed_paste_finished = false
@@ -106,6 +123,14 @@ module Reline
@completion_proc = p
end
+ def autocompletion
+ @config.autocompletion
+ end
+
+ def autocompletion=(val)
+ @config.autocompletion = val
+ end
+
def output_modifier_proc=(p)
raise ArgumentError unless p.respond_to?(:call) or p.nil?
@output_modifier_proc = p
@@ -130,6 +155,12 @@ module Reline
@dig_perfect_match_proc = p
end
+ def add_dialog_proc(name_sym, p, context = nil)
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
+ raise ArgumentError unless name_sym.instance_of?(Symbol)
+ @dialog_proc_list << [name_sym, p, context]
+ end
+
def input=(val)
raise TypeError unless val.respond_to?(:getc) or val.nil?
if val.respond_to?(:getc)
@@ -171,6 +202,46 @@ module Reline
Reline::IOGate.get_screen_size
end
+ Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
+ # autocomplete
+ return nil unless config.autocompletion
+ if just_cursor_moving and completion_journey_data.nil?
+ # Auto complete starts only when edited
+ return nil
+ end
+ pre, target, post = retrieve_completion_block(true)
+ if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
+ return nil
+ end
+ if completion_journey_data and completion_journey_data.list
+ result = completion_journey_data.list.dup
+ result.shift
+ pointer = completion_journey_data.pointer - 1
+ else
+ result = call_completion_proc_with_checking_args(pre, target, post)
+ pointer = nil
+ end
+ if result and result.size == 1 and result[0] == target and pointer != 0
+ result = nil
+ end
+ target_width = Reline::Unicode.calculate_width(target)
+ x = cursor_pos.x - target_width
+ if x < 0
+ x = screen_width + x
+ y = -1
+ else
+ y = 0
+ end
+ cursor_pos_to_render = Reline::CursorPos.new(x, y)
+ if context and context.is_a?(Array)
+ context.clear
+ context.push(cursor_pos_to_render, result, pointer, dialog)
+ end
+ dialog.pointer = pointer
+ DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15)
+ }
+ Reline::DEFAULT_DIALOG_CONTEXT = Array.new
+
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
unless confirm_multiline_termination
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
@@ -230,6 +301,10 @@ module Reline
line_editor.auto_indent_proc = auto_indent_proc
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
line_editor.pre_input_hook = pre_input_hook
+ @dialog_proc_list.each do |d|
+ name_sym, dialog_proc, context = d
+ line_editor.add_dialog_proc(name_sym, dialog_proc, context)
+ end
unless config.test_mode
config.read
@@ -303,25 +378,9 @@ module Reline
break
when :matching
if buffer.size == 1
- begin
- succ_c = nil
- Timeout.timeout(keyseq_timeout / 1000.0) {
- succ_c = Reline::IOGate.getc
- }
- rescue Timeout::Error # cancel matching only when first byte
- block.([Reline::Key.new(c, c, false)])
- break
- else
- if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
- if c == "\e".ord
- block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
- else
- block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
- end
- break
- else
- Reline::IOGate.ungetc(succ_c)
- end
+ case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
+ when :break then break
+ when :next then next
end
end
when :unmatched
@@ -338,6 +397,38 @@ module Reline
end
end
+ private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
+ begin
+ succ_c = nil
+ Timeout.timeout(keyseq_timeout / 1000.0) {
+ succ_c = Reline::IOGate.getc
+ }
+ rescue Timeout::Error # cancel matching only when first byte
+ block.([Reline::Key.new(c, c, false)])
+ return :break
+ else
+ case key_stroke.match_status(buffer.dup.push(succ_c))
+ when :unmatched
+ if c == "\e".ord
+ block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
+ else
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
+ end
+ return :break
+ when :matching
+ Reline::IOGate.ungetc(succ_c)
+ return :next
+ when :matched
+ buffer << succ_c
+ expanded = key_stroke.expand(buffer).map{ |expanded_c|
+ Reline::Key.new(expanded_c, expanded_c, false)
+ }
+ block.(expanded)
+ return :break
+ end
+ end
+ end
+
private def read_escaped_key(keyseq_timeout, c, block)
begin
escaped_c = nil
@@ -366,7 +457,7 @@ module Reline
private def may_req_ambiguous_char_width
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
- return if @ambiguous_width
+ return if defined? @ambiguous_width
Reline::IOGate.move_cursor_column(0)
begin
output.write "\u{25bd}"
@@ -389,7 +480,7 @@ module Reline
#--------------------------------------------------------
(Core::ATTR_READER_NAMES).each { |name|
- def_single_delegators :core, "#{name}", "#{name}="
+ def_single_delegators :core, :"#{name}", :"#{name}="
}
def_single_delegators :core, :input=, :output=
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
@@ -424,6 +515,8 @@ module Reline
def_single_delegators :core, :ambiguous_width
def_single_delegators :core, :last_incremental_search
def_single_delegators :core, :last_incremental_search=
+ def_single_delegators :core, :add_dialog_proc
+ def_single_delegators :core, :autocompletion, :autocompletion=
def_single_delegators :core, :readmultiline
def_instance_delegators self, :readmultiline
@@ -445,6 +538,7 @@ module Reline
core.completer_quote_characters = '"\''
core.filename_quote_characters = ""
core.special_prefixes = ""
+ core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
}
end
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index 3880f51551..ae6961e29f 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -37,6 +37,7 @@ class Reline::ANSI
# default bindings
[27, 32] => :em_set_mark, # M-<space>
[24, 24] => :em_exchange_mark, # C-x C-x
+ [27, 91, 90] => :completion_journey_up, # S-Tab
}.each_pair do |key, func|
config.add_default_key_binding_by_keymap(:emacs, key, func)
end
@@ -125,8 +126,8 @@ class Reline::ANSI
unless @@buf.empty?
return @@buf.shift
end
- until c = @@input.raw(intr: true, &:getbyte)
- sleep 0.1
+ until c = @@input.raw(intr: true) { select([@@input], [], [], 0.1) && @@input.getbyte }
+ Reline.core.line_editor.resize
end
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
rescue Errno::EIO
@@ -274,6 +275,22 @@ class Reline::ANSI
end
end
+ def self.hide_cursor
+ if Reline::Terminfo.enabled?
+ @@output.write Reline::Terminfo.tigetstr('civis')
+ else
+ # ignored
+ end
+ end
+
+ def self.show_cursor
+ if Reline::Terminfo.enabled?
+ @@output.write Reline::Terminfo.tigetstr('cnorm')
+ else
+ # ignored
+ end
+ end
+
def self.erase_after_cursor
@@output.write "\e[K"
end
@@ -295,8 +312,6 @@ class Reline::ANSI
def self.prep
retrieve_keybuffer
- int_handle = Signal.trap('INT', 'IGNORE')
- Signal.trap('INT', int_handle)
nil
end
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index c2b50a95a2..4b2655d8eb 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -50,6 +50,7 @@ class Reline::Config
@additional_key_bindings[:emacs] = {}
@additional_key_bindings[:vi_insert] = {}
@additional_key_bindings[:vi_command] = {}
+ @oneshot_key_bindings = {}
@skip_section = nil
@if_stack = nil
@editing_mode_label = :emacs
@@ -65,6 +66,7 @@ class Reline::Config
@history_size = -1 # unlimited
@keyseq_timeout = 500
@test_mode = false
+ @autocompletion = false
end
def reset
@@ -74,6 +76,7 @@ class Reline::Config
@additional_key_bindings.keys.each do |key|
@additional_key_bindings[key].clear
end
+ @oneshot_key_bindings.clear
reset_default_key_bindings
end
@@ -89,6 +92,14 @@ class Reline::Config
(val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
end
+ def autocompletion=(val)
+ @autocompletion = val
+ end
+
+ def autocompletion
+ @autocompletion
+ end
+
def keymap
@key_actors[@keymap_label]
end
@@ -119,8 +130,12 @@ class Reline::Config
return home_rc_path
end
+ private def default_inputrc_path
+ @default_inputrc_path ||= inputrc_path
+ end
+
def read(file = nil)
- file ||= inputrc_path
+ file ||= default_inputrc_path
begin
if file.respond_to?(:readlines)
lines = file.readlines
@@ -139,8 +154,19 @@ class Reline::Config
end
def key_bindings
- # override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label]
- @key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label])
+ # The key bindings for each editing mode will be overwritten by the user-defined ones.
+ kb = @key_actors[@editing_mode_label].default_key_bindings.dup
+ kb.merge!(@additional_key_bindings[@editing_mode_label])
+ kb.merge!(@oneshot_key_bindings)
+ kb
+ end
+
+ def add_oneshot_key_binding(keystroke, target)
+ @oneshot_key_bindings[keystroke] = target
+ end
+
+ def reset_oneshot_key_bindings
+ @oneshot_key_bindings.clear
end
def add_default_key_binding_by_keymap(keymap, keystroke, target)
diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb
index 2f87d718c6..5df346882a 100644
--- a/lib/reline/general_io.rb
+++ b/lib/reline/general_io.rb
@@ -24,6 +24,7 @@ class Reline::GeneralIO
end
@@buf = []
+ @@input = STDIN
def self.input=(val)
@@input = val
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb
index 017e3db00a..16e5f69914 100644
--- a/lib/reline/key_stroke.rb
+++ b/lib/reline/key_stroke.rb
@@ -1,38 +1,87 @@
class Reline::KeyStroke
- using Module.new {
- refine Array do
- def start_with?(other)
- other.size <= size && other == self.take(other.size)
+ def initialize(config)
+ @config = config
+ end
+
+ def compress_meta_key(ary)
+ ary.inject([]) { |result, key|
+ if result.size > 0 and result.last == "\e".ord
+ result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
+ else
+ result << key
end
+ result
+ }
+ end
- def bytes
- self
+ def start_with?(me, other)
+ compressed_me = compress_meta_key(me)
+ compressed_other = compress_meta_key(other)
+ i = 0
+ loop do
+ my_c = compressed_me[i]
+ other_c = compressed_other[i]
+ other_is_last = (i + 1) == compressed_other.size
+ me_is_last = (i + 1) == compressed_me.size
+ if my_c != other_c
+ if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
+ return true
+ else
+ return false
+ end
+ elsif other_is_last
+ return true
+ elsif me_is_last
+ return false
end
+ i += 1
end
- }
+ end
- def initialize(config)
- @config = config
+ def equal?(me, other)
+ case me
+ when Array
+ compressed_me = compress_meta_key(me)
+ compressed_other = compress_meta_key(other)
+ compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
+ when Integer
+ if other.is_a?(Reline::Key)
+ if other.combined_char == "\e".ord
+ false
+ else
+ other.combined_char == me
+ end
+ else
+ me == other
+ end
+ when Reline::Key
+ if other.is_a?(Integer)
+ me.combined_char == other
+ else
+ me == other
+ end
+ end
end
def match_status(input)
key_mapping.keys.select { |lhs|
- lhs.start_with? input
+ start_with?(lhs, input)
}.tap { |it|
- return :matched if it.size == 1 && (it.max_by(&:size)&.size&.== input.size)
- return :matching if it.size == 1 && (it.max_by(&:size)&.size&.!= input.size)
+ return :matched if it.size == 1 && equal?(it[0], input)
+ return :matching if it.size == 1 && !equal?(it[0], input)
return :matched if it.max_by(&:size)&.size&.< input.size
return :matching if it.size > 1
}
key_mapping.keys.select { |lhs|
- input.start_with? lhs
+ start_with?(input, lhs)
}.tap { |it|
return it.size > 0 ? :matched : :unmatched
}
end
def expand(input)
- lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).reverse.first
+ input = compress_meta_key(input)
+ lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
return input unless lhs
rhs = key_mapping[lhs]
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 8b52a428e4..f6facc9da8 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -5,6 +5,7 @@ require 'tempfile'
class Reline::LineEditor
# TODO: undo
+ # TODO: Use "private alias_method" idiom after drop Ruby 2.5.
attr_reader :line
attr_reader :byte_pointer
attr_accessor :confirm_multiline_termination_proc
@@ -150,7 +151,8 @@ class Reline::LineEditor
@screen_size = Reline::IOGate.get_screen_size
@screen_height = @screen_size.first
reset_variables(prompt, encoding: encoding)
- @old_trap = Signal.trap('SIGINT') {
+ @old_trap = Signal.trap('INT') {
+ clear_dialog
if @scroll_partial_screen
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
else
@@ -158,50 +160,96 @@ class Reline::LineEditor
end
Reline::IOGate.move_cursor_column(0)
scroll_down(1)
- @old_trap.call if @old_trap.respond_to?(:call) # can also be string, ex: "DEFAULT"
- raise Interrupt
+ case @old_trap
+ when 'DEFAULT', 'SYSTEM_DEFAULT'
+ raise Interrupt
+ when 'IGNORE'
+ # Do nothing
+ when 'EXIT'
+ exit
+ else
+ @old_trap.call
+ end
}
+ begin
+ @old_tstp_trap = Signal.trap('TSTP') {
+ Reline::IOGate.ungetc("\C-z".ord)
+ @old_tstp_trap.call if @old_tstp_trap.respond_to?(:call)
+ }
+ rescue ArgumentError
+ end
Reline::IOGate.set_winch_handler do
- @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
- old_screen_size = @screen_size
- @screen_size = Reline::IOGate.get_screen_size
- @screen_height = @screen_size.first
- if old_screen_size.last < @screen_size.last # columns increase
- @rerender_all = true
- rerender
- else
- back = 0
- new_buffer = whole_lines
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
- new_buffer.each_with_index do |line, index|
- prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
- width = prompt_width + calculate_width(line)
- height = calculate_height_by_width(width)
- back += height
- end
- @highest_in_all = back
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @first_line_started_from =
- if @line_index.zero?
- 0
- else
- calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
- end
- if @prompt_proc
- prompt = prompt_list[@line_index]
- prompt_width = calculate_width(prompt, true)
+ @resized = true
+ end
+ if ENV.key?('RELINE_ALT_SCROLLBAR')
+ @full_block = '::'
+ @upper_half_block = "''"
+ @lower_half_block = '..'
+ @block_elem_width = 2
+ elsif Reline::IOGate.win?
+ @full_block = '█'
+ @upper_half_block = '▀'
+ @lower_half_block = '▄'
+ @block_elem_width = 1
+ elsif @encoding == Encoding::UTF_8
+ @full_block = '█'
+ @upper_half_block = '▀'
+ @lower_half_block = '▄'
+ @block_elem_width = Reline::Unicode.calculate_width('█')
+ else
+ @full_block = '::'
+ @upper_half_block = "''"
+ @lower_half_block = '..'
+ @block_elem_width = 2
+ end
+ end
+
+ def resize
+ return unless @resized
+ @resized = false
+ @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
+ old_screen_size = @screen_size
+ @screen_size = Reline::IOGate.get_screen_size
+ @screen_height = @screen_size.first
+ if old_screen_size.last < @screen_size.last # columns increase
+ @rerender_all = true
+ rerender
+ else
+ back = 0
+ new_buffer = whole_lines
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
+ new_buffer.each_with_index do |line, index|
+ prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
+ width = prompt_width + calculate_width(line)
+ height = calculate_height_by_width(width)
+ back += height
+ end
+ @highest_in_all = back
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @first_line_started_from =
+ if @line_index.zero?
+ 0
+ else
+ calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
end
- calculate_nearest_cursor
- @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
- Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @rerender_all = true
+ if @prompt_proc
+ prompt = prompt_list[@line_index]
+ prompt_width = calculate_width(prompt, true)
end
+ calculate_nearest_cursor
+ @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @rerender_all = true
end
end
def finalize
- Signal.trap('SIGINT', @old_trap)
+ Signal.trap('INT', @old_trap)
+ begin
+ Signal.trap('TSTP', @old_tstp_trap)
+ rescue ArgumentError
+ end
end
def eof?
@@ -241,6 +289,9 @@ class Reline::LineEditor
@drop_terminate_spaces = false
@in_pasting = false
@auto_indent_proc = nil
+ @dialogs = []
+ @last_key = nil
+ @resized = false
reset_line
end
@@ -406,6 +457,7 @@ class Reline::LineEditor
Reline::IOGate.erase_after_cursor
end
@output.flush
+ clear_dialog
return
end
new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
@@ -416,6 +468,7 @@ class Reline::LineEditor
else
if @just_cursor_moving and not @rerender_all
rendered = just_move_cursor
+ render_dialog((prompt_width + @cursor) % @screen_size.last)
@just_cursor_moving = false
return
elsif @previous_line_index or new_highest_in_this != @highest_in_this
@@ -438,18 +491,20 @@ class Reline::LineEditor
new_lines = whole_lines
end
line = modify_lines(new_lines)[@line_index]
+ clear_dialog
prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
render_partial(prompt, prompt_width, line, @first_line_started_from)
move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1)
scroll_down(1)
Reline::IOGate.move_cursor_column(0)
Reline::IOGate.erase_after_cursor
- elsif not rendered
- unless @in_pasting
+ else
+ if not rendered and not @in_pasting
line = modify_lines(whole_lines)[@line_index]
prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
render_partial(prompt, prompt_width, line, @first_line_started_from)
end
+ render_dialog((prompt_width + @cursor) % @screen_size.last)
end
@buffer_of_lines[@line_index] = @line
@rest_height = 0 if @scroll_partial_screen
@@ -464,6 +519,400 @@ class Reline::LineEditor
end
end
+ class DialogProcScope
+ def initialize(line_editor, config, proc_to_exec, context)
+ @line_editor = line_editor
+ @config = config
+ @proc_to_exec = proc_to_exec
+ @context = context
+ @cursor_pos = Reline::CursorPos.new
+ end
+
+ def context
+ @context
+ end
+
+ def retrieve_completion_block(set_completion_quote_character = false)
+ @line_editor.retrieve_completion_block(set_completion_quote_character)
+ end
+
+ def call_completion_proc_with_checking_args(pre, target, post)
+ @line_editor.call_completion_proc_with_checking_args(pre, target, post)
+ end
+
+ def set_dialog(dialog)
+ @dialog = dialog
+ end
+
+ def dialog
+ @dialog
+ end
+
+ def set_cursor_pos(col, row)
+ @cursor_pos.x = col
+ @cursor_pos.y = row
+ end
+
+ def set_key(key)
+ @key = key
+ end
+
+ def key
+ @key
+ end
+
+ def cursor_pos
+ @cursor_pos
+ end
+
+ def just_cursor_moving
+ @line_editor.instance_variable_get(:@just_cursor_moving)
+ end
+
+ def screen_width
+ @line_editor.instance_variable_get(:@screen_size).last
+ end
+
+ def completion_journey_data
+ @line_editor.instance_variable_get(:@completion_journey_data)
+ end
+
+ def config
+ @config
+ end
+
+ def call
+ instance_exec(&@proc_to_exec)
+ end
+ end
+
+ class Dialog
+ attr_reader :name, :contents, :width
+ attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key
+
+ def initialize(name, config, proc_scope)
+ @name = name
+ @config = config
+ @proc_scope = proc_scope
+ @width = nil
+ @scroll_top = 0
+ @trap_key = nil
+ end
+
+ def set_cursor_pos(col, row)
+ @proc_scope.set_cursor_pos(col, row)
+ end
+
+ def width=(v)
+ @width = v
+ end
+
+ def contents=(contents)
+ @contents = contents
+ if contents and @width.nil?
+ @width = contents.map{ |line| Reline::Unicode.calculate_width(line, true) }.max
+ end
+ end
+
+ def call(key)
+ @proc_scope.set_dialog(self)
+ @proc_scope.set_key(key)
+ dialog_render_info = @proc_scope.call
+ if @trap_key
+ if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap
+ @trap_key.each do |t|
+ @config.add_oneshot_key_binding(t, @name)
+ end
+ elsif @trap_key.is_a?(Array)
+ @config.add_oneshot_key_binding(@trap_key, @name)
+ elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
+ @config.add_oneshot_key_binding([@trap_key], @name)
+ end
+ end
+ dialog_render_info
+ end
+ end
+
+ def add_dialog_proc(name, p, context = nil)
+ return if @dialogs.any? { |d| d.name == name }
+ @dialogs << Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
+ end
+
+ DIALOG_DEFAULT_HEIGHT = 20
+ private def render_dialog(cursor_column)
+ @dialogs.each do |dialog|
+ render_each_dialog(dialog, cursor_column)
+ end
+ end
+
+ private def padding_space_with_escape_sequences(str, width)
+ str + (' ' * (width - calculate_width(str, true)))
+ end
+
+ private def render_each_dialog(dialog, cursor_column)
+ if @in_pasting
+ dialog.contents = nil
+ dialog.trap_key = nil
+ return
+ end
+ dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
+ dialog_render_info = dialog.call(@last_key)
+ if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
+ dialog.lines_backup = {
+ lines: modify_lines(whole_lines),
+ line_index: @line_index,
+ first_line_started_from: @first_line_started_from,
+ started_from: @started_from,
+ byte_pointer: @byte_pointer
+ }
+ clear_each_dialog(dialog)
+ dialog.contents = nil
+ dialog.trap_key = nil
+ return
+ end
+ old_dialog = dialog.clone
+ dialog.contents = dialog_render_info.contents
+ pointer = dialog.pointer
+ if dialog_render_info.width
+ dialog.width = dialog_render_info.width
+ else
+ dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
+ end
+ height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
+ height = dialog.contents.size if dialog.contents.size < height
+ if dialog.contents.size > height
+ if dialog.pointer
+ if dialog.pointer < 0
+ dialog.scroll_top = 0
+ elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
+ dialog.scroll_top = dialog.pointer - (height - 1)
+ elsif (dialog.pointer - dialog.scroll_top) < 0
+ dialog.scroll_top = dialog.pointer
+ end
+ pointer = dialog.pointer - dialog.scroll_top
+ end
+ dialog.contents = dialog.contents[dialog.scroll_top, height]
+ end
+ if dialog.contents and dialog.scroll_top >= dialog.contents.size
+ dialog.scroll_top = dialog.contents.size - height
+ end
+ if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
+ bar_max_height = height * 2
+ moving_distance = (dialog_render_info.contents.size - height) * 2
+ position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
+ bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
+ dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
+ else
+ dialog.scrollbar_pos = nil
+ end
+ upper_space = @first_line_started_from - @started_from
+ lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
+ dialog.column = dialog_render_info.pos.x
+ dialog.width += @block_elem_width if dialog.scrollbar_pos
+ diff = (dialog.column + dialog.width) - (@screen_size.last)
+ if diff > 0
+ dialog.column -= diff
+ end
+ if (lower_space + @rest_height - dialog_render_info.pos.y) >= height
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
+ elsif upper_space >= height
+ dialog.vertical_offset = dialog_render_info.pos.y - height
+ else
+ if (lower_space + @rest_height - dialog_render_info.pos.y) < height
+ scroll_down(height + dialog_render_info.pos.y)
+ move_cursor_up(height + dialog_render_info.pos.y)
+ end
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
+ end
+ Reline::IOGate.hide_cursor
+ if dialog.column < 0
+ dialog.column = 0
+ dialog.width = @screen_size.last
+ end
+ reset_dialog(dialog, old_dialog)
+ move_cursor_down(dialog.vertical_offset)
+ Reline::IOGate.move_cursor_column(dialog.column)
+ dialog.contents.each_with_index do |item, i|
+ if i == pointer
+ bg_color = '45'
+ else
+ if dialog_render_info.bg_color
+ bg_color = dialog_render_info.bg_color
+ else
+ bg_color = '46'
+ end
+ end
+ str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
+ str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
+ @output.write "\e[#{bg_color}m#{str}"
+ if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
+ @output.write "\e[37m"
+ if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
+ @output.write @full_block
+ elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
+ @output.write @upper_half_block
+ str += ''
+ elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
+ @output.write @lower_half_block
+ else
+ @output.write ' ' * @block_elem_width
+ end
+ end
+ @output.write "\e[0m"
+ Reline::IOGate.move_cursor_column(dialog.column)
+ move_cursor_down(1) if i < (dialog.contents.size - 1)
+ end
+ Reline::IOGate.move_cursor_column(cursor_column)
+ move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
+ Reline::IOGate.show_cursor
+ dialog.lines_backup = {
+ lines: modify_lines(whole_lines),
+ line_index: @line_index,
+ first_line_started_from: @first_line_started_from,
+ started_from: @started_from,
+ byte_pointer: @byte_pointer
+ }
+ end
+
+ private def reset_dialog(dialog, old_dialog)
+ return if dialog.lines_backup.nil? or old_dialog.contents.nil?
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
+ visual_lines = []
+ visual_start = nil
+ dialog.lines_backup[:lines].each_with_index { |l, i|
+ pr = prompt_list ? prompt_list[i] : prompt
+ vl, _ = split_by_width(pr + l, @screen_size.last)
+ vl.compact!
+ if i == dialog.lines_backup[:line_index]
+ visual_start = visual_lines.size + dialog.lines_backup[:started_from]
+ end
+ visual_lines.concat(vl)
+ }
+ old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from]
+ y = @first_line_started_from + @started_from
+ y_diff = y - old_y
+ if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset)
+ # rerender top
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
+ start = visual_start + old_dialog.vertical_offset
+ line_num = dialog.vertical_offset - old_dialog.vertical_offset
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * old_dialog.width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
+ s = padding_space_with_escape_sequences(s, old_dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
+ end
+ if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
+ # rerender bottom
+ move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff)
+ start = visual_start + dialog.vertical_offset + dialog.contents.size
+ line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size)
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * old_dialog.width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
+ s = padding_space_with_escape_sequences(s, old_dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
+ end
+ if old_dialog.column < dialog.column
+ # rerender left
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
+ width = dialog.column - old_dialog.column
+ start = visual_start + old_dialog.vertical_offset
+ line_num = old_dialog.contents.size
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
+ s = padding_space_with_escape_sequences(s, dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
+ end
+ if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
+ # rerender right
+ move_cursor_down(old_dialog.vertical_offset + y_diff)
+ width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)
+ start = visual_start + old_dialog.vertical_offset
+ line_num = old_dialog.contents.size
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width)
+ if visual_lines[start + i].nil?
+ s = ' ' * width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
+ s = padding_space_with_escape_sequences(s, dialog.width)
+ end
+ Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
+ end
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ end
+
+ private def clear_dialog
+ @dialogs.each do |dialog|
+ clear_each_dialog(dialog)
+ end
+ end
+
+ private def clear_each_dialog(dialog)
+ dialog.trap_key = nil
+ return unless dialog.contents
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
+ visual_lines = []
+ visual_lines_under_dialog = []
+ visual_start = nil
+ dialog.lines_backup[:lines].each_with_index { |l, i|
+ pr = prompt_list ? prompt_list[i] : prompt
+ vl, _ = split_by_width(pr + l, @screen_size.last)
+ vl.compact!
+ if i == dialog.lines_backup[:line_index]
+ visual_start = visual_lines.size + dialog.lines_backup[:started_from] + dialog.vertical_offset
+ end
+ visual_lines.concat(vl)
+ }
+ visual_lines_under_dialog = visual_lines[visual_start, dialog.contents.size]
+ visual_lines_under_dialog = [] if visual_lines_under_dialog.nil?
+ Reline::IOGate.hide_cursor
+ move_cursor_down(dialog.vertical_offset)
+ dialog_vertical_size = dialog.contents.size
+ dialog_vertical_size.times do |i|
+ if i < visual_lines_under_dialog.size
+ Reline::IOGate.move_cursor_column(dialog.column)
+ str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
+ str = padding_space_with_escape_sequences(str, dialog.width)
+ @output.write "\e[0m#{str}\e[0m"
+ else
+ Reline::IOGate.move_cursor_column(dialog.column)
+ @output.write "\e[0m#{' ' * dialog.width}\e[0m"
+ end
+ move_cursor_down(1) if i < (dialog_vertical_size - 1)
+ end
+ move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ Reline::IOGate.show_cursor
+ end
+
private def calculate_scroll_partial_screen(highest_in_all, cursor_y)
if @screen_height < highest_in_all
old_scroll_partial_screen = @scroll_partial_screen
@@ -805,7 +1254,7 @@ class Reline::LineEditor
height = render_partial(prompt, prompt_width, line, back, with_control: false)
end
if index < (@buffer_of_lines.size - 1)
- move_cursor_down(height)
+ move_cursor_down(1)
back += height
end
end
@@ -924,6 +1373,16 @@ class Reline::LineEditor
@completion_journey_data = CompletionJourneyData.new(
preposing, postposing,
[target] + list.select{ |item| item.start_with?(target) }, 0)
+ if @completion_journey_data.list.size == 1
+ @completion_journey_data.pointer = 0
+ else
+ case direction
+ when :up
+ @completion_journey_data.pointer = @completion_journey_data.list.size - 1
+ when :down
+ @completion_journey_data.pointer = 1
+ end
+ end
@completion_state = CompletionState::JOURNEY
else
case direction
@@ -938,13 +1397,15 @@ class Reline::LineEditor
@completion_journey_data.pointer = 0
end
end
- completed = @completion_journey_data.list[@completion_journey_data.pointer]
- @line = @completion_journey_data.preposing + completed + @completion_journey_data.postposing
- line_to_pointer = @completion_journey_data.preposing + completed
- @cursor_max = calculate_width(@line)
- @cursor = calculate_width(line_to_pointer)
- @byte_pointer = line_to_pointer.bytesize
end
+ completed = @completion_journey_data.list[@completion_journey_data.pointer]
+ new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index]
+ @line = new_line.nil? ? String.new(encoding: @encoding) : new_line
+ line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last
+ line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil?
+ @cursor_max = calculate_width(@line)
+ @cursor = calculate_width(line_to_pointer)
+ @byte_pointer = line_to_pointer.bytesize
end
private def run_for_operators(key, method_symbol, &block)
@@ -976,7 +1437,10 @@ class Reline::LineEditor
end
@waiting_operator_proc = nil
@waiting_operator_vi_arg = nil
- @vi_arg = nil
+ if @vi_arg
+ @rerender_all = true
+ @vi_arg = nil
+ end
else
block.(false)
end
@@ -1027,7 +1491,10 @@ class Reline::LineEditor
wrap_method_call(method_symbol, method_obj, key) if method_obj
end
@kill_ring.process
- @vi_arg = nil
+ if @vi_arg
+ @rerender_al = true
+ @vi_arg = nil
+ end
elsif @vi_arg
if key.chr =~ /[0-9]/
ed_argument_digit(key)
@@ -1044,7 +1511,10 @@ class Reline::LineEditor
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
end
@kill_ring.process
- @vi_arg = nil
+ if @vi_arg
+ @rerender_all = true
+ @vi_arg = nil
+ end
end
elsif @waiting_proc
@waiting_proc.(key)
@@ -1102,6 +1572,13 @@ class Reline::LineEditor
end
def input_key(key)
+ @last_key = key
+ @config.reset_oneshot_key_bindings
+ @dialogs.each do |dialog|
+ if key.char.instance_of?(Symbol) and key.char == dialog.name
+ return
+ end
+ end
@just_cursor_moving = nil
if key.char.nil?
if @first_char
@@ -1119,7 +1596,20 @@ class Reline::LineEditor
if result.is_a?(Array)
completion_occurs = true
process_insert
- complete(result)
+ if @config.autocompletion
+ move_completed_list(result, :down)
+ else
+ complete(result)
+ end
+ end
+ end
+ elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up
+ if not @config.disable_completion and @config.autocompletion
+ result = call_completion_proc
+ if result.is_a?(Array)
+ completion_occurs = true
+ process_insert
+ move_completed_list(result, :up)
end
end
elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
@@ -1138,6 +1628,7 @@ class Reline::LineEditor
end
unless completion_occurs
@completion_state = CompletionState::NORMAL
+ @completion_journey_data = nil
end
if not @in_pasting and @just_cursor_moving.nil?
if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line
@@ -1157,7 +1648,13 @@ class Reline::LineEditor
def call_completion_proc
result = retrieve_completion_block(true)
- preposing, target, postposing = result
+ pre, target, post = result
+ result = call_completion_proc_with_checking_args(pre, target, post)
+ Reline.core.instance_variable_set(:@completion_quote_character, nil)
+ result
+ end
+
+ def call_completion_proc_with_checking_args(pre, target, post)
if @completion_proc and target
argnum = @completion_proc.parameters.inject(0) { |result, item|
case item.first
@@ -1171,12 +1668,11 @@ class Reline::LineEditor
when 1
result = @completion_proc.(target)
when 2
- result = @completion_proc.(target, preposing)
+ result = @completion_proc.(target, pre)
when 3..Float::INFINITY
- result = @completion_proc.(target, preposing, postposing)
+ result = @completion_proc.(target, pre, post)
end
end
- Reline.core.instance_variable_set(:@completion_quote_character, nil)
result
end
@@ -1457,6 +1953,8 @@ class Reline::LineEditor
end
end
+ # Editline:: +ed-unassigned+ This editor command always results in an error.
+ # GNU Readline:: There is no corresponding macro.
private def ed_unassigned(key) end # do nothing
private def process_insert(force: false)
@@ -1474,6 +1972,19 @@ class Reline::LineEditor
@continuous_insertion_buffer.clear
end
+ # Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters)
+ # In insert mode, insert the input character left of the cursor
+ # position. In replace mode, overwrite the character at the
+ # cursor and move the cursor to the right by one character
+ # position. Accept an argument to do this repeatedly. It is an
+ # error if the input character is the NUL character (+Ctrl-@+).
+ # Failure to enlarge the edit buffer also results in an error.
+ # Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append
+ # the input digit to the argument being read. Otherwise, call
+ # +ed-insert+. It is an error if the input character is not a
+ # digit or if the existing argument is already greater than a
+ # million.
+ # GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
private def ed_insert(key)
str = nil
width = nil
@@ -1524,6 +2035,8 @@ class Reline::LineEditor
arg.times do
if key == "\C-j".ord or key == "\C-m".ord
key_newline(key)
+ elsif key == 0
+ # Ignore NUL.
else
ed_insert(key)
end
@@ -1958,6 +2471,7 @@ class Reline::LineEditor
arg -= 1
ed_prev_history(key, arg: arg) if arg > 0
end
+ alias_method :previous_history, :ed_prev_history
private def ed_next_history(key, arg: 1)
if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
@@ -2005,6 +2519,7 @@ class Reline::LineEditor
arg -= 1
ed_next_history(key, arg: arg) if arg > 0
end
+ alias_method :next_history, :ed_next_history
private def ed_newline(key)
process_insert(force: true)
@@ -2039,7 +2554,7 @@ class Reline::LineEditor
end
end
- private def em_delete_prev_char(key)
+ private def em_delete_prev_char(key, arg: 1)
if @is_multiline and @cursor == 0 and @line_index > 0
@buffer_of_lines[@line_index] = @line
@cursor = calculate_width(@buffer_of_lines[@line_index - 1])
@@ -2057,6 +2572,8 @@ class Reline::LineEditor
@cursor -= width
@cursor_max -= width
end
+ arg -= 1
+ em_delete_prev_char(key, arg: arg) if arg > 0
end
alias_method :backward_delete_char, :em_delete_prev_char
@@ -2076,6 +2593,7 @@ class Reline::LineEditor
@rest_height += 1
end
end
+ alias_method :kill_line, :ed_kill_line
private def em_kill_line(key)
if @byte_pointer > 0
@@ -2086,7 +2604,8 @@ class Reline::LineEditor
@cursor = 0
end
end
- alias_method :kill_line, :em_kill_line
+ alias_method :unix_line_discard, :em_kill_line
+ alias_method :vi_kill_line_prev, :em_kill_line
private def em_delete(key)
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
@@ -2591,7 +3110,14 @@ class Reline::LineEditor
private def ed_argument_digit(key)
if @vi_arg.nil?
- unless key.chr.to_i.zero?
+ if key.chr.to_i.zero?
+ if key.anybits?(0b10000000)
+ unescaped_key = key ^ 0b10000000
+ unless unescaped_key.chr.to_i.zero?
+ @vi_arg = unescaped_key.chr.to_i
+ end
+ end
+ else
@vi_arg = key.chr.to_i
end
else
diff --git a/lib/reline/terminfo.rb b/lib/reline/terminfo.rb
index 811f740229..b4d1d735f8 100644
--- a/lib/reline/terminfo.rb
+++ b/lib/reline/terminfo.rb
@@ -1,5 +1,13 @@
-require 'fiddle'
-require 'fiddle/import'
+begin
+ require 'fiddle'
+ require 'fiddle/import'
+rescue LoadError
+ module Reline::Terminfo
+ def self.curses_dl
+ false
+ end
+ end
+end
module Reline::Terminfo
extend Fiddle::Importer
@@ -20,9 +28,9 @@ module Reline::Terminfo
end
end
- @curses_dl = nil
+ @curses_dl = false
def self.curses_dl
- return @curses_dl if @curses_dl
+ return @curses_dl unless @curses_dl == false
if RUBY_VERSION >= '3.0.0'
# Gem module isn't defined in test-all of the Ruby repository, and
# Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC.
@@ -33,7 +41,7 @@ module Reline::Terminfo
else
fiddle_supports_variadic = false
end
- if fiddle_supports_variadic and Fiddle.const_defined?(:TYPE_VARIADIC)
+ if fiddle_supports_variadic and not Fiddle.const_defined?(:TYPE_VARIADIC)
# If the libffi version is not 3.0.5 or higher, there isn't TYPE_VARIADIC.
fiddle_supports_variadic = false
end
@@ -47,9 +55,10 @@ module Reline::Terminfo
break
end
end
+ @curses_dl = nil if @curses_dl == false
@curses_dl
end
-end
+end if not Reline.const_defined?(:Terminfo) or not Reline::Terminfo.respond_to?(:curses_dl)
module Reline::Terminfo
dlload curses_dl
@@ -70,7 +79,7 @@ module Reline::Terminfo
def self.setupterm(term, fildes)
errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
ret = @setupterm.(term, fildes, errret_int)
- errret = errret_int.unpack('i')[0]
+ errret = errret_int.unpack1('i')
case ret
when 0 # OK
0
@@ -97,7 +106,12 @@ module Reline::Terminfo
end
def self.tigetstr(capname)
- StringWithTiparm.new(@tigetstr.(capname).to_s)
+ capability = @tigetstr.(capname)
+ case capability.to_i
+ when 0, -1
+ raise TerminfoError, "can't find capability: #{capname}"
+ end
+ StringWithTiparm.new(capability.to_s)
end
def self.tiparm(str, *args)
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
index 7dbe8a12a5..80cc54a05e 100644
--- a/lib/reline/unicode.rb
+++ b/lib/reline/unicode.rb
@@ -101,9 +101,9 @@ class Reline::Unicode
def self.get_mbchar_width(mbchar)
ord = mbchar.ord
- if (0x00 <= ord and ord <= 0x1F)
+ if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs
return 2
- elsif (0x20 <= ord and ord <= 0x7E)
+ elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars
return 1
end
m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
@@ -185,6 +185,37 @@ class Reline::Unicode
[lines, height]
end
+ # Take a chunk of a String cut by width with escape sequences.
+ def self.take_range(str, start_col, max_width, encoding = str.encoding)
+ chunk = String.new(encoding: encoding)
+ total_width = 0
+ rest = str.encode(Encoding::UTF_8)
+ in_zero_width = false
+ rest.scan(WIDTH_SCANNER) do |gc|
+ case
+ when gc[NON_PRINTING_START_INDEX]
+ in_zero_width = true
+ when gc[NON_PRINTING_END_INDEX]
+ in_zero_width = false
+ when gc[CSI_REGEXP_INDEX]
+ chunk << gc[CSI_REGEXP_INDEX]
+ when gc[OSC_REGEXP_INDEX]
+ chunk << gc[OSC_REGEXP_INDEX]
+ when gc[GRAPHEME_CLUSTER_INDEX]
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
+ if in_zero_width
+ chunk << gc
+ else
+ mbchar_width = get_mbchar_width(gc)
+ total_width += mbchar_width
+ break if (start_col + max_width) < total_width
+ chunk << gc if start_col < total_width
+ end
+ end
+ end
+ chunk
+ end
+
def self.get_next_mbchar_size(line, byte_pointer)
grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first
grapheme ? grapheme.bytesize : 0
diff --git a/lib/reline/version.rb b/lib/reline/version.rb
index 42855b1bd2..8425d5e14a 100644
--- a/lib/reline/version.rb
+++ b/lib/reline/version.rb
@@ -1,3 +1,3 @@
module Reline
- VERSION = '0.2.6'
+ VERSION = '0.2.8.pre.11'
end
diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb
index 5b4cb05b99..73653b2de2 100644
--- a/lib/reline/windows.rb
+++ b/lib/reline/windows.rb
@@ -42,6 +42,14 @@ class Reline::Windows
}.each_pair do |key, func|
config.add_default_key_binding_by_keymap(:emacs, key, func)
end
+
+ # Emulate ANSI key sequence.
+ {
+ [27, 91, 90] => :completion_journey_up, # S-Tab
+ }.each_pair do |key, func|
+ config.add_default_key_binding_by_keymap(:emacs, key, func)
+ config.add_default_key_binding_by_keymap(:vi_insert, key, func)
+ end
end
if defined? JRUBY_VERSION
@@ -106,6 +114,7 @@ class Reline::Windows
SCROLLLOCK_ON = 0x0040
SHIFT_PRESSED = 0x0010
+ VK_TAB = 0x09
VK_END = 0x23
VK_HOME = 0x24
VK_LEFT = 0x25
@@ -133,9 +142,11 @@ class Reline::Windows
@@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
@@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
@@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L')
+ @@SetConsoleCursorInfo = Win32API.new('kernel32', 'SetConsoleCursorInfo', ['L', 'P'], 'L')
@@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
@@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')
+ @@WaitForSingleObject = Win32API.new('kernel32', 'WaitForSingleObject', ['L', 'L'], 'L')
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
private_class_method def self.getconsolemode
@@ -173,7 +184,7 @@ class Reline::Windows
# DWORD FileNameLength;
# WCHAR FileName[1];
# } FILE_NAME_INFO
- len = p_buffer[0, 4].unpack("L")[0]
+ len = p_buffer[0, 4].unpack1("L")
name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
# Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
@@ -197,6 +208,9 @@ class Reline::Windows
[ { control_keys: [], virtual_key_code: VK_DELETE }, [0, 83] ],
[ { control_keys: [], virtual_key_code: VK_HOME }, [0, 71] ],
[ { control_keys: [], virtual_key_code: VK_END }, [0, 79] ],
+
+ # Emulate ANSI key sequence.
+ [ { control_keys: :SHIFT, virtual_key_code: VK_TAB }, [27, 91, 90] ],
]
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
@@ -212,27 +226,31 @@ class Reline::Windows
# no char, only control keys
return if key.char_code == 0 and key.control_keys.any?
+ @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT)
+
@@output_buf.concat(key.char.bytes)
end
def self.check_input_event
num_of_events = 0.chr * 8
- while @@output_buf.empty? #or true
- next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack('L').first == 0
+ while @@output_buf.empty?
+ Reline.core.line_editor.resize
+ next if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
+ next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
input_record = 0.chr * 18
read_event = 0.chr * 4
if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
- event = input_record[0, 2].unpack('s*').first
+ event = input_record[0, 2].unpack1('s*')
case event
when WINDOW_BUFFER_SIZE_EVENT
@@winch_handler.()
when KEY_EVENT
- key_down = input_record[4, 4].unpack('l*').first
- repeat_count = input_record[8, 2].unpack('s*').first
- virtual_key_code = input_record[10, 2].unpack('s*').first
- virtual_scan_code = input_record[12, 2].unpack('s*').first
- char_code = input_record[14, 2].unpack('S*').first
- control_key_state = input_record[16, 2].unpack('S*').first
+ key_down = input_record[4, 4].unpack1('l*')
+ repeat_count = input_record[8, 2].unpack1('s*')
+ virtual_key_code = input_record[10, 2].unpack1('s*')
+ virtual_scan_code = input_record[12, 2].unpack1('s*')
+ char_code = input_record[14, 2].unpack1('S*')
+ control_key_state = input_record[16, 2].unpack1('S*')
is_key_down = key_down.zero? ? false : true
if is_key_down
process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
@@ -265,17 +283,25 @@ class Reline::Windows
end
end
- def self.get_screen_size
+ def self.get_console_screen_buffer_info
csbi = 0.chr * 22
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
+ return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
+ csbi
+ end
+
+ def self.get_screen_size
+ unless csbi = get_console_screen_buffer_info
+ return [1, 1]
+ end
csbi[0, 4].unpack('SS').reverse
end
def self.cursor_pos
- csbi = 0.chr * 22
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
- x = csbi[4, 2].unpack('s*').first
- y = csbi[6, 2].unpack('s*').first
+ unless csbi = get_console_screen_buffer_info
+ return Reline::CursorPos.new(0, 0)
+ end
+ x = csbi[4, 2].unpack1('s*')
+ y = csbi[6, 2].unpack1('s*')
Reline::CursorPos.new(x, y)
end
@@ -295,6 +321,7 @@ class Reline::Windows
def self.move_cursor_down(val)
if val > 0
+ return unless csbi = get_console_screen_buffer_info
screen_height = get_screen_size.first
y = cursor_pos.y + val
y = screen_height - 1 if y > (screen_height - 1)
@@ -305,12 +332,12 @@ class Reline::Windows
end
def self.erase_after_cursor
- csbi = 0.chr * 24
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
- cursor = csbi[4, 4].unpack('L').first
+ return unless csbi = get_console_screen_buffer_info
+ attributes = csbi[8, 2].unpack1('S')
+ cursor = csbi[4, 4].unpack1('L')
written = 0.chr * 4
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
- @@FillConsoleOutputAttribute.call(@@hConsoleHandle, 0, get_screen_size.last - cursor_pos.x, cursor, written)
+ @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
end
def self.scroll_down(val)
@@ -324,10 +351,9 @@ class Reline::Windows
end
def self.clear_screen
- csbi = 0.chr * 22
- return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
- buffer_width = csbi[0, 2].unpack('S').first
- attributes = csbi[8, 2].unpack('S').first
+ return unless csbi = get_console_screen_buffer_info
+ buffer_width = csbi[0, 2].unpack1('S')
+ attributes = csbi[8, 2].unpack1('S')
_window_left, window_top, _window_right, window_bottom = *csbi[10,8].unpack('S*')
fill_length = buffer_width * (window_bottom - window_top + 1)
screen_topleft = window_top * 65536
@@ -341,6 +367,20 @@ class Reline::Windows
raise NotImplementedError
end
+ def self.hide_cursor
+ size = 100
+ visible = 0 # 0 means false
+ cursor_info = [size, visible].pack('Li')
+ @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
+ end
+
+ def self.show_cursor
+ size = 100
+ visible = 1 # 1 means true
+ cursor_info = [size, visible].pack('Li')
+ @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
+ end
+
def self.set_winch_handler(&handler)
@@winch_handler = handler
end
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 60a599e380..80708e2aa0 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -12,11 +12,11 @@ module Gem
end
# Must be first since it unloads the prelude from 1.9.2
-require 'rubygems/compatibility'
+require_relative 'rubygems/compatibility'
-require 'rubygems/defaults'
-require 'rubygems/deprecate'
-require 'rubygems/errors'
+require_relative 'rubygems/defaults'
+require_relative 'rubygems/deprecate'
+require_relative 'rubygems/errors'
##
# RubyGems is the Ruby standard for publishing and managing third party
@@ -249,9 +249,6 @@ module Gem
# you to specify specific gem versions.
def self.bin_path(name, exec_name = nil, *requirements)
- # TODO: fails test_self_bin_path_bin_file_gone_in_latest
- # Gem::Specification.find_by_name(name, *requirements).bin_file exec_name
-
requirements = Gem::Requirement.default if
requirements.empty?
@@ -562,7 +559,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
def self.install(name, version = Gem::Requirement.default, *options)
- require "rubygems/dependency_installer"
+ require_relative "rubygems/dependency_installer"
inst = Gem::DependencyInstaller.new(*options)
inst.install name, version
inst.installed_gems
@@ -628,12 +625,12 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
rescue ::LoadError
# If we can't load psych, that's fine, go on.
else
- require 'rubygems/psych_additions'
- require 'rubygems/psych_tree'
+ require_relative 'rubygems/psych_additions'
+ require_relative 'rubygems/psych_tree'
end
require 'yaml'
- require 'rubygems/safe_yaml'
+ require_relative 'rubygems/safe_yaml'
@yaml_loaded = true
end
@@ -993,7 +990,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Lazily loads DefaultUserInteraction and returns the default UI.
def self.ui
- require 'rubygems/user_interaction'
+ require_relative 'rubygems/user_interaction'
Gem::DefaultUserInteraction.ui
end
@@ -1053,7 +1050,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Find rubygems plugin files in the standard location and load them
def self.load_plugins
- load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir)
+ Gem.path.each do |gem_path|
+ load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir(gem_path))
+ end
end
##
@@ -1111,27 +1110,22 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path)
- require 'rubygems/user_interaction'
- Gem::DefaultUserInteraction.use_ui(ui) do
- require "bundler"
- begin
- Bundler.ui.silence do
- @gemdeps = Bundler.setup
+ require_relative 'rubygems/user_interaction'
+ require "bundler"
+ begin
+ Gem::DefaultUserInteraction.use_ui(ui) do
+ begin
+ Bundler.ui.silence do
+ @gemdeps = Bundler.setup
+ end
+ ensure
+ Gem::DefaultUserInteraction.ui.close
end
- ensure
- Gem::DefaultUserInteraction.ui.close
end
- @gemdeps.requested_specs.map(&:to_spec).sort_by(&:name)
- end
-
- rescue => e
- case e
- when Gem::LoadError, Gem::UnsatisfiableDependencyError, (defined?(Bundler::GemNotFound) ? Bundler::GemNotFound : Gem::LoadError)
+ rescue Bundler::BundlerError => e
warn e.message
- warn "You may need to `gem install -g` to install missing gems"
+ warn "You may need to `bundle install` to install missing gems"
warn ""
- else
- raise
end
end
@@ -1328,7 +1322,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
autoload :Version, File.expand_path('rubygems/version', __dir__)
end
-require 'rubygems/exceptions'
+require_relative 'rubygems/exceptions'
# REFACTOR: This should be pulled out into some kind of hacks file.
begin
@@ -1337,6 +1331,14 @@ begin
require 'rubygems/defaults/operating_system'
rescue LoadError
+ # Ignored
+rescue StandardError => e
+ msg = "#{e.message}\n" \
+ "Loading the rubygems/defaults/operating_system.rb file caused an error. " \
+ "This file is owned by your OS, not by rubygems upstream. " \
+ "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \
+ "the problem and ask for help."
+ raise e.class, msg
end
begin
@@ -1351,8 +1353,6 @@ end
# Loads the default specs.
Gem::Specification.load_defaults
-require 'rubygems/core_ext/kernel_gem'
-require 'rubygems/core_ext/kernel_require'
-require 'rubygems/core_ext/kernel_warn'
-
-Gem.use_gemdeps
+require_relative 'rubygems/core_ext/kernel_gem'
+require_relative 'rubygems/core_ext/kernel_require'
+require_relative 'rubygems/core_ext/kernel_warn'
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 2409550882..39bf8bd30d 100644
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -5,9 +5,9 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/command'
-require 'rubygems/user_interaction'
-require 'rubygems/text'
+require_relative 'command'
+require_relative 'user_interaction'
+require_relative 'text'
##
# The command manager registers and installs all the individual sub-commands
diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb
index 842ec1855a..6d1a057dfa 100644
--- a/lib/rubygems/commands/build_command.rb
+++ b/lib/rubygems/commands/build_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/package'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../package'
+require_relative '../version_option'
class Gem::Commands::BuildCommand < Gem::Command
include Gem::VersionOption
diff --git a/lib/rubygems/commands/cert_command.rb b/lib/rubygems/commands/cert_command.rb
index 3fc0daea7d..bdfeb0ba6e 100644
--- a/lib/rubygems/commands/cert_command.rb
+++ b/lib/rubygems/commands/cert_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/security'
+require_relative '../command'
+require_relative '../security'
class Gem::Commands::CertCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/check_command.rb b/lib/rubygems/commands/check_command.rb
index 8b8eda53cf..3b6b97ae3b 100644
--- a/lib/rubygems/commands/check_command.rb
+++ b/lib/rubygems/commands/check_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/validator'
-require 'rubygems/doctor'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../validator'
+require_relative '../doctor'
class Gem::Commands::CheckCommand < Gem::Command
include Gem::VersionOption
diff --git a/lib/rubygems/commands/cleanup_command.rb b/lib/rubygems/commands/cleanup_command.rb
index 662badce33..c965085880 100644
--- a/lib/rubygems/commands/cleanup_command.rb
+++ b/lib/rubygems/commands/cleanup_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/dependency_list'
-require 'rubygems/uninstaller'
+require_relative '../command'
+require_relative '../dependency_list'
+require_relative '../uninstaller'
class Gem::Commands::CleanupCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb
index f17aed64db..716022c458 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../version_option'
class Gem::Commands::ContentsCommand < Gem::Command
include Gem::VersionOption
diff --git a/lib/rubygems/commands/dependency_command.rb b/lib/rubygems/commands/dependency_command.rb
index e472d8fa8d..7d217076a5 100644
--- a/lib/rubygems/commands/dependency_command.rb
+++ b/lib/rubygems/commands/dependency_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
class Gem::Commands::DependencyCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index 37429fb836..b6eeb620bd 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::EnvironmentCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/fetch_command.rb b/lib/rubygems/commands/fetch_command.rb
index 6a1b346dd3..619f56a5da 100644
--- a/lib/rubygems/commands/fetch_command.rb
+++ b/lib/rubygems/commands/fetch_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
class Gem::Commands::FetchCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/generate_index_command.rb b/lib/rubygems/commands/generate_index_command.rb
index 93e25ef5e4..87200dab91 100644
--- a/lib/rubygems/commands/generate_index_command.rb
+++ b/lib/rubygems/commands/generate_index_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/indexer'
+require_relative '../command'
+require_relative '../indexer'
##
# Generates a index files for use as a gem server.
diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb
index 4e8d7600fb..7f3383c9f3 100644
--- a/lib/rubygems/commands/help_command.rb
+++ b/lib/rubygems/commands/help_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::HelpCommand < Gem::Command
# :stopdoc:
diff --git a/lib/rubygems/commands/info_command.rb b/lib/rubygems/commands/info_command.rb
index 9ca6ae364f..3f2dd4ae0b 100644
--- a/lib/rubygems/commands/info_command.rb
+++ b/lib/rubygems/commands/info_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+require_relative '../command'
+require_relative '../query_utils'
class Gem::Commands::InfoCommand < Gem::Command
include Gem::QueryUtils
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 4d36c69d51..adf2cdba84 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/install_update_options'
-require 'rubygems/dependency_installer'
-require 'rubygems/local_remote_options'
-require 'rubygems/validator'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../install_update_options'
+require_relative '../dependency_installer'
+require_relative '../local_remote_options'
+require_relative '../validator'
+require_relative '../version_option'
##
# Gem installer command line tool
@@ -172,7 +172,7 @@ You can use `i` command instead of `install`.
end
def install_from_gemdeps # :nodoc:
- require 'rubygems/request_set'
+ require_relative '../request_set'
rs = Gem::RequestSet.new
specs = rs.install_from_gemdeps options do |req, inst|
@@ -247,11 +247,11 @@ You can use `i` command instead of `install`.
def load_hooks # :nodoc:
if options[:install_as_default]
- require 'rubygems/install_default_message'
+ require_relative '../install_default_message'
else
- require 'rubygems/install_message'
+ require_relative '../install_message'
end
- require 'rubygems/rdoc'
+ require_relative '../rdoc'
end
def show_install_errors(errors) # :nodoc:
@@ -260,7 +260,8 @@ You can use `i` command instead of `install`.
errors.each do |x|
return unless Gem::SourceFetchProblem === x
- msg = "Unable to pull data from '#{x.source.uri}': #{x.error.message}"
+ require_relative "../uri"
+ msg = "Unable to pull data from '#{Gem::Uri.new(x.source.uri).redacted}': #{x.error.message}"
alert_warning msg
end
diff --git a/lib/rubygems/commands/list_command.rb b/lib/rubygems/commands/list_command.rb
index 5c99d3d73d..dea11111c9 100644
--- a/lib/rubygems/commands/list_command.rb
+++ b/lib/rubygems/commands/list_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+require_relative '../command'
+require_relative '../query_utils'
##
# Searches for gems starting with the supplied argument.
diff --git a/lib/rubygems/commands/lock_command.rb b/lib/rubygems/commands/lock_command.rb
index f1dc1ac586..cb6229a2cb 100644
--- a/lib/rubygems/commands/lock_command.rb
+++ b/lib/rubygems/commands/lock_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::LockCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/mirror_command.rb b/lib/rubygems/commands/mirror_command.rb
index 86671a93b2..7daa47e2f0 100644
--- a/lib/rubygems/commands/mirror_command.rb
+++ b/lib/rubygems/commands/mirror_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
unless defined? Gem::Commands::MirrorCommand
class Gem::Commands::MirrorCommand < Gem::Command
diff --git a/lib/rubygems/commands/open_command.rb b/lib/rubygems/commands/open_command.rb
index 8012a9a0e1..1e616fd68f 100644
--- a/lib/rubygems/commands/open_command.rb
+++ b/lib/rubygems/commands/open_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../version_option'
class Gem::Commands::OpenCommand < Gem::Command
include Gem::VersionOption
diff --git a/lib/rubygems/commands/outdated_command.rb b/lib/rubygems/commands/outdated_command.rb
index 3579bfc3ba..162d338320 100644
--- a/lib/rubygems/commands/outdated_command.rb
+++ b/lib/rubygems/commands/outdated_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../spec_fetcher'
+require_relative '../version_option'
class Gem::Commands::OutdatedCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb
index dd49027469..0a5665228f 100644
--- a/lib/rubygems/commands/owner_command.rb
+++ b/lib/rubygems/commands/owner_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/gemcutter_utilities'
-require 'rubygems/text'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../gemcutter_utilities'
+require_relative '../text'
class Gem::Commands::OwnerCommand < Gem::Command
include Gem::Text
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 143105981e..41547ce73b 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/package'
-require 'rubygems/installer'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../package'
+require_relative '../installer'
+require_relative '../version_option'
class Gem::Commands::PristineCommand < Gem::Command
include Gem::VersionOption
@@ -138,7 +138,7 @@ extensions will be restored.
gem = spec.cache_file
unless File.exist? gem or options[:only_executables] or options[:only_plugins]
- require 'rubygems/remote_fetcher'
+ require_relative '../remote_fetcher'
say "Cached gem for #{spec.full_name} not found, attempting to fetch..."
diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb
index 1a9a1932f8..1864b4b095 100644
--- a/lib/rubygems/commands/push_command.rb
+++ b/lib/rubygems/commands/push_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/gemcutter_utilities'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../gemcutter_utilities'
+require_relative '../package'
class Gem::Commands::PushCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
index 789afd6509..5896bec44e 100644
--- a/lib/rubygems/commands/query_command.rb
+++ b/lib/rubygems/commands/query_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
-require 'rubygems/deprecate'
+require_relative '../command'
+require_relative '../query_utils'
+require_relative '../deprecate'
class Gem::Commands::QueryCommand < Gem::Command
extend Gem::Deprecate
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index e8c9e84b29..305c80ccfe 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/rdoc'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../rdoc'
require 'fileutils'
class Gem::Commands::RdocCommand < Gem::Command
diff --git a/lib/rubygems/commands/search_command.rb b/lib/rubygems/commands/search_command.rb
index aeb2119235..488d777939 100644
--- a/lib/rubygems/commands/search_command.rb
+++ b/lib/rubygems/commands/search_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+require_relative '../command'
+require_relative '../query_utils'
class Gem::Commands::SearchCommand < Gem::Command
include Gem::QueryUtils
diff --git a/lib/rubygems/commands/server_command.rb b/lib/rubygems/commands/server_command.rb
index 594cf77f66..f3c08efb5e 100644
--- a/lib/rubygems/commands/server_command.rb
+++ b/lib/rubygems/commands/server_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/server'
-require 'rubygems/deprecate'
+require_relative '../command'
+require_relative '../server'
+require_relative '../deprecate'
class Gem::Commands::ServerCommand < Gem::Command
extend Gem::Deprecate
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 47e215c149..00953a8f4b 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
##
# Installs RubyGems itself. This command is ordinarily only available from a
@@ -348,7 +348,7 @@ By default, this RubyGems will install gem as:
rm_rf dir
end
- require 'rubygems/rdoc'
+ require_relative '../rdoc'
fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
def fake_spec.full_gem_path
@@ -407,7 +407,7 @@ By default, this RubyGems will install gem as:
cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e)
end
- require 'rubygems/installer'
+ require_relative '../installer'
Dir.chdir("bundler") do
built_gem = Gem::Package.build(bundler_spec)
@@ -462,20 +462,8 @@ By default, this RubyGems will install gem as:
lib_dir = RbConfig::CONFIG[site_or_vendor]
bin_dir = RbConfig::CONFIG['bindir']
else
- # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
- # confused about installation location, so switch back to
- # sitelibdir/vendorlibdir.
- if defined?(APPLE_GEM_HOME) and
- # just in case Apple and RubyGems don't get this patched up proper.
- (prefix == RbConfig::CONFIG['libdir'] or
- # this one is important
- prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby'))
- lib_dir = RbConfig::CONFIG[site_or_vendor]
- bin_dir = RbConfig::CONFIG['bindir']
- else
- lib_dir = File.join prefix, 'lib'
- bin_dir = File.join prefix, 'bin'
- end
+ lib_dir = File.join prefix, 'lib'
+ bin_dir = File.join prefix, 'bin'
end
unless install_destdir.empty?
@@ -596,7 +584,7 @@ abort "#{deprecation_message}"
end
def uninstall_old_gemcutter
- require 'rubygems/uninstaller'
+ require_relative '../uninstaller'
ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true,
:version => '< 0.4')
@@ -605,7 +593,7 @@ abort "#{deprecation_message}"
end
def regenerate_binstubs
- require "rubygems/commands/pristine_command"
+ require_relative "pristine_command"
say "Regenerating binstubs"
args = %w[--all --only-executables --silent]
@@ -618,7 +606,7 @@ abort "#{deprecation_message}"
end
def regenerate_plugins
- require "rubygems/commands/pristine_command"
+ require_relative "pristine_command"
say "Regenerating plugins"
args = %w[--all --only-plugins --silent]
diff --git a/lib/rubygems/commands/signin_command.rb b/lib/rubygems/commands/signin_command.rb
index 2e19c8333c..23bb2f937f 100644
--- a/lib/rubygems/commands/signin_command.rb
+++ b/lib/rubygems/commands/signin_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/gemcutter_utilities'
+require_relative '../command'
+require_relative '../gemcutter_utilities'
class Gem::Commands::SigninCommand < Gem::Command
include Gem::GemcutterUtilities
diff --git a/lib/rubygems/commands/signout_command.rb b/lib/rubygems/commands/signout_command.rb
index ebbe746cb4..c9485e0c1b 100644
--- a/lib/rubygems/commands/signout_command.rb
+++ b/lib/rubygems/commands/signout_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::SignoutCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb
index f74fb12e42..9e74f3c47d 100644
--- a/lib/rubygems/commands/sources_command.rb
+++ b/lib/rubygems/commands/sources_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/remote_fetcher'
-require 'rubygems/spec_fetcher'
-require 'rubygems/local_remote_options'
+require_relative '../command'
+require_relative '../remote_fetcher'
+require_relative '../spec_fetcher'
+require_relative '../local_remote_options'
class Gem::Commands::SourcesCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/specification_command.rb b/lib/rubygems/commands/specification_command.rb
index 3fddaaaf30..473b6e7b19 100644
--- a/lib/rubygems/commands/specification_command.rb
+++ b/lib/rubygems/commands/specification_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
+require_relative '../package'
class Gem::Commands::SpecificationCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/commands/stale_command.rb b/lib/rubygems/commands/stale_command.rb
index badc9905c1..62a97966f1 100644
--- a/lib/rubygems/commands/stale_command.rb
+++ b/lib/rubygems/commands/stale_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::StaleCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb
index 1540b2f0fb..20781b224d 100644
--- a/lib/rubygems/commands/uninstall_command.rb
+++ b/lib/rubygems/commands/uninstall_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/uninstaller'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../uninstaller'
require 'fileutils'
##
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index 8d90d08eb4..3f1708375f 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/security_option'
-require 'rubygems/remote_fetcher'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../security_option'
+require_relative '../remote_fetcher'
+require_relative '../package'
# forward-declare
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 91d93e398c..d104488c94 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/command_manager'
-require 'rubygems/dependency_installer'
-require 'rubygems/install_update_options'
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
-require 'rubygems/install_message' # must come before rdoc for messaging
-require 'rubygems/rdoc'
+require_relative '../command'
+require_relative '../command_manager'
+require_relative '../dependency_installer'
+require_relative '../install_update_options'
+require_relative '../local_remote_options'
+require_relative '../spec_fetcher'
+require_relative '../version_option'
+require_relative '../install_message' # must come before rdoc for messaging
+require_relative '../rdoc'
class Gem::Commands::UpdateCommand < Gem::Command
include Gem::InstallUpdateOptions
diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb
index d42ab18395..44e87a2b98 100644
--- a/lib/rubygems/commands/which_command.rb
+++ b/lib/rubygems/commands/which_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::WhichCommand < Gem::Command
def initialize
diff --git a/lib/rubygems/commands/yank_command.rb b/lib/rubygems/commands/yank_command.rb
index a7930253d6..cad78aec5f 100644
--- a/lib/rubygems/commands/yank_command.rb
+++ b/lib/rubygems/commands/yank_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
-require 'rubygems/gemcutter_utilities'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
+require_relative '../gemcutter_utilities'
class Gem::Commands::YankCommand < Gem::Command
include Gem::LocalRemoteOptions
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index 02bb2be122..60c1d50ba9 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
require 'rbconfig'
##
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index e95bc06792..39b69ddb1c 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -34,21 +34,7 @@ module Gem
# specified in the environment
def self.default_dir
- path = if defined? RUBY_FRAMEWORK_VERSION
- [
- File.dirname(RbConfig::CONFIG['sitedir']),
- 'Gems',
- RbConfig::CONFIG['ruby_version'],
- ]
- else
- [
- RbConfig::CONFIG['rubylibprefix'],
- 'gems',
- RbConfig::CONFIG['ruby_version'],
- ]
- end
-
- @default_dir ||= File.join(*path)
+ @default_dir ||= File.join(RbConfig::CONFIG['rubylibprefix'], 'gems', RbConfig::CONFIG['ruby_version'])
end
##
@@ -73,7 +59,7 @@ module Gem
# Path to specification files of default gems.
def self.default_specifications_dir
- File.join(Gem.default_dir, "specifications", "default")
+ @default_specifications_dir ||= File.join(Gem.default_dir, "specifications", "default")
end
##
@@ -197,11 +183,7 @@ module Gem
# The default directory for binaries
def self.default_bindir
- if defined? RUBY_FRAMEWORK_VERSION # mac framework support
- '/usr/local/bin'
- else # generic install
- RbConfig::CONFIG['bindir']
- end
+ RbConfig::CONFIG['bindir']
end
def self.ruby_engine
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index 400a5de5cf..913bba32eb 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/dependency_list'
-require 'rubygems/package'
-require 'rubygems/installer'
-require 'rubygems/spec_fetcher'
-require 'rubygems/user_interaction'
-require 'rubygems/available_set'
-require 'rubygems/deprecate'
+require_relative '../rubygems'
+require_relative 'dependency_list'
+require_relative 'package'
+require_relative 'installer'
+require_relative 'spec_fetcher'
+require_relative 'user_interaction'
+require_relative 'available_set'
+require_relative 'deprecate'
##
# Installs a gem along with all its dependencies from local and remote gems.
diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb
index bcf436cd03..8f61869874 100644
--- a/lib/rubygems/dependency_list.rb
+++ b/lib/rubygems/dependency_list.rb
@@ -6,7 +6,7 @@
#++
require 'tsort'
-require 'rubygems/deprecate'
+require_relative 'deprecate'
##
# Gem::DependencyList is used for installing and uninstalling gems in the
diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb
index ef31aeddd0..41bcda9804 100644
--- a/lib/rubygems/doctor.rb
+++ b/lib/rubygems/doctor.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# Cleans up after a partially-failed uninstall or for an invalid
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index abee20651e..86f0d1da14 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -171,8 +171,7 @@ module Gem
# An English description of the error.
def wordy
- @source.uri.password = 'REDACTED' unless @source.uri.password.nil?
- "Unable to download data from #{@source.uri} - #{@error.message}"
+ "Unable to download data from #{Gem::Uri.new(@source.uri).redacted} - #{@error.message}"
end
##
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 185efdb6ab..f0debb646f 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/deprecate'
-require 'rubygems/unknown_command_spell_checker'
+require_relative 'deprecate'
+require_relative 'unknown_command_spell_checker'
##
# Base exception class for RubyGems. All exception raised by RubyGems are a
diff --git a/lib/rubygems/gem_runner.rb b/lib/rubygems/gem_runner.rb
index a36674503e..55b5a7d067 100644
--- a/lib/rubygems/gem_runner.rb
+++ b/lib/rubygems/gem_runner.rb
@@ -5,9 +5,9 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/command_manager'
-require 'rubygems/deprecate'
+require_relative '../rubygems'
+require_relative 'command_manager'
+require_relative 'deprecate'
##
# Load additional plugins from $LOAD_PATH
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index f465881041..0968e1a6f9 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/remote_fetcher'
-require 'rubygems/text'
+require_relative 'remote_fetcher'
+require_relative 'text'
##
# Utility methods for using the RubyGems API.
diff --git a/lib/rubygems/indexer.rb b/lib/rubygems/indexer.rb
index e595459c87..6e8dade640 100644
--- a/lib/rubygems/indexer.rb
+++ b/lib/rubygems/indexer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/package'
+require_relative '../rubygems'
+require_relative 'package'
require 'tmpdir'
##
diff --git a/lib/rubygems/install_default_message.rb b/lib/rubygems/install_default_message.rb
index f68fd2fd04..052ef528e1 100644
--- a/lib/rubygems/install_default_message.rb
+++ b/lib/rubygems/install_default_message.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# A post-install hook that displays "Successfully installed
diff --git a/lib/rubygems/install_message.rb b/lib/rubygems/install_message.rb
index 3c13888a84..861ead3770 100644
--- a/lib/rubygems/install_message.rb
+++ b/lib/rubygems/install_message.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# A default post-install hook that displays "Successfully installed
diff --git a/lib/rubygems/install_update_options.rb b/lib/rubygems/install_update_options.rb
index 54a3950b64..cafa63544f 100644
--- a/lib/rubygems/install_update_options.rb
+++ b/lib/rubygems/install_update_options.rb
@@ -5,8 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/security_option'
+require_relative '../rubygems'
+require_relative 'security_option'
##
# Mixin methods for install and update options for Gem::Commands
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 7cc9bc6a0b..cf5ed7b502 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -5,13 +5,13 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/command'
-require 'rubygems/installer_uninstaller_utils'
-require 'rubygems/exceptions'
-require 'rubygems/deprecate'
-require 'rubygems/package'
-require 'rubygems/ext'
-require 'rubygems/user_interaction'
+require_relative 'command'
+require_relative 'installer_uninstaller_utils'
+require_relative 'exceptions'
+require_relative 'deprecate'
+require_relative 'package'
+require_relative 'ext'
+require_relative 'user_interaction'
##
# The installer installs the files contained in the .gem into the Gem.home.
@@ -761,7 +761,7 @@ class Gem::Installer
#
require 'rubygems'
-
+#{gemdeps_load(spec.name)}
version = "#{Gem::Requirement.default_prerelease}"
str = ARGV.first
@@ -782,6 +782,15 @@ end
TEXT
end
+ def gemdeps_load(name)
+ return '' if name == "bundler"
+
+ <<-TEXT
+
+Gem.use_gemdeps
+TEXT
+ end
+
##
# return the stub script text used to launch the true Ruby script
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index 2d0509eb03..8acd98d2e4 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -6,7 +6,7 @@
#++
require 'uri'
-require 'rubygems'
+require_relative '../rubygems'
##
# Mixin methods for local and remote Gem::Command options.
diff --git a/lib/rubygems/mock_gem_ui.rb b/lib/rubygems/mock_gem_ui.rb
index ec244fb7c6..914ecb9a71 100644
--- a/lib/rubygems/mock_gem_ui.rb
+++ b/lib/rubygems/mock_gem_ui.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
##
# This Gem::StreamUI subclass records input and output to StringIO for
diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb
index 3d0afa3094..c732d7f968 100644
--- a/lib/rubygems/name_tuple.rb
+++ b/lib/rubygems/name_tuple.rb
@@ -89,9 +89,8 @@ class Gem::NameTuple
alias to_s inspect # :nodoc:
def <=>(other)
- [@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1] <=>
- [other.name, other.version,
- other.platform == Gem::Platform::RUBY ? -1 : 1]
+ [@name, @version, Gem::Platform.sort_priority(@platform)] <=>
+ [other.name, other.version, Gem::Platform.sort_priority(other.platform)]
end
include Comparable
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index a4ae3e9ea5..94705914af 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -41,9 +41,9 @@
# #files are the files in the .gem tar file, not the Ruby files in the gem
# #extract_files and #contents automatically call #verify
-require "rubygems"
-require 'rubygems/security'
-require 'rubygems/user_interaction'
+require_relative "../rubygems"
+require_relative 'security'
+require_relative 'user_interaction'
class Gem::Package
include Gem::UserInteraction
@@ -71,6 +71,13 @@ class Gem::Package
end
end
+ class SymlinkError < Error
+ def initialize(name, destination, destination_dir)
+ super "installing symlink '%s' pointing to parent path %s of %s is not allowed" %
+ [name, destination, destination_dir]
+ end
+ end
+
class NonSeekableIO < Error; end
class TooLongFileName < Error; end
@@ -400,13 +407,21 @@ EOM
# extracted.
def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
- directories = [] if dir_mode
+ directories = []
open_tar_gz io do |tar|
tar.each do |entry|
next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH
destination = install_location entry.full_name, destination_dir
+ if entry.symlink?
+ link_target = entry.header.linkname
+ real_destination = link_target.start_with?("/") ? link_target : File.expand_path(link_target, File.dirname(destination))
+
+ raise Gem::Package::SymlinkError.new(entry.full_name, real_destination, destination_dir) unless
+ normalize_path(real_destination).start_with? normalize_path(destination_dir + '/')
+ end
+
FileUtils.rm_rf destination
mkdir_options = {}
@@ -417,9 +432,11 @@ EOM
else
File.dirname destination
end
- directories << mkdir if directories
- mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
+ unless directories.include?(mkdir)
+ FileUtils.mkdir_p mkdir, **mkdir_options
+ directories << mkdir
+ end
File.open destination, 'wb' do |out|
out.write entry.read
@@ -432,8 +449,7 @@ EOM
end
end
- if directories
- directories.uniq!
+ if dir_mode
File.chmod(dir_mode, *directories)
end
end
@@ -466,21 +482,11 @@ EOM
raise Gem::Package::PathError.new(filename, destination_dir) if
filename.start_with? '/'
- destination_dir = File.expand_path(File.realpath(destination_dir))
- destination = File.expand_path(File.join(destination_dir, filename))
+ destination_dir = File.realpath(destination_dir)
+ destination = File.expand_path(filename, destination_dir)
raise Gem::Package::PathError.new(destination, destination_dir) unless
- destination.start_with? destination_dir + '/'
-
- begin
- real_destination = File.expand_path(File.realpath(destination))
- rescue
- # it's fine if the destination doesn't exist, because rm -rf'ing it can't cause any damage
- nil
- else
- raise Gem::Package::PathError.new(real_destination, destination_dir) unless
- real_destination.start_with? destination_dir + '/'
- end
+ normalize_path(destination).start_with? normalize_path(destination_dir + '/')
destination.tap(&Gem::UNTAINT)
destination
@@ -494,22 +500,6 @@ EOM
end
end
- def mkdir_p_safe(mkdir, mkdir_options, destination_dir, file_name)
- destination_dir = File.realpath(File.expand_path(destination_dir))
- parts = mkdir.split(File::SEPARATOR)
- parts.reduce do |path, basename|
- path = File.realpath(path) unless path == ""
- path = File.expand_path(path + File::SEPARATOR + basename)
- lstat = File.lstat path rescue nil
- if !lstat || !lstat.directory?
- unless normalize_path(path).start_with? normalize_path(destination_dir) and (FileUtils.mkdir path, **mkdir_options rescue false)
- raise Gem::Package::PathError.new(file_name, destination_dir)
- end
- end
- path
- end
- end
-
##
# Loads a Gem::Specification from the TarEntry +entry+
@@ -702,12 +692,12 @@ EOM
end
end
-require 'rubygems/package/digest_io'
-require 'rubygems/package/source'
-require 'rubygems/package/file_source'
-require 'rubygems/package/io_source'
-require 'rubygems/package/old'
-require 'rubygems/package/tar_header'
-require 'rubygems/package/tar_reader'
-require 'rubygems/package/tar_reader/entry'
-require 'rubygems/package/tar_writer'
+require_relative 'package/digest_io'
+require_relative 'package/source'
+require_relative 'package/file_source'
+require_relative 'package/io_source'
+require_relative 'package/old'
+require_relative 'package/tar_header'
+require_relative 'package/tar_reader'
+require_relative 'package/tar_reader/entry'
+require_relative 'package/tar_writer'
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index e7c5620533..41121f3bfb 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -121,4 +121,4 @@ class Gem::Package::TarReader
end
end
-require 'rubygems/package/tar_reader/entry'
+require_relative 'tar_reader/entry'
diff --git a/lib/rubygems/package_task.rb b/lib/rubygems/package_task.rb
index d5a2885a64..bb48616b0e 100644
--- a/lib/rubygems/package_task.rb
+++ b/lib/rubygems/package_task.rb
@@ -20,8 +20,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-require 'rubygems'
-require 'rubygems/package'
+require_relative '../rubygems'
+require_relative 'package'
require 'rake/packagetask'
##
diff --git a/lib/rubygems/path_support.rb b/lib/rubygems/path_support.rb
index 8103caf324..d601e653c9 100644
--- a/lib/rubygems/path_support.rb
+++ b/lib/rubygems/path_support.rb
@@ -72,12 +72,7 @@ class Gem::PathSupport
# Return the default Gem path
def default_path
- gem_path = Gem.default_path + [@home]
-
- if defined?(APPLE_GEM_HOME)
- gem_path << APPLE_GEM_HOME
- end
- gem_path
+ Gem.default_path + [@home]
end
def expand(path)
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index fd1c0a62ac..a5e65f9243 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require "rubygems/deprecate"
+require_relative "deprecate"
##
# Available list of platforms for targeting Gem installations.
@@ -40,6 +40,10 @@ class Gem::Platform
match_platforms?(platform, Gem.platforms)
end
+ def self.sort_priority(platform)
+ platform == Gem::Platform::RUBY ? -1 : 1
+ end
+
def self.installable?(spec)
if spec.respond_to? :installable_platform?
spec.installable_platform?
@@ -100,6 +104,7 @@ class Gem::Platform
when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ]
when /linux-?((?!gnu)\w+)?/ then [ 'linux', $1 ]
when /mingw32/ then [ 'mingw32', nil ]
+ when /mingw-?(\w+)?/ then [ 'mingw', $1 ]
when /(mswin\d+)(\_(\d+))?/ then
os, version = $1, $3
@cpu = 'x86' if @cpu.nil? and os =~ /32$/
diff --git a/lib/rubygems/query_utils.rb b/lib/rubygems/query_utils.rb
index ea0f260ab4..0acd5bf9c8 100644
--- a/lib/rubygems/query_utils.rb
+++ b/lib/rubygems/query_utils.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
-require 'rubygems/text'
+require_relative 'local_remote_options'
+require_relative 'spec_fetcher'
+require_relative 'version_option'
+require_relative 'text'
module Gem::QueryUtils
diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb
index c40bb7d9f1..ac5e8f0822 100644
--- a/lib/rubygems/rdoc.rb
+++ b/lib/rubygems/rdoc.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems'
+require_relative '../rubygems'
begin
require 'rdoc/rubygems_hook'
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 45dca1195e..bd8165e3c7 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/request'
-require 'rubygems/request/connection_pools'
-require 'rubygems/s3_uri_signer'
-require 'rubygems/uri_formatter'
-require 'rubygems/uri_parser'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'request'
+require_relative 'request/connection_pools'
+require_relative 's3_uri_signer'
+require_relative 'uri_formatter'
+require_relative 'uri'
+require_relative 'user_interaction'
##
# RemoteFetcher handles the details of fetching gems and gem information from
@@ -25,15 +25,12 @@ class Gem::RemoteFetcher
attr_accessor :uri, :original_uri
def initialize(message, uri)
- super message
+ uri = Gem::Uri.new(uri)
- uri = Gem::UriParser.parse_uri(uri)
+ super uri.redact_credentials_from(message)
- @original_uri = uri.dup
-
- uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password
-
- @uri = uri.to_s
+ @original_uri = uri.to_s
+ @uri = uri.redacted.to_s
end
def to_s # :nodoc:
@@ -75,7 +72,7 @@ class Gem::RemoteFetcher
# fetching the gem.
def initialize(proxy=nil, dns=nil, headers={})
- require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
+ require_relative 'core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
require 'net/http'
require 'stringio'
require 'uri'
@@ -129,7 +126,7 @@ class Gem::RemoteFetcher
require "fileutils"
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
- source_uri = Gem::UriParser.parse_uri(source_uri)
+ source_uri = Gem::Uri.new(source_uri)
scheme = source_uri.scheme
@@ -224,7 +221,7 @@ class Gem::RemoteFetcher
unless location = response['Location']
raise FetchError.new("redirecting but no redirect location was given", uri)
end
- location = Gem::UriParser.parse_uri location
+ location = Gem::Uri.new location
if https?(uri) && !https?(location)
raise FetchError.new("redirecting to non-https resource: #{location}", uri)
@@ -242,7 +239,7 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- uri = Gem::UriParser.parse_uri uri
+ uri = Gem::Uri.new uri
unless uri.scheme
raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb
index 5bda0b2e5e..d6100c914b 100644
--- a/lib/rubygems/request.rb
+++ b/lib/rubygems/request.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'net/http'
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
class Gem::Request
extend Gem::UserInteraction
@@ -96,8 +96,10 @@ class Gem::Request
return unless cert
case error_number
when OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED then
+ require 'time'
"Certificate #{cert.subject} expired at #{cert.not_after.iso8601}"
when OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID then
+ require 'time'
"Certificate #{cert.subject} not valid until #{cert.not_before.iso8601}"
when OpenSSL::X509::V_ERR_CERT_REJECTED then
"Certificate #{cert.subject} is rejected"
@@ -191,7 +193,7 @@ class Gem::Request
begin
@requests[connection.object_id] += 1
- verbose "#{request.method} #{@uri}"
+ verbose "#{request.method} #{Gem::Uri.new(@uri).redacted}"
file_name = File.basename(@uri.path)
# perform download progress reporter only for gems
@@ -287,6 +289,6 @@ class Gem::Request
end
end
-require 'rubygems/request/http_pool'
-require 'rubygems/request/https_pool'
-require 'rubygems/request/connection_pools'
+require_relative 'request/http_pool'
+require_relative 'request/https_pool'
+require_relative 'request/connection_pools'
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index 36ec87e1f7..9286c54221 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -303,7 +303,7 @@ class Gem::RequestSet
end
end
- require "rubygems/dependency_installer"
+ require_relative "dependency_installer"
inst = Gem::DependencyInstaller.new options
inst.installed_gems.replace specs
@@ -461,6 +461,6 @@ class Gem::RequestSet
end
end
-require 'rubygems/request_set/gem_dependency_api'
-require 'rubygems/request_set/lockfile'
-require 'rubygems/request_set/lockfile/tokenizer'
+require_relative 'request_set/gem_dependency_api'
+require_relative 'request_set/lockfile'
+require_relative 'request_set/lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index 8f8f142fff..bec29ef1b9 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -236,4 +236,4 @@ class Gem::RequestSet::Lockfile
end
end
-require 'rubygems/request_set/lockfile/tokenizer'
+require_relative 'lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/lockfile/tokenizer.rb b/lib/rubygems/request_set/lockfile/tokenizer.rb
index 6918e8e1a5..cb8030c143 100644
--- a/lib/rubygems/request_set/lockfile/tokenizer.rb
+++ b/lib/rubygems/request_set/lockfile/tokenizer.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/request_set/lockfile/parser'
+require_relative 'parser'
class Gem::RequestSet::Lockfile::Tokenizer
Token = Struct.new :type, :value, :column, :line
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 16de45ad91..d2e28fab5b 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require "rubygems/deprecate"
+require_relative "deprecate"
##
# A Requirement is a set of one or more version restrictions. It supports a
diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb
index 71c35ea3d3..51a11fed47 100644
--- a/lib/rubygems/resolver.rb
+++ b/lib/rubygems/resolver.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/dependency'
-require 'rubygems/exceptions'
-require 'rubygems/util/list'
+require_relative 'dependency'
+require_relative 'exceptions'
+require_relative 'util/list'
##
# Given a set of Gem::Dependency objects as +needed+ and a way to query the
@@ -10,7 +10,7 @@ require 'rubygems/util/list'
# all the requirements.
class Gem::Resolver
- require 'rubygems/resolver/molinillo'
+ require_relative 'resolver/molinillo'
##
# If the DEBUG_RESOLVER environment variable is set then debugging mode is
@@ -318,30 +318,30 @@ class Gem::Resolver
private :amount_constrained
end
-require 'rubygems/resolver/activation_request'
-require 'rubygems/resolver/conflict'
-require 'rubygems/resolver/dependency_request'
-require 'rubygems/resolver/requirement_list'
-require 'rubygems/resolver/stats'
-
-require 'rubygems/resolver/set'
-require 'rubygems/resolver/api_set'
-require 'rubygems/resolver/composed_set'
-require 'rubygems/resolver/best_set'
-require 'rubygems/resolver/current_set'
-require 'rubygems/resolver/git_set'
-require 'rubygems/resolver/index_set'
-require 'rubygems/resolver/installer_set'
-require 'rubygems/resolver/lock_set'
-require 'rubygems/resolver/vendor_set'
-require 'rubygems/resolver/source_set'
-
-require 'rubygems/resolver/specification'
-require 'rubygems/resolver/spec_specification'
-require 'rubygems/resolver/api_specification'
-require 'rubygems/resolver/git_specification'
-require 'rubygems/resolver/index_specification'
-require 'rubygems/resolver/installed_specification'
-require 'rubygems/resolver/local_specification'
-require 'rubygems/resolver/lock_specification'
-require 'rubygems/resolver/vendor_specification'
+require_relative 'resolver/activation_request'
+require_relative 'resolver/conflict'
+require_relative 'resolver/dependency_request'
+require_relative 'resolver/requirement_list'
+require_relative 'resolver/stats'
+
+require_relative 'resolver/set'
+require_relative 'resolver/api_set'
+require_relative 'resolver/composed_set'
+require_relative 'resolver/best_set'
+require_relative 'resolver/current_set'
+require_relative 'resolver/git_set'
+require_relative 'resolver/index_set'
+require_relative 'resolver/installer_set'
+require_relative 'resolver/lock_set'
+require_relative 'resolver/vendor_set'
+require_relative 'resolver/source_set'
+
+require_relative 'resolver/specification'
+require_relative 'resolver/spec_specification'
+require_relative 'resolver/api_specification'
+require_relative 'resolver/git_specification'
+require_relative 'resolver/index_specification'
+require_relative 'resolver/installed_specification'
+require_relative 'resolver/local_specification'
+require_relative 'resolver/lock_specification'
+require_relative 'resolver/vendor_specification'
diff --git a/lib/rubygems/resolver/git_specification.rb b/lib/rubygems/resolver/git_specification.rb
index 555dcffc22..ee47080ab4 100644
--- a/lib/rubygems/resolver/git_specification.rb
+++ b/lib/rubygems/resolver/git_specification.rb
@@ -21,7 +21,7 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
# the executables.
def install(options = {})
- require 'rubygems/installer'
+ require_relative '../installer'
installer = Gem::Installer.for_spec spec, options
diff --git a/lib/rubygems/resolver/installer_set.rb b/lib/rubygems/resolver/installer_set.rb
index 60181315b0..237bc3f782 100644
--- a/lib/rubygems/resolver/installer_set.rb
+++ b/lib/rubygems/resolver/installer_set.rb
@@ -71,17 +71,17 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
found = found.sort_by do |s|
- [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
+ [s.version, Gem::Platform.sort_priority(s.platform)]
end
newest = found.last
unless @force
- found_matching_metadata = found.select do |spec|
+ found_matching_metadata = found.reverse.find do |spec|
metadata_satisfied?(spec)
end
- if found_matching_metadata.empty?
+ if found_matching_metadata.nil?
if newest
ensure_required_ruby_version_met(newest.spec)
ensure_required_rubygems_version_met(newest.spec)
@@ -92,7 +92,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
raise exc
end
else
- newest = found_matching_metadata.last
+ newest = found_matching_metadata
end
end
diff --git a/lib/rubygems/resolver/molinillo.rb b/lib/rubygems/resolver/molinillo.rb
index 2357f41bee..12ca740e5a 100644
--- a/lib/rubygems/resolver/molinillo.rb
+++ b/lib/rubygems/resolver/molinillo.rb
@@ -1,2 +1,2 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo'
+require_relative 'molinillo/lib/molinillo'
diff --git a/lib/rubygems/resolver/set.rb b/lib/rubygems/resolver/set.rb
index 8046e18ea1..5d8dd51eaa 100644
--- a/lib/rubygems/resolver/set.rb
+++ b/lib/rubygems/resolver/set.rb
@@ -20,7 +20,6 @@ class Gem::Resolver::Set
attr_accessor :prerelease
def initialize # :nodoc:
- require 'uri'
@prerelease = false
@remote = true
@errors = []
diff --git a/lib/rubygems/resolver/specification.rb b/lib/rubygems/resolver/specification.rb
index 8c6fc9afcf..dfcb7eb057 100644
--- a/lib/rubygems/resolver/specification.rb
+++ b/lib/rubygems/resolver/specification.rb
@@ -93,7 +93,7 @@ class Gem::Resolver::Specification
# specification.
def install(options = {})
- require 'rubygems/installer'
+ require_relative '../installer'
gem = download options
diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb
index bba9afc9ff..da2af5f326 100644
--- a/lib/rubygems/s3_uri_signer.rb
+++ b/lib/rubygems/s3_uri_signer.rb
@@ -1,5 +1,5 @@
require 'digest'
-require 'rubygems/openssl'
+require_relative 'openssl'
##
# S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems
@@ -140,8 +140,8 @@ class Gem::S3URISigner
def ec2_metadata_credentials_json
require 'net/http'
- require 'rubygems/request'
- require 'rubygems/request/connection_pools'
+ require_relative 'request'
+ require_relative 'request/connection_pools'
require 'json'
iam_info = ec2_metadata_request(EC2_IAM_INFO)
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
index c80639af6d..28f705549c 100644
--- a/lib/rubygems/security.rb
+++ b/lib/rubygems/security.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/exceptions'
+require_relative 'exceptions'
require_relative 'openssl'
##
@@ -592,9 +592,9 @@ module Gem::Security
end
if Gem::HAVE_OPENSSL
- require 'rubygems/security/policy'
- require 'rubygems/security/policies'
- require 'rubygems/security/trust_dir'
+ require_relative 'security/policy'
+ require_relative 'security/policies'
+ require_relative 'security/trust_dir'
end
-require 'rubygems/security/signer'
+require_relative 'security/signer'
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
index 7629d64796..9683e55b32 100644
--- a/lib/rubygems/security/policy.rb
+++ b/lib/rubygems/security/policy.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+require_relative '../user_interaction'
##
# A Gem::Security::Policy object encapsulates the settings for verifying
diff --git a/lib/rubygems/security/signer.rb b/lib/rubygems/security/signer.rb
index 6c85ab08d2..c5c2c4f220 100644
--- a/lib/rubygems/security/signer.rb
+++ b/lib/rubygems/security/signer.rb
@@ -2,7 +2,7 @@
##
# Basic OpenSSL-based package signing class.
-require "rubygems/user_interaction"
+require_relative "../user_interaction"
class Gem::Security::Signer
include Gem::UserInteraction
diff --git a/lib/rubygems/security_option.rb b/lib/rubygems/security_option.rb
index 3403aaaf05..6c75d6ecb4 100644
--- a/lib/rubygems/security_option.rb
+++ b/lib/rubygems/security_option.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative '../rubygems'
# forward-declare
@@ -20,7 +20,7 @@ end
module Gem::SecurityOption
def add_security_option
OptionParser.accept Gem::Security::Policy do |value|
- require 'rubygems/security'
+ require_relative 'security'
raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless
defined?(Gem::Security::HighSecurity)
diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb
index 2c2805f31c..45be05bcda 100644
--- a/lib/rubygems/server.rb
+++ b/lib/rubygems/server.rb
@@ -3,8 +3,8 @@ require 'zlib'
require 'erb'
require 'uri'
-require 'rubygems'
-require 'rubygems/rdoc'
+require_relative '../rubygems'
+require_relative 'rdoc'
##
# Gem::Server and allows users to serve gems for consumption by
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index 37e03cdfae..f03e09872c 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require "rubygems/text"
+require_relative "text"
##
# A Source knows how to list and fetch gems from a RubyGems marshal index.
#
@@ -240,9 +240,9 @@ class Gem::Source
end
end
-require 'rubygems/source/git'
-require 'rubygems/source/installed'
-require 'rubygems/source/specific_file'
-require 'rubygems/source/local'
-require 'rubygems/source/lock'
-require 'rubygems/source/vendor'
+require_relative 'source/git'
+require_relative 'source/installed'
+require_relative 'source/specific_file'
+require_relative 'source/local'
+require_relative 'source/lock'
+require_relative 'source/vendor'
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index b2bcadc49c..68ff605a83 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/remote_fetcher'
-require 'rubygems/user_interaction'
-require 'rubygems/errors'
-require 'rubygems/text'
-require 'rubygems/name_tuple'
+require_relative 'remote_fetcher'
+require_relative 'user_interaction'
+require_relative 'errors'
+require_relative 'text'
+require_relative 'name_tuple'
##
# SpecFetcher handles metadata updates from remote gem repositories.
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index ff345bf7a3..bafc5e2619 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -6,11 +6,11 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/deprecate'
-require 'rubygems/basic_specification'
-require 'rubygems/stub_specification'
-require 'rubygems/specification_policy'
-require 'rubygems/util/list'
+require_relative 'deprecate'
+require_relative 'basic_specification'
+require_relative 'stub_specification'
+require_relative 'specification_policy'
+require_relative 'util/list'
##
# The Specification class contains the information for a gem. Typically
@@ -855,7 +855,7 @@ class Gem::Specification < Gem::BasicSpecification
next names if names.nonzero?
versions = b.version <=> a.version
next versions if versions.nonzero?
- b.platform == Gem::Platform::RUBY ? -1 : 1
+ Gem::Platform.sort_priority(b.platform)
end
end
@@ -1556,8 +1556,8 @@ class Gem::Specification < Gem::BasicSpecification
# the gem.build_complete file is missing.
def build_extensions # :nodoc:
- return if default_gem?
return if extensions.empty?
+ return if default_gem?
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, 'extensions'))
@@ -1568,9 +1568,9 @@ class Gem::Specification < Gem::BasicSpecification
unresolved_deps = Gem::Specification.unresolved_deps.dup
Gem::Specification.unresolved_deps.clear
- require 'rubygems/config_file'
- require 'rubygems/ext'
- require 'rubygems/user_interaction'
+ require_relative 'config_file'
+ require_relative 'ext'
+ require_relative 'user_interaction'
ui = Gem::SilentUI.new
Gem::DefaultUserInteraction.use_ui ui do
@@ -2120,8 +2120,8 @@ class Gem::Specification < Gem::BasicSpecification
# probably want to build_extensions
def missing_extensions?
- return false if default_gem?
return false if extensions.empty?
+ return false if default_gem?
return false if File.exist? gem_build_complete_path
true
@@ -2333,7 +2333,7 @@ class Gem::Specification < Gem::BasicSpecification
# Returns an object you can use to sort specifications in #sort_by.
def sort_obj
- [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
+ [@name, @version, Gem::Platform.sort_priority(@new_platform)]
end
##
@@ -2525,7 +2525,7 @@ class Gem::Specification < Gem::BasicSpecification
# back, we have to check again here to make sure that our
# psych code was properly loaded, and load it if not.
unless Gem.const_defined?(:NoAliasYAMLTree)
- require 'rubygems/psych_tree'
+ require_relative 'psych_tree'
end
builder = Gem::NoAliasYAMLTree.create
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb
index 86277a2058..73bd31970c 100644
--- a/lib/rubygems/specification_policy.rb
+++ b/lib/rubygems/specification_policy.rb
@@ -1,4 +1,4 @@
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
class Gem::SpecificationPolicy
include Gem::UserInteraction
@@ -381,7 +381,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
end
LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
- LAZY_PATTERN = /FI XME|TO DO/x.freeze
+ LAZY_PATTERN = /\AFI XME|\ATO DO/x.freeze
HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze
def validate_lazy_metadata
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 87a5ef770f..11fb611329 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -6,11 +6,11 @@
#++
require 'fileutils'
-require 'rubygems'
-require 'rubygems/installer_uninstaller_utils'
-require 'rubygems/dependency_list'
-require 'rubygems/rdoc'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'installer_uninstaller_utils'
+require_relative 'dependency_list'
+require_relative 'rdoc'
+require_relative 'user_interaction'
##
# An Uninstaller.
@@ -360,7 +360,7 @@ class Gem::Uninstaller
# of what it did for us to find rather than trying to recreate
# it again.
if @format_executable
- require 'rubygems/installer'
+ require_relative 'installer'
Gem::Installer.exec_format % File.basename(filename)
else
filename
diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb
new file mode 100644
index 0000000000..ba30fac2f5
--- /dev/null
+++ b/lib/rubygems/uri.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+##
+# The Uri handles rubygems source URIs.
+#
+
+class Gem::Uri
+ def initialize(source_uri)
+ @parsed_uri = parse(source_uri)
+ end
+
+ def redacted
+ return self unless valid_uri?
+
+ if token? || oauth_basic?
+ with_redacted_user
+ elsif password?
+ with_redacted_password
+ else
+ self
+ end
+ end
+
+ def to_s
+ @parsed_uri.to_s
+ end
+
+ def redact_credentials_from(text)
+ return text unless valid_uri? && password?
+
+ text.sub(password, 'REDACTED')
+ end
+
+ def method_missing(method_name, *args, &blk)
+ if @parsed_uri.respond_to?(method_name)
+ @parsed_uri.send(method_name, *args, &blk)
+ else
+ super
+ end
+ end
+
+ def respond_to_missing?(method_name, include_private = false)
+ @parsed_uri.respond_to?(method_name, include_private) || super
+ end
+
+ protected
+
+ # Add a protected reader for the cloned instance to access the original object's parsed uri
+ attr_reader :parsed_uri
+
+ private
+
+ ##
+ # Parses the #uri, raising if it's invalid
+
+ def parse!(uri)
+ require "uri"
+
+ raise URI::InvalidURIError unless uri
+
+ # Always escape URI's to deal with potential spaces and such
+ # It should also be considered that source_uri may already be
+ # a valid URI with escaped characters. e.g. "{DESede}" is encoded
+ # 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))
+ end
+ end
+
+ ##
+ # Parses the #uri, returning the original uri if it's invalid
+
+ def parse(uri)
+ return uri unless uri.is_a?(String)
+
+ parse!(uri)
+ rescue URI::InvalidURIError
+ uri
+ end
+
+ def with_redacted_user
+ clone.tap {|uri| uri.user = 'REDACTED' }
+ end
+
+ def with_redacted_password
+ clone.tap {|uri| uri.password = 'REDACTED' }
+ end
+
+ def valid_uri?
+ !@parsed_uri.is_a?(String)
+ end
+
+ def password?
+ !!password
+ end
+
+ def oauth_basic?
+ password == 'x-oauth-basic'
+ end
+
+ def token?
+ !user.nil? && password.nil?
+ end
+
+ def initialize_copy(original)
+ @parsed_uri = original.parsed_uri.clone
+ end
+end
diff --git a/lib/rubygems/uri_parser.rb b/lib/rubygems/uri_parser.rb
deleted file mode 100644
index f51d77a4af..0000000000
--- a/lib/rubygems/uri_parser.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-##
-# The UriParser handles parsing URIs.
-#
-
-class Gem::UriParser
- def self.parse_uri(source_uri)
- return source_uri unless source_uri.is_a?(String)
-
- new.parse(source_uri)
- end
-
- ##
- # Parses the #uri, raising if it's invalid
-
- def parse!(uri)
- require "uri"
-
- raise URI::InvalidURIError unless uri
-
- # Always escape URI's to deal with potential spaces and such
- # It should also be considered that source_uri may already be
- # a valid URI with escaped characters. e.g. "{DESede}" is encoded
- # 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))
- end
- end
-
- ##
- # Parses the #uri, returning the original uri if it's invalid
-
- def parse(uri)
- parse!(uri)
- rescue URI::InvalidURIError
- uri
- end
-end
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 6376ea7cf8..0ab44fbf6c 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -5,8 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/deprecate'
-require 'rubygems/text'
+require_relative 'deprecate'
+require_relative 'text'
##
# Module that defines the default UserInteraction. Any class including this
diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb
index 2a55305172..4363c5adce 100644
--- a/lib/rubygems/util.rb
+++ b/lib/rubygems/util.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/deprecate'
+require_relative 'deprecate'
##
# This module contains various utility methods as module methods.
diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb
index 98cbd8929b..8de5b11ae3 100644
--- a/lib/rubygems/util/licenses.rb
+++ b/lib/rubygems/util/licenses.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/text'
+require_relative '../text'
class Gem::Licenses
extend Gem::Text
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 30cdd93b5c..728595e778 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -5,8 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/package'
-require 'rubygems/installer'
+require_relative 'package'
+require_relative 'installer'
##
# Validator performs various gem file and gem database validation
diff --git a/lib/rubygems/version_option.rb b/lib/rubygems/version_option.rb
index be71ef409b..eabe4fdb57 100644
--- a/lib/rubygems/version_option.rb
+++ b/lib/rubygems/version_option.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative '../rubygems'
##
# Mixin methods for --version and --platform Gem::Command options.
diff --git a/lib/securerandom.rb b/lib/securerandom.rb
index 241fde98ce..323d4af3b7 100644
--- a/lib/securerandom.rb
+++ b/lib/securerandom.rb
@@ -31,7 +31,7 @@
# * uuid
#
# These methods are usable as class methods of SecureRandom such as
-# `SecureRandom.hex`.
+# +SecureRandom.hex+.
#
# === Examples
#
diff --git a/lib/set.rb b/lib/set.rb
index 50399309e3..7832c848cf 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -834,13 +834,14 @@ class Set
alias to_s inspect
def pretty_print(pp) # :nodoc:
- pp.text sprintf('#<%s: {', self.class.name)
- pp.nest(1) {
- pp.seplist(self) { |o|
- pp.pp o
+ pp.group(1, sprintf('#<%s:', self.class.name), '>') {
+ pp.breakable
+ pp.group(1, '{', '}') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
}
}
- pp.text "}>"
end
def pretty_print_cycle(pp) # :nodoc:
diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec
index 4917b997e7..c4f28b2ef7 100644
--- a/lib/tempfile.gemspec
+++ b/lib/tempfile.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "tempfile"
- spec.version = "0.1.1"
+ spec.version = "0.1.2"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index 1577e45bec..c1b696c4cf 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -36,9 +36,9 @@ require 'tmpdir'
#
# When a Tempfile object is garbage collected, or when the Ruby interpreter
# exits, its associated temporary file is automatically deleted. This means
-# that's it's unnecessary to explicitly delete a Tempfile after use, though
-# it's good practice to do so: not explicitly deleting unused Tempfiles can
-# potentially leave behind large amounts of tempfiles on the filesystem
+# that it's unnecessary to explicitly delete a Tempfile after use, though
+# it's a good practice to do so: not explicitly deleting unused Tempfiles can
+# potentially leave behind a large number of temp files on the filesystem
# until they're garbage collected. The existence of these temp files can make
# it harder to determine a new Tempfile filename.
#
diff --git a/lib/time.gemspec b/lib/time.gemspec
index 040b9f34cf..72fba34204 100644
--- a/lib/time.gemspec
+++ b/lib/time.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "time"
- spec.version = "0.1.0"
+ spec.version = "0.2.0"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/timeout.rb b/lib/timeout.rb
index e7b11c0a86..f50e706d4b 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -23,7 +23,7 @@
# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
module Timeout
- VERSION = "0.1.1"
+ VERSION = "0.2.0".freeze
# Raised by Timeout.timeout when the block times out.
class Error < RuntimeError
diff --git a/lib/un.gemspec b/lib/un.gemspec
index 1b89ffa2fb..de8e6ec312 100644
--- a/lib/un.gemspec
+++ b/lib/un.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "un"
- spec.version = "0.1.0"
+ spec.version = "0.2.0"
spec.authors = ["WATANABE Hirofumi"]
spec.email = ["eban@ruby-lang.org"]
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/un"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
@@ -18,6 +19,6 @@ Gem::Specification.new do |spec|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
end
spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.executables = []
spec.require_paths = ["lib"]
end
diff --git a/lib/un.rb b/lib/un.rb
index 3f59e3ff8b..5feac92120 100644
--- a/lib/un.rb
+++ b/lib/un.rb
@@ -23,6 +23,7 @@
# ruby -run -e wait_writable -- [OPTION] FILE
# ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
# ruby -run -e httpd -- [OPTION] [DocumentRoot]
+# ruby -run -e colorize -- [FILE]
# ruby -run -e help [COMMAND]
require "fileutils"
@@ -346,6 +347,21 @@ def httpd
end
options[:Port] ||= 8080 # HTTP Alternate
options[:DocumentRoot] = argv.shift || '.'
+ s = nil
+ options[:StartCallback] = proc {
+ logger = s.logger
+ logger.info("To access this server, open this URL in a browser:")
+ s.listeners.each do |listener|
+ if options[:SSLEnable]
+ addr = listener.addr
+ addr[3] = "127.0.0.1" if addr[3] == "0.0.0.0"
+ addr[3] = "::1" if addr[3] == "::"
+ logger.info(" https://#{Addrinfo.new(addr).inspect_sockaddr}")
+ else
+ logger.info(" http://#{listener.connect_address.inspect_sockaddr}")
+ end
+ end
+ }
s = WEBrick::HTTPServer.new(options)
shut = proc {s.shutdown}
siglist = %w"TERM QUIT"
@@ -359,6 +375,29 @@ def httpd
end
##
+# Colorize ruby code.
+#
+# ruby -run -e colorize -- [FILE]
+#
+
+def colorize
+ begin
+ require "irb/color"
+ rescue LoadError
+ raise "colorize requires irb 1.1.0 or later"
+ end
+ setup do |argv, |
+ if argv.empty?
+ puts IRB::Color.colorize_code STDIN.read
+ return
+ end
+ argv.each do |file|
+ puts IRB::Color.colorize_code File.read(file)
+ end
+ end
+end
+
+##
# Display help message.
#
# ruby -run -e help [COMMAND]
diff --git a/lib/yaml/yaml.gemspec b/lib/yaml/yaml.gemspec
index cf19b0e0da..e8f20b8c2e 100644
--- a/lib/yaml/yaml.gemspec
+++ b/lib/yaml/yaml.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "yaml"
- spec.version = "0.1.1"
+ spec.version = "0.2.0"
spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]