Skip to content

Commit 65cf31d

Browse files
author
José Valim
committed
Do not match files starting with . in Path.wildcard/2 by default
1 parent e14c9ea commit 65cf31d

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

lib/elixir/lib/path.ex

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,32 @@ defmodule Path do
483483
FN.split(IO.chardata_to_string(path))
484484
end
485485

486+
defmodule Wildcard do
487+
@moduledoc false
488+
489+
def read_file_info(file) do
490+
call({:read_link_info, file})
491+
end
492+
493+
def list_dir(dir) do
494+
case call({:list_dir, dir}) do
495+
{:ok, files} ->
496+
{:ok, for(file <- files, hd(file) != ?., do: file)}
497+
other ->
498+
other
499+
end
500+
end
501+
502+
@compile {:inline, call: 1}
503+
504+
defp call(tuple) do
505+
x = :erlang.dt_spread_tag(true)
506+
y = :gen_server.call(:file_server_2, tuple)
507+
:erlang.dt_restore_tag(x)
508+
y
509+
end
510+
end
511+
486512
@doc """
487513
Traverses paths according to the given `glob` expression.
488514
@@ -503,6 +529,9 @@ defmodule Path do
503529
exactly the same character in the same position will match. Note
504530
that matching is case-sensitive; i.e. "a" will not match "A".
505531
532+
By default, the patterns `*` and `?` do not match files starting
533+
with a dot `.` unless `match_dot: true` is given.
534+
506535
## Examples
507536
508537
Imagine you have a directory called `projects` with three Elixir projects
@@ -517,10 +546,11 @@ defmodule Path do
517546
518547
"""
519548
@spec wildcard(t) :: [binary]
520-
def wildcard(glob) do
549+
def wildcard(glob, opts \\ []) do
550+
mod = if Keyword.get(opts, :match_dot), do: :file, else: Path.Wildcard
521551
glob
522-
|> chardata_to_list
523-
|> :filelib.wildcard
552+
|> chardata_to_list()
553+
|> :filelib.wildcard(mod)
524554
|> Enum.map(&IO.chardata_to_string/1)
525555
end
526556

@@ -552,7 +582,7 @@ defmodule Path do
552582
normalize t, acc
553583
end
554584

555-
defp normalize([".."|t], [<<_letter, ?:, ?/>>|_] = acc) when _letter in ?a..?z do
585+
defp normalize([".."|t], [<<letter, ?:, ?/>>|_] = acc) when letter in ?a..?z do
556586
normalize t, acc
557587
end
558588

lib/elixir/test/elixir/path_test.exs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,30 @@ defmodule PathTest do
55
import PathHelpers
66

77
if :file.native_name_encoding == :utf8 do
8-
test :wildcard do
8+
test :wildcard_with_utf8 do
99
File.mkdir_p(tmp_path("héllò"))
1010
assert Path.wildcard(tmp_path("héllò")) == [tmp_path("héllò")]
1111
after
1212
File.rm_rf tmp_path("héllò")
1313
end
1414
end
1515

16+
test :wildcard do
17+
hello = tmp_path("wildcard/.hello")
18+
world = tmp_path("wildcard/.hello/world")
19+
File.mkdir_p(world)
20+
21+
assert Path.wildcard(tmp_path("wildcard/*/*")) == []
22+
assert Path.wildcard(tmp_path("wildcard/**/*")) == []
23+
assert Path.wildcard(tmp_path("wildcard/?hello/world")) == []
24+
25+
assert Path.wildcard(tmp_path("wildcard/*/*"), match_dot: true) == [world]
26+
assert Path.wildcard(tmp_path("wildcard/**/*"), match_dot: true) == [hello, world]
27+
assert Path.wildcard(tmp_path("wildcard/?hello/world"), match_dot: true) == [world]
28+
after
29+
File.rm_rf tmp_path("wildcard")
30+
end
31+
1632
if is_win? do
1733
test :relative do
1834
assert Path.relative("C:/usr/local/bin") == "usr/local/bin"

lib/mix/lib/mix/utils.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ defmodule Mix.Utils do
108108
the return result. If it is a directory, it is searched
109109
recursively for files with the given extensions or matching
110110
the given patterns.
111-
112-
Any file starting with `"."` is ignored.
113111
"""
114112
def extract_files(paths, exts_or_pattern)
115113

@@ -118,15 +116,9 @@ defmodule Mix.Utils do
118116
end
119117

120118
def extract_files(paths, pattern) do
121-
files = Enum.flat_map(paths, fn path ->
119+
Enum.flat_map(paths, fn path ->
122120
if File.regular?(path), do: [path], else: Path.wildcard("#{path}/**/#{pattern}")
123-
end)
124-
files |> exclude_files |> Enum.uniq
125-
end
126-
127-
defp exclude_files(files) do
128-
filter = fn(x) -> not match?("." <> _, Path.basename(x)) end
129-
Enum.filter files, filter
121+
end) |> Enum.uniq
130122
end
131123

132124
@doc """

0 commit comments

Comments
 (0)