Handle symlink cycles when fuzzy file finding (file open)

This commit is contained in:
Pistos 2020-02-26 14:08:04 -05:00
parent 88afb72f21
commit e3c0bcdd18
5 changed files with 68 additions and 21 deletions

View file

@ -1,6 +1,10 @@
Diakonos Changelog
------------------
0.9.8
- Handle symlink cycles when fuzzy file finding (file open)
0.9.7
- Added ability to move lines up or down.
- Made compatible with Ruby 2.4.0.

View file

@ -34,13 +34,6 @@
#
# And so forth.
class FuzzyFileFinder
module Version
MAJOR = 1
MINOR = 0
TINY = 4
STRING = [MAJOR, MINOR, TINY].join(".")
end
# This is the exception that is raised if you try to scan a
# directory tree with too many entries. By default, a ceiling of
# 10,000 entries is enforced, but you can change that number via
@ -112,22 +105,29 @@ class FuzzyFileFinder
def initialize( params = {} )
@ceiling = params[:ceiling] || 10_000
@ignores = Array(params[:ignores])
if params[:directories]
directories = Array(params[:directories])
directories << "." if directories.empty?
else
directories = ['.']
end
@recursive = params[:recursive].nil? ? true : params[:recursive]
# expand any paths with ~
root_dirnames = directories.map { |d| File.expand_path(d) }.select { |d| File.directory?(d) }.uniq
root_dirnames = directories.map { |d|
File.realpath(d)
}.select { |d|
File.directory?(d)
}.uniq
@roots = root_dirnames.map { |d| Directory.new(d, true) }
@shared_prefix = determine_shared_prefix
@shared_prefix_re = Regexp.new("^#{Regexp.escape(shared_prefix)}" + (shared_prefix.empty? ? "" : "/"))
@files = []
@directories = {} # To detect link cycles
rescan!
end
@ -218,19 +218,24 @@ class FuzzyFileFinder
# Recursively scans +directory+ and all files and subdirectories
# beneath it, depth-first.
def follow_tree(directory)
Dir.entries(directory.name).each do |entry|
next if entry[0,1] == "."
raise TooManyEntries if files.length > ceiling
real_dir = File.realpath(directory.name)
if ! @directories[real_dir]
@directories[real_dir] = true
full = File.join(directory.name, entry)
next if ignore?(full)
Dir.entries(directory.name).each do |entry|
next if entry[0,1] == "."
raise TooManyEntries if files.length > ceiling
if File.directory?(full)
if @recursive
follow_tree(Directory.new(full))
full = File.join(directory.name, entry)
next if ignore?(full)
if File.directory?(full)
if @recursive
follow_tree(Directory.new(full))
end
else
files.push(FileSystemEntry.new(directory, entry))
end
else
files.push(FileSystemEntry.new(directory, entry))
end
end
end

View file

@ -1,6 +1,6 @@
module Diakonos
VERSION = '0.9.7'
LAST_MODIFIED = 'October 2, 2019'
VERSION = '0.9.8'
LAST_MODIFIED = 'February 26, 2020'
def self.parse_version( s )
if s
@ -11,7 +11,7 @@ module Diakonos
def self.check_ruby_version
ruby_version = parse_version( RUBY_VERSION )
if ruby_version < [ 2, 1 ]
$stderr.puts "This version of Diakonos (#{Diakonos::VERSION}) requires Ruby 2.1, 2.2, 2.3 or 2.4."
$stderr.puts "This version of Diakonos (#{Diakonos::VERSION}) requires Ruby 2.1 or higher."
if ruby_version >= [ 2, 0 ]
$stderr.puts "Version 0.9.5 is the last version of Diakonos which can run under Ruby 2.0."
elsif ruby_version >= [ 1, 9 ]

View file

@ -0,0 +1,37 @@
require 'spec_helper'
RSpec.describe FuzzyFileFinder do
let(:params) {
{
ceiling: ceiling,
directories: directories,
ignores: ignores,
recursive: recursive,
}
}
let(:finder) { described_class.new(params) }
let(:ceiling) { nil }
let(:directories) { ['spec/test-files'] }
let(:ignores) { [] }
let(:recursive) { nil }
describe "#find" do
let(:matches) {
finder.find(input).map { |match|
match[:path].gsub(/^#{__dir__}/, '')
}
}
context "basic input" do
let(:input) { 'lo' }
it "finds the matching files" do
expect(matches).to eq [
'/test-files/longer-sample-file.rb',
'/test-files/lorem-ipsum.txt',
]
end
end
end
end

1
spec/test-files/self Symbolic link
View file

@ -0,0 +1 @@
.