diff --git a/lib/jekyll/cleaner.rb b/lib/jekyll/cleaner.rb index d23da78f..ca8a0ca9 100644 --- a/lib/jekyll/cleaner.rb +++ b/lib/jekyll/cleaner.rb @@ -40,7 +40,7 @@ module Jekyll regex = keep_file_regex dirs = keep_dirs - Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file| + Utils.safe_glob(site.in_dest_dir, ["**", "*"], File::FNM_DOTMATCH).each do |file| next if file =~ HIDDEN_FILE_REGEX || file =~ regex || dirs.include?(file) files << file end diff --git a/lib/jekyll/collection.rb b/lib/jekyll/collection.rb index 70d47e90..6cf3e99b 100644 --- a/lib/jekyll/collection.rb +++ b/lib/jekyll/collection.rb @@ -78,7 +78,7 @@ module Jekyll def entries return Array.new unless exists? @entries ||= - Dir.glob(collection_dir("**", "*.*")).map do |entry| + Utils.safe_glob(collection_dir, ["**", "*.*"]).map do |entry| entry["#{collection_dir}/"] = ''; entry end end diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index 7d2490a6..67657492 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -218,5 +218,38 @@ module Jekyll template end + + # Work the same way as Dir.glob but seperating the input into two parts + # ('dir' + '/' + 'pattern') to make sure the first part('dir') does not act + # as a pattern. + # + # For example, Dir.glob("path[/*") always returns an empty array, + # because the method fails to find the closing pattern to '[' which is ']' + # + # Examples: + # safe_glob("path[", "*") + # # => ["path[/file1", "path[/file2"] + # + # safe_glob("path", "*", File::FNM_DOTMATCH) + # # => ["path/.", "path/..", "path/file1"] + # + # safe_glob("path", ["**", "*"]) + # # => ["path[/file1", "path[/folder/file2"] + # + # dir - the dir where glob will be executed under + # (the dir will be included to each result) + # patterns - the patterns (or the pattern) which will be applied under the dir + # flags - the flags which will be applied to the pattern + # + # Returns matched pathes + def safe_glob(dir, patterns, flags = 0) + return [] unless Dir.exist?(dir) + pattern = File.join(Array patterns) + return [dir] if pattern.empty? + Dir.chdir(dir) do + Dir.glob(pattern, flags).map { |f| File.join(dir, f) } + end + end + end end diff --git a/test/safe_glob_test[/find_me.txt b/test/safe_glob_test[/find_me.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/test_utils.rb b/test/test_utils.rb index d1ec2ece..f25a5f69 100644 --- a/test/test_utils.rb +++ b/test/test_utils.rb @@ -195,4 +195,43 @@ class TestUtils < JekyllUnitTest assert_equal "/:basename", Utils.add_permalink_suffix("/:basename", "/:title") end end + + context "The \`Utils.safe_glob\` method" do + should "not apply pattern to the dir" do + dir = "test/safe_glob_test[" + assert_equal [], Dir.glob(dir + "/*") + assert_equal ["test/safe_glob_test[/find_me.txt"], Utils.safe_glob(dir, "*") + end + + should "return the same data to #glob" do + dir = "test" + assert_equal Dir.glob(dir + "/*"), Utils.safe_glob(dir, "*") + assert_equal Dir.glob(dir + "/**/*"), Utils.safe_glob(dir, "**/*") + end + + should "return the same data to #glob if dir is not found" do + dir = "dir_not_exist" + assert_equal [], Utils.safe_glob(dir, "*") + assert_equal Dir.glob(dir + "/*"), Utils.safe_glob(dir, "*") + end + + should "return the same data to #glob if pattern is blank" do + dir = "test" + assert_equal [dir], Utils.safe_glob(dir, "") + assert_equal Dir.glob(dir), Utils.safe_glob(dir, "") + assert_equal Dir.glob(dir), Utils.safe_glob(dir, nil) + end + + should "return the same data to #glob if flag is given" do + dir = "test" + assert_equal Dir.glob(dir + "/*", File::FNM_DOTMATCH), + Utils.safe_glob(dir, "*", File::FNM_DOTMATCH) + end + + should "support pattern as an array to support windows" do + dir = "test" + assert_equal Dir.glob(dir + "/**/*"), Utils.safe_glob(dir, ["**", "*"]) + end + end + end