Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix irb_history saved to current directory #901

Merged
merged 4 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions doc/irb/indexes.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,6 @@ for each entry that is pre-defined, the initial value is given:
- `:RC`: Whether a {configuration file}[rdoc-ref:IRB@Configuration+File]
was found and interpreted;
initial value: `true` if a configuration file was found, `false` otherwise.
- `:RC_NAME_GENERATOR`: \Proc to generate paths of potential
{configuration files}[rdoc-ref:IRB@Configuration+File];
initial value: `=> #<Proc:0x000055f9bebfed80 /var/lib/gems/3.0.0/gems/irb-1.8.3/lib/irb/init.rb:401>`.
- `:SAVE_HISTORY`: Number of commands to save in
{input command history}[rdoc-ref:IRB@Input+Command+History];
initial value: `1000`.
Expand Down
2 changes: 1 addition & 1 deletion lib/irb/command/irb_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def execute
str += "IRB version: #{IRB.version}\n"
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
rc_files = IRB.rc_files.select { |rc| File.exist?(rc) }
rc_files = IRB.irbrc_files
str += ".irbrc paths: #{rc_files.join(", ")}\n" if rc_files.any?
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
Expand Down
9 changes: 6 additions & 3 deletions lib/irb/history.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def load_history
if history_file = IRB.conf[:HISTORY_FILE]
history_file = File.expand_path(history_file)
end
history_file = IRB.rc_files("_history").first unless history_file
if File.exist?(history_file)
history_file = IRB.rc_file("_history") unless history_file
if history_file && File.exist?(history_file)
File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
f.each { |l|
l = l.chomp
Expand All @@ -41,7 +41,10 @@ def save_history
if history_file = IRB.conf[:HISTORY_FILE]
history_file = File.expand_path(history_file)
end
history_file = IRB.rc_files("_history").first unless history_file
history_file = IRB.rc_file("_history") unless history_file

# When HOME and XDG_CONFIG_HOME are not available, history_file might be nil
return unless history_file

# Change the permission of a file that already exists[BUG #7694]
begin
Expand Down
104 changes: 60 additions & 44 deletions lib/irb/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -395,64 +395,36 @@ def IRB.parse_opts(argv: ::ARGV)
# Run the config file
def IRB.run_config
if @CONF[:RC]
rc_files.each do |rc|
# Because rc_file always returns `HOME/.irbrc` even if no rc file is present, we can't warn users about missing rc files.
# Otherwise, it'd be very noisy.
load rc if File.exist?(rc)
irbrc_files.each do |rc|
load rc
rescue StandardError, ScriptError => e
warn "Error loading RC file '#{rc}':\n#{e.full_message(highlight: false)}"
end
end
end

IRBRC_EXT = "rc"
def IRB.rc_file(ext = IRBRC_EXT)
warn "rc_file is deprecated, please use rc_files instead."
rc_files(ext).first
end

def IRB.rc_files(ext = IRBRC_EXT)
if !@CONF[:RC_NAME_GENERATOR]
@CONF[:RC_NAME_GENERATOR] ||= []
existing_rc_file_generators = []

rc_file_generators do |rcgen|
@CONF[:RC_NAME_GENERATOR] << rcgen
existing_rc_file_generators << rcgen if File.exist?(rcgen.call(ext))
end
def IRB.rc_file(ext)
prepare_irbrc_name_generators

if existing_rc_file_generators.any?
@CONF[:RC_NAME_GENERATOR] = existing_rc_file_generators
end
# When irbrc exist in default location
if (rcgen = @existing_rc_name_generators.first)
return rcgen.call(ext)
end

@CONF[:RC_NAME_GENERATOR].map do |rc|
rc_file = rc.call(ext)
fail IllegalRCNameGenerator unless rc_file.is_a?(String)
rc_file
# When irbrc does not exist in default location
rc_file_generators do |rcgen|
return rcgen.call(ext)
end

# When HOME and XDG_CONFIG_HOME are not available
nil
end

# enumerate possible rc-file base name generators
def IRB.rc_file_generators
if irbrc = ENV["IRBRC"]
yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
end
if xdg_config_home = ENV["XDG_CONFIG_HOME"]
irb_home = File.join(xdg_config_home, "irb")
if File.directory?(irb_home)
yield proc{|rc| irb_home + "/irb#{rc}"}
end
end
if home = ENV["HOME"]
yield proc{|rc| home+"/.irb#{rc}"}
yield proc{|rc| home+"/.config/irb/irb#{rc}"}
end
current_dir = Dir.pwd
yield proc{|rc| current_dir+"/.irb#{rc}"}
yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
yield proc{|rc| current_dir+"/_irb#{rc}"}
yield proc{|rc| current_dir+"/$irb#{rc}"}
def IRB.irbrc_files
prepare_irbrc_name_generators
@irbrc_files
end

# loading modules
Expand All @@ -468,6 +440,50 @@ def IRB.load_modules

class << IRB
private

def prepare_irbrc_name_generators
return if @existing_rc_name_generators

@existing_rc_name_generators = []
@irbrc_files = []
rc_file_generators do |rcgen|
irbrc = rcgen.call(IRBRC_EXT)
if File.exist?(irbrc)
@irbrc_files << irbrc
@existing_rc_name_generators << rcgen
end
end
generate_current_dir_irbrc_files.each do |irbrc|
@irbrc_files << irbrc if File.exist?(irbrc)
end
@irbrc_files.uniq!
end

# enumerate possible rc-file base name generators
def rc_file_generators
if irbrc = ENV["IRBRC"]
yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
end
if xdg_config_home = ENV["XDG_CONFIG_HOME"]
irb_home = File.join(xdg_config_home, "irb")
if File.directory?(irb_home)
yield proc{|rc| irb_home + "/irb#{rc}"}
end
end
if home = ENV["HOME"]
yield proc{|rc| home+"/.irb#{rc}"}
if xdg_config_home.nil? || xdg_config_home.empty?
yield proc{|rc| home+"/.config/irb/irb#{rc}"}
end
end
end

# possible irbrc files in current directory
def generate_current_dir_irbrc_files
current_dir = Dir.pwd
%w[.irbrc irbrc _irbrc $irbrc].map { |file| "#{current_dir}/#{file}" }
end

def set_encoding(extern, intern = nil, override: true)
verbose, $VERBOSE = $VERBOSE, nil
Encoding.default_external = extern unless extern.nil? || extern.empty?
Expand Down
5 changes: 0 additions & 5 deletions lib/irb/lc/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ def initialize(val)
super("Undefined prompt mode(#{val}).")
end
end
class IllegalRCGenerator < StandardError
def initialize
super("Define illegal RC_NAME_GENERATOR.")
end
end

# :startdoc:
end
5 changes: 0 additions & 5 deletions lib/irb/lc/ja/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ def initialize(val)
super("プロンプトモード(#{val})は定義されていません.")
end
end
class IllegalRCGenerator < StandardError
def initialize
super("RC_NAME_GENERATORが正しく定義されていません.")
end
end

# :startdoc:
end
Expand Down
1 change: 1 addition & 0 deletions test/irb/test_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def setup
@xdg_config_home_backup = ENV.delete("XDG_CONFIG_HOME")
save_encodings
IRB.instance_variable_get(:@CONF).clear
IRB.instance_variable_set(:@existing_rc_name_generators, nil)
@is_win = (RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/)
end

Expand Down
18 changes: 14 additions & 4 deletions test/irb/test_history.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ def setup
@backup_irbrc = ENV.delete("IRBRC")
@backup_default_external = Encoding.default_external
ENV["HOME"] = @tmpdir
IRB.conf[:RC_NAME_GENERATOR] = nil
IRB.instance_variable_set(:@existing_rc_name_generators, nil)
end

def teardown
IRB.conf[:RC_NAME_GENERATOR] = nil
IRB.instance_variable_set(:@existing_rc_name_generators, nil)
ENV["HOME"] = @backup_home
ENV["XDG_CONFIG_HOME"] = @backup_xdg_config_home
ENV["IRBRC"] = @backup_irbrc
Expand Down Expand Up @@ -144,7 +144,7 @@ def test_history_concurrent_use_not_present
io.class::HISTORY << 'line1'
io.class::HISTORY << 'line2'

history_file = IRB.rc_files("_history").first
history_file = IRB.rc_file("_history")
assert_not_send [File, :file?, history_file]
File.write(history_file, "line0\n")
io.save_history
Expand Down Expand Up @@ -183,6 +183,16 @@ def test_history_does_not_raise_when_history_file_directory_does_not_exist
IRB.conf[:HISTORY_FILE] = backup_history_file
end

def test_no_home_no_history_file_does_not_raise_history_save
ENV['HOME'] = nil
io = TestInputMethodWithRelineHistory.new
assert_nil(IRB.rc_file('_history'))
assert_nothing_raised do
io.load_history
io.save_history
end
end

private

def history_concurrent_use_for_input_method(input_method)
Expand Down Expand Up @@ -217,7 +227,7 @@ def history_concurrent_use_for_input_method(input_method)
def assert_history(expected_history, initial_irb_history, input, input_method = TestInputMethodWithRelineHistory, locale: IRB::Locale.new)
IRB.conf[:LC_MESSAGES] = locale
actual_history = nil
history_file = IRB.rc_files("_history").first
history_file = IRB.rc_file("_history")
ENV["HOME"] = @tmpdir
File.open(history_file, "w") do |f|
f.write(initial_irb_history)
Expand Down
Loading
Loading