[前][次][番号順一覧][スレッド一覧]

ruby-changes:64838

From: Nobuyoshi <ko1@a...>
Date: Tue, 12 Jan 2021 20:03:09 +0900 (JST)
Subject: [ruby-changes:64838] 7dc0511ea4 (master): Remove "." and ".." from Dir.glob with FNM_DOTMATCH [Bug #17280]

https://git.ruby-lang.org/ruby.git/commit/?id=7dc0511ea4

From 7dc0511ea4be210f82abb1c82a31aec3a4fe5736 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Tue, 12 Jan 2021 18:17:02 +0900
Subject: Remove "." and ".." from Dir.glob with FNM_DOTMATCH [Bug #17280]

Co-authored-by: Jeremy Evans <code@j...>

diff --git a/dir.c b/dir.c
index bedbdd9..48c9eae 100644
--- a/dir.c
+++ b/dir.c
@@ -222,6 +222,7 @@ typedef enum { https://github.com/ruby/ruby/blob/trunk/dir.c#L222
 #define FNM_SHORTNAME	0
 #endif
 #define FNM_GLOB_NOSORT 0x40
+#define FNM_GLOB_SKIPDOT 0x80
 
 #define FNM_NOMATCH	1
 #define FNM_ERROR	2
@@ -2413,6 +2414,10 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2414
             }
             return status;
         }
+
+	int skipdot = (flags & FNM_GLOB_SKIPDOT);
+	flags |= FNM_GLOB_SKIPDOT;
+
 	while ((dp = glob_getent(&globent, flags, enc)) != NULL) {
 	    char *buf;
 	    rb_pathtype_t new_pathtype = path_unknown;
@@ -2423,11 +2428,12 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2428
 
 	    name = dp->d_name;
 	    namlen = dp->d_namlen;
-	    if (recursive && name[0] == '.') {
+	    if (name[0] == '.') {
 		++dotfile;
 		if (namlen == 1) {
 		    /* unless DOTMATCH, skip current directories not to recurse infinitely */
-		    if (!(flags & FNM_DOTMATCH)) continue;
+		    if (recursive && !(flags & FNM_DOTMATCH)) continue;
+		    if (skipdot) continue;
 		    ++dotfile;
 		    new_pathtype = path_directory; /* force to skip stat/lstat */
 		}
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index 71b1438..a1ea3db 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -169,4 +169,14 @@ module DirSpecs https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/fixtures/common.rb#L169
       subdir_two
     ]
   end
+
+  if RUBY_VERSION > '3.1'
+    def self.expected_glob_paths
+      expected_paths - ['..']
+    end
+  else
+    def self.expected_glob_paths
+      expected_paths
+    end
+  end
 end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 9b6e2b2..61553ab 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -39,7 +39,7 @@ describe "Dir.glob" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/glob_spec.rb#L39
   end
 
   it "matches both dot and non-dotfiles with '*' and option File::FNM_DOTMATCH" do
-    Dir.glob('*', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_paths
+    Dir.glob('*', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_glob_paths
   end
 
   it "matches files with any beginning with '*<non-special characters>' and option File::FNM_DOTMATCH" do
@@ -47,7 +47,7 @@ describe "Dir.glob" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/glob_spec.rb#L47
   end
 
   it "matches any files in the current directory with '**' and option File::FNM_DOTMATCH" do
-    Dir.glob('**', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_paths
+    Dir.glob('**', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_glob_paths
   end
 
   it "recursively matches any subdirectories except './' or '../' with '**/' from the current directory and option File::FNM_DOTMATCH" do
@@ -70,16 +70,31 @@ describe "Dir.glob" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/glob_spec.rb#L70
     Dir.glob('**/', File::FNM_DOTMATCH).sort.should == expected
   end
 
-  it "recursively matches files and directories in nested dot subdirectory with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
-    expected = %w[
-      nested/.
-      nested/.dotsubir
-      nested/.dotsubir/.
-      nested/.dotsubir/.dotfile
-      nested/.dotsubir/nondotfile
-    ]
+  ruby_version_is ''...'3.1' do
+    it "recursively matches files and directories in nested dot subdirectory with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
+      expected = %w[
+        nested/.
+        nested/.dotsubir
+        nested/.dotsubir/.
+        nested/.dotsubir/.dotfile
+        nested/.dotsubir/nondotfile
+      ]
 
-    Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
+      Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
+    end
+  end
+
+  ruby_version_is '3.1' do
+    it "recursively matches files and directories in nested dot subdirectory except . with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
+      expected = %w[
+       nested/.
+       nested/.dotsubir
+       nested/.dotsubir/.dotfile
+       nested/.dotsubir/nondotfile
+     ]
+
+      Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
+    end
   end
 
   # This is a separate case to check **/ coming after a constant
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index f6d41ba..c35f7d7 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -121,8 +121,16 @@ describe :dir_glob, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/shared/glob.rb#L121
     Dir.send(@method, 'special/test\{1\}/*').should == ['special/test{1}/file[1]']
   end
 
-  it "matches dotfiles with '.*'" do
-    Dir.send(@method, '.*').sort.should == %w|. .. .dotfile .dotsubdir|.sort
+  ruby_version_is ''...'3.1' do
+    it "matches dotfiles with '.*'" do
+      Dir.send(@method, '.*').sort.should == %w|. .. .dotfile .dotsubdir|.sort
+    end
+  end
+
+  ruby_version_is '3.1' do
+    it "matches dotfiles except .. with '.*'" do
+      Dir.send(@method, '.*').sort.should == %w|. .dotfile .dotsubdir|.sort
+    end
   end
 
   it "matches non-dotfiles with '*<non-special characters>'" do
@@ -167,8 +175,16 @@ describe :dir_glob, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/shared/glob.rb#L175
     Dir.send(@method, '**').sort.should == expected
   end
 
-  it "matches dotfiles in the current directory with '.**'" do
-    Dir.send(@method, '.**').sort.should == %w|. .. .dotsubdir .dotfile|.sort
+  ruby_version_is ''...'3.1' do
+    it "matches dotfiles in the current directory with '.**'" do
+      Dir.send(@method, '.**').sort.should == %w|. .. .dotsubdir .dotfile|.sort
+    end
+  end
+
+  ruby_version_is '3.1' do
+    it "matches dotfiles in the current directory except .. with '.**'" do
+      Dir.send(@method, '.**').sort.should == %w|. .dotsubdir .dotfile|.sort
+    end
   end
 
   it "recursively matches any nondot subdirectories with '**/'" do
@@ -189,9 +205,19 @@ describe :dir_glob, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/shared/glob.rb#L205
     Dir.send(@method, '**/').sort.should == expected
   end
 
-  it "recursively matches any subdirectories including ./ and ../ with '.**/'" do
-    Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
-      Dir.send(@method, '.**/').sort.should == %w|./ ../|.sort
+  ruby_version_is ''...'3.1' do
+    it "recursively matches any subdirectories including ./ and ../ with '.**/'" do
+      Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
+        Dir.send(@method, '.**/').sort.should == %w|./ ../|.sort
+      end
+    end
+  end
+
+  ruby_version_is '3.1' do
+    it "recursively matches any subdirectories including ./ with '.**/'" do
+      Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
+        Dir.send(@method, '.**/').should == ['./']
+      end
     end
   end
 
@@ -234,7 +260,7 @@ describe :dir_glob, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/dir/shared/glob.rb#L260
   end
 
   it "matches dot or non-dotfiles with '{,.}*'" do
-    Dir.send(@method, '{,.}*').sort.should == DirSpecs.expected_paths
+    Dir.send(@method, '{,.}*').sort.should == DirSpecs.expected_glob_paths
   end
 
   it "respects the order of {} expressions, expanding left most first" do
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef48..2c07f77 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1266,7 +1266,7 @@ class TestPathname < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/pathname/test_pathname.rb#L1266
       open("f", "w") {|f| f.write "abc" }
       Dir.chdir("/") {
         assert_equal(
-          [Pathname("."), Pathname(".."), Pathname("f")],
+          [Pathname("."), Pathname("f")],
           Pathname.glob("*", File::FNM_DOTMATCH, base: dir).sort)
       }
     }
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index e5bcbea..bc91be4 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -165,7 +165,7 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L165
   end
 
   def test_glob
-    assert_equal((%w(. ..) + ("a".."z").to_a).map{|f| File.join(@root, f) },
+    assert_equal((%w(.) + ("a".."z").to_a).map{|f| File.join(@root, f) },
                  Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH))
     assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
                  Dir.glob([@root, File.join(@root, "*")]))
@@ -203,6 +203,9 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L203
     Dir.chdir(@root) do
       assert_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/.", bug8006)
 
+      Dir.mkdir("a/b")
+      assert_not_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/b/.")
+
       FileUtils.mkdir_p("a/b/c/d/e/f")
       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/e/f"), bug6977)
       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/d/e/f"), bug6977)
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]