Skip to content

Commit

Permalink
Fix files_included not being honored by Runner
Browse files Browse the repository at this point in the history
when reading from stdin.

Refs #1115
  • Loading branch information
rrrene committed Feb 17, 2024
1 parent 6d867b2 commit de32209
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/credo.ex
Expand Up @@ -31,12 +31,14 @@ defmodule Credo do
|> WriteDebugReport.call([])
end

@doc false
def run(argv_or_exec, files_that_changed) do
argv_or_exec
|> Execution.build(files_that_changed)
|> Execution.run()
|> WriteDebugReport.call([])
end

@doc false
def version, do: @version
end
16 changes: 15 additions & 1 deletion lib/credo/check/runner.ex
Expand Up @@ -51,7 +51,21 @@ defmodule Credo.Check.Runner do
# but it is necessary to avoid hitting the filesystem when reading from STDIN
[%Credo.SourceFile{filename: filename}] = Execution.get_source_files(exec)

if filename in files_excluded do
file_included? =
if files_included != [] do
Credo.Sources.filename_matches?(filename, files_included)
else
true
end

file_excluded? =
if files_excluded != [] do
Credo.Sources.filename_matches?(filename, files_excluded)
else
false
end

if !file_included? || file_excluded? do
:skip_run
else
[]
Expand Down
35 changes: 35 additions & 0 deletions lib/credo/sources.ex
Expand Up @@ -9,6 +9,41 @@ defmodule Credo.Sources do
@default_sources_glob ~w(** *.{ex,exs})
@stdin_filename "stdin"

@doc false
def filename_matches?(filename, patterns) do
patterns
|> List.wrap()
|> Enum.any?(&match_filename_pattern(filename, &1))
end

defp match_filename_pattern(filename, pattern) when is_binary(pattern) do
if String.contains?(pattern, "*") do
matches_glob_naively?(filename, pattern)
else
String.starts_with?(filename, pattern)
end
end

defp match_filename_pattern(filename, %Regex{} = pattern), do: String.match?(filename, pattern)

defp match_filename_pattern(_, pattern),
do: raise("Expected String or Regex, got: #{inspect(pattern)}")

# naively converts glob pattern to regex
# does not account for brace or tilde expansion or command substitution
# or anything other than * and **
defp matches_glob_naively?(filename, pattern) do
pattern
|> String.replace("/", "\\/")
|> String.replace("**", ".+")
|> String.replace("*", "[^\/]+")
|> Regex.compile()
|> case do
{:ok, regex} -> String.match?(filename, regex)
_ -> raise "Compiling glob pattern to regex failed: #{inspect(pattern)}"
end
end

@doc """
Finds sources for a given `Credo.Execution`.
Expand Down
17 changes: 17 additions & 0 deletions test/credo/sources_test.exs
Expand Up @@ -293,4 +293,21 @@ defmodule Credo.SourcesTest do

assert expected == Credo.Sources.find_in_dir(dir, ["*.ex"], [~r/.ex$/])
end

test "it matches filenames given patterns" do
assert Credo.Sources.filename_matches?("lib/credo/check/runner.ex", [
"lib/credo/check/runner.ex"
])

assert Credo.Sources.filename_matches?("lib/credo/check.ex", ["lib/*/check.ex"])
assert Credo.Sources.filename_matches?("lib/credo/check/runner.ex", ["lib/**/runner.ex"])
assert Credo.Sources.filename_matches?("lib/credo/check/runner.ex", ["lib/**/*.ex"])

assert Credo.Sources.filename_matches?("lib/credo/check/foo.ex", ["lib/**/*.ex"])
assert Credo.Sources.filename_matches?("lib/credo/check/foo.ex", [~r/.ex$/])

refute Credo.Sources.filename_matches?("lib/credo/check/runner.ex", ["lib/*/runner.ex"])
refute Credo.Sources.filename_matches?("lib/credo/check/runner.ex", ["*.exs"])
refute Credo.Sources.filename_matches?("lib/credo/check/runner.ex", [~r/.exs$/])
end
end

0 comments on commit de32209

Please sign in to comment.