mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Remove "." and ".." from Dir.glob with FNM_DOTMATCH [Bug #17280]
Co-authored-by: Jeremy Evans <code@jeremyevans.net>
This commit is contained in:
		
							parent
							
								
									ccabf4966f
								
							
						
					
					
						commit
						7dc0511ea4
					
				
				
				Notes:
				
					git
				
				2021-01-12 20:03:14 +09:00 
				
			
			
			
		
		
					 6 changed files with 83 additions and 23 deletions
				
			
		
							
								
								
									
										10
									
								
								dir.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								dir.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -222,6 +222,7 @@ typedef enum {
 | 
			
		|||
#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(
 | 
			
		|||
            }
 | 
			
		||||
            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(
 | 
			
		|||
 | 
			
		||||
	    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 */
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,4 +169,14 @@ module DirSpecs
 | 
			
		|||
      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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ describe "Dir.glob" do
 | 
			
		|||
  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
 | 
			
		|||
  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
 | 
			
		|||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,8 +121,16 @@ describe :dir_glob, shared: true do
 | 
			
		|||
    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
 | 
			
		|||
    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
 | 
			
		|||
    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
 | 
			
		|||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1266,7 +1266,7 @@ class TestPathname < Test::Unit::TestCase
 | 
			
		|||
      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)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,7 +165,7 @@ class TestDir < Test::Unit::TestCase
 | 
			
		|||
  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
 | 
			
		|||
    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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue