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 Globber.constant_entry? matching patterns #13955

Merged
113 changes: 77 additions & 36 deletions spec/std/dir_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,15 @@ describe "Dir" do

describe "glob" do
it "tests glob with a single pattern" do
Dir["#{datapath}/dir/*.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*.txt"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
].sort
end

it "tests glob with multiple patterns" do
Dir["#{datapath}/dir/*.txt", "#{datapath}/dir/subdir/*.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*.txt", "#{Path[datapath].to_posix}/dir/subdir/*.txt"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
Expand All @@ -211,7 +211,7 @@ describe "Dir" do

it "tests glob with a single pattern with block" do
result = [] of String
Dir.glob("#{datapath}/dir/*.txt") do |filename|
Dir.glob("#{Path[datapath].to_posix}/dir/*.txt") do |filename|
result << filename
end
result.sort.should eq([
Expand All @@ -222,19 +222,19 @@ describe "Dir" do
end

it "tests a recursive glob" do
Dir["#{datapath}/dir/**/*.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/**/*.txt"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
datapath("dir", "subdir", "f1.txt"),
datapath("dir", "subdir", "subdir2", "f2.txt"),
].sort

Dir["#{datapath}/dir/**/subdir2/f2.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/**/subdir2/f2.txt"].sort.should eq [
datapath("dir", "subdir", "subdir2", "f2.txt"),
].sort

Dir["#{datapath}/dir/**/subdir2/*.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/**/subdir2/*.txt"].sort.should eq [
datapath("dir", "subdir", "subdir2", "f2.txt"),
].sort
end
Expand Down Expand Up @@ -274,15 +274,15 @@ describe "Dir" do
end

it "tests a recursive glob with '?'" do
Dir["#{datapath}/dir/f?.tx?"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/f?.tx?"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "f3.txx"),
].sort
end

it "tests a recursive glob with alternation" do
Dir["#{datapath}/{dir,dir/subdir}/*.txt"].sort.should eq [
Dir["#{Path[datapath].to_posix}/{dir,dir/subdir}/*.txt"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
Expand All @@ -291,7 +291,7 @@ describe "Dir" do
end

it "tests a glob with recursion inside alternation" do
Dir["#{datapath}/dir/{**/*.txt,**/*.txx}"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/{**/*.txt,**/*.txx}"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "f3.txx"),
Expand All @@ -302,15 +302,56 @@ describe "Dir" do
end

it "tests a recursive glob with nested alternations" do
Dir["#{datapath}/dir/{?1.*,{f,g}2.txt}"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/{?1.*,{f,g}2.txt}"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
].sort
end

it "tests with []" do
Dir["#{Path[datapath].to_posix}/dir/[a-z][0-9].txt"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "g2.txt"),
].sort
end

it "tests with {}" do
Dir["#{Path[datapath].to_posix}/dir/{f,g}{1,2,3}.tx{t,x}"].sort.should eq [
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
datapath("dir", "f3.txx"),
datapath("dir", "g2.txt"),
].sort
end

{% if flag?(:windows) %}
pending "tests with \\"
{% else %}
it "tests with \\" do
with_tempfile "glob-escape-pattern" do |path|
Dir.mkdir_p path
Dir.cd(path) do
File.touch "g1.txt"
File.touch %q(\g3)
File.touch %q(\g4*)

Dir[%q(\\g*)].sort.should eq [
"\\g3",
"\\g4*",
].sort

Dir[%q(*g?\*)].sort.should eq [
"\\g4*",
].sort
end
end
end
{% end %}

it "tests with *" do
Dir["#{datapath}/dir/*"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*"].sort.should eq [
datapath("dir", "dots"),
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
Expand All @@ -322,7 +363,7 @@ describe "Dir" do
end

it "tests with ** (same as *)" do
Dir["#{datapath}/dir/**"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/**"].sort.should eq [
datapath("dir", "dots"),
datapath("dir", "f1.txt"),
datapath("dir", "f2.txt"),
Expand All @@ -334,7 +375,7 @@ describe "Dir" do
end

it "tests with */" do
Dir["#{datapath}/dir/*/"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*/"].sort.should eq [
datapath("dir", "dots", ""),
datapath("dir", "subdir", ""),
datapath("dir", "subdir2", ""),
Expand All @@ -350,15 +391,15 @@ describe "Dir" do
end

it "tests with relative path" do
Dir["#{datapath}/dir/*/"].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*/"].sort.should eq [
datapath("dir", "dots", ""),
datapath("dir", "subdir", ""),
datapath("dir", "subdir2", ""),
].sort
end

it "tests with relative path (starts with .)" do
Dir["./#{datapath}/dir/*/"].sort.should eq [
Dir["./#{Path[datapath].to_posix}/dir/*/"].sort.should eq [
File.join(".", "spec", "std", "data", "dir", "dots", ""),
File.join(".", "spec", "std", "data", "dir", "subdir", ""),
File.join(".", "spec", "std", "data", "dir", "subdir2", ""),
Expand All @@ -368,7 +409,7 @@ describe "Dir" do
it "tests with relative path (starts with ..)" do
Dir.cd(datapath) do
base_path = Path["..", "data", "dir"]
Dir["#{base_path}/*/"].sort.should eq [
Dir["#{base_path.to_posix}/*/"].sort.should eq [
base_path.join("dots", "").to_s,
base_path.join("subdir", "").to_s,
base_path.join("subdir2", "").to_s,
Expand All @@ -394,11 +435,11 @@ describe "Dir" do
File.symlink(datapath("dir", "f1.txt"), link)
File.symlink(datapath("dir", "nonexisting"), non_link)

Dir["#{path}/*_link.txt"].sort.should eq [
Dir["#{Path[path].to_posix}/*_link.txt"].sort.should eq [
link.to_s,
non_link.to_s,
].sort
Dir["#{path}/non_link.txt"].should eq [non_link.to_s]
Dir["#{Path[path].to_posix}/non_link.txt"].should eq [non_link.to_s]
end
end

Expand All @@ -414,8 +455,8 @@ describe "Dir" do
File.write(non_link, "")
File.symlink(target, link_dir)

Dir.glob("#{path}/glob/*/a.txt").sort.should eq [] of String
Dir.glob("#{path}/glob/*/a.txt", follow_symlinks: true).sort.should eq [
Dir.glob("#{Path[path].to_posix}/glob/*/a.txt").sort.should eq [] of String
Dir.glob("#{Path[path].to_posix}/glob/*/a.txt", follow_symlinks: true).sort.should eq [
File.join(path, "glob", "dir", "a.txt"),
]
end
Expand All @@ -435,27 +476,27 @@ describe "Dir" do
end

it "pattern ending with .." do
Dir["#{datapath}/dir/.."].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/.."].sort.should eq [
datapath("dir", ".."),
].sort
end

it "pattern ending with */.." do
Dir["#{datapath}/dir/*/.."].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*/.."].sort.should eq [
datapath("dir", "dots", ".."),
datapath("dir", "subdir", ".."),
datapath("dir", "subdir2", ".."),
].sort
end

it "pattern ending with ." do
Dir["#{datapath}/dir/."].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/."].sort.should eq [
datapath("dir", "."),
].sort
end

it "pattern ending with */." do
Dir["#{datapath}/dir/*/."].sort.should eq [
Dir["#{Path[datapath].to_posix}/dir/*/."].sort.should eq [
datapath("dir", "dots", "."),
datapath("dir", "subdir", "."),
datapath("dir", "subdir2", "."),
Expand All @@ -464,26 +505,26 @@ describe "Dir" do

context "match: :dot_files / match_hidden" do
it "matches dot files" do
Dir.glob("#{datapath}/dir/dots/**/*", match: :dot_files).sort.should eq [
Dir.glob("#{Path[datapath].to_posix}/dir/dots/**/*", match: :dot_files).sort.should eq [
datapath("dir", "dots", ".dot.hidden"),
datapath("dir", "dots", ".hidden"),
datapath("dir", "dots", ".hidden", "f1.txt"),
].sort
Dir.glob("#{datapath}/dir/dots/**/*", match_hidden: true).sort.should eq [
Dir.glob("#{Path[datapath].to_posix}/dir/dots/**/*", match_hidden: true).sort.should eq [
datapath("dir", "dots", ".dot.hidden"),
datapath("dir", "dots", ".hidden"),
datapath("dir", "dots", ".hidden", "f1.txt"),
].sort
end

it "ignores hidden files" do
Dir.glob("#{datapath}/dir/dots/*", match: :none).should be_empty
Dir.glob("#{datapath}/dir/dots/*", match_hidden: false).should be_empty
Dir.glob("#{Path[datapath].to_posix}/dir/dots/*", match: :none).should be_empty
Dir.glob("#{Path[datapath].to_posix}/dir/dots/*", match_hidden: false).should be_empty
end

it "ignores hidden files recursively" do
Dir.glob("#{datapath}/dir/dots/**/*", match: :none).should be_empty
Dir.glob("#{datapath}/dir/dots/**/*", match_hidden: false).should be_empty
Dir.glob("#{Path[datapath].to_posix}/dir/dots/**/*", match: :none).should be_empty
Dir.glob("#{Path[datapath].to_posix}/dir/dots/**/*", match_hidden: false).should be_empty
end
end

Expand Down Expand Up @@ -534,10 +575,10 @@ describe "Dir" do
expected_hidden = (expected + [hidden_txt, hidden_dir, inside_hidden]).sort!
expected_system_hidden = (expected_hidden + [system_hidden_txt, system_hidden_dir, inside_system_hidden]).sort!

Dir.glob("#{path}/**/*", match: :none).sort.should eq(expected)
Dir.glob("#{path}/**/*", match: :native_hidden).sort.should eq(expected_hidden)
Dir.glob("#{path}/**/*", match: :os_hidden).sort.should eq(expected)
Dir.glob("#{path}/**/*", match: File::MatchOptions[NativeHidden, OSHidden]).sort.should eq(expected_system_hidden)
Dir.glob("#{Path[path].to_posix}/**/*", match: :none).sort.should eq(expected)
Dir.glob("#{Path[path].to_posix}/**/*", match: :native_hidden).sort.should eq(expected_hidden)
Dir.glob("#{Path[path].to_posix}/**/*", match: :os_hidden).sort.should eq(expected)
Dir.glob("#{Path[path].to_posix}/**/*", match: File::MatchOptions[NativeHidden, OSHidden]).sort.should eq(expected_system_hidden)
end
end
{% end %}
Expand All @@ -550,8 +591,8 @@ describe "Dir" do
]

it "posix path" do
Dir[Path.posix(datapath, "dir", "*.txt")].sort.should eq expected
Dir[[Path.posix(datapath, "dir", "*.txt")]].sort.should eq expected
Dir[Path.posix(Path[datapath].to_posix, "dir", "*.txt")].sort.should eq expected
Dir[[Path.posix(Path[datapath].to_posix, "dir", "*.txt")]].sort.should eq expected
end

it "windows path" do
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/command/format.cr
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Crystal::Command
format_file filename
end
elsif Dir.exists?(filename)
filename = filename.chomp('/')
filename = ::Path[filename.chomp('/')].to_posix
filenames = Dir["#{filename}/**/*.cr"]
format_many filenames
else
Expand Down
1 change: 1 addition & 0 deletions src/compiler/crystal/command/spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Crystal::Command
locations << {file, line}
else
if Dir.exists?(filename)
filename = ::Path[filename].to_posix
target_filenames.concat Dir["#{filename}/**/*_spec.cr"]
elsif File.file?(filename)
target_filenames << filename
Expand Down
2 changes: 1 addition & 1 deletion src/dir/glob.cr
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class Dir

private def self.constant_entry?(file)
file.each_char do |char|
return false if char.in?('*', '?')
return false if char.in?('*', '?', '[', '\\')
end

true
Expand Down
Loading