defmodule GitGud.Workflows.GlobTest do
@moduledoc """
Filter patterns (`branches:`, `tags:`, `paths:`) follow GitHub's cheat
sheet, not shell globbing: a workflow copied from GitHub's docs has to
claim the same refs and files here. `?` and `+` are quantifiers there, not
wildcards.
"""
use ExUnit.Case, async: true
alias GitGud.Workflows.Glob
doctest Glob
defp m?(pattern, path), do: Glob.match?(pattern, path)
test "* stays within one directory" do
assert m?("*.md", "a.md")
refute m?("*.md", "docs/a.md")
end
test "**/ matches any depth, including none" do
assert m?("**/*.md", "a.md")
assert m?("**/*.md", "docs/a.md")
assert m?("**/*.md", "docs/deep/a.md")
refute m?("**/*.md", "docs/a.txt")
end
test "a trailing /** matches the files under the directory, not the directory" do
assert m?("docs/**", "docs/a.txt")
assert m?("docs/**", "docs/a/b.txt")
refute m?("docs/**", "docs")
refute m?("docs/**", "other/docs/a.txt")
end
test "a directory prefix is a whole path segment" do
assert m?("android/**", "android/app/build.gradle")
refute m?("android/**", "androidx/a")
end
test "** with no slash crosses directories" do
assert m?("**.js", "a.js")
assert m?("**.js", "a/b/c.js")
assert m?("**", "anything/at/all")
end
# `?` used to be "any one character" (`a?c` matched `abc`); on GitHub it
# makes the preceding character optional.
test "? is zero or one of the preceding character" do
assert m?("colou?r", "color")
assert m?("colou?r", "colour")
refute m?("colou?r", "colouur")
assert m?("a?c", "ac")
assert m?("a?c", "c")
refute m?("a?c", "abc")
end
test "+ is one or more of the preceding character" do
assert m?("v1+", "v1")
assert m?("v1+", "v11")
refute m?("v1+", "v")
assert m?("a+b", "aaab")
refute m?("a+b", "b")
end
test "quantifiers apply to a class" do
assert m?("v[0-9]+.[0-9]+", "v10.233")
refute m?("v[0-9]+.[0-9]+", "v.1")
assert m?("[ab]?c", "c")
end
test "a quantifier applies to a whole multibyte character" do
assert m?("café+", "cafééé")
refute m?("café+", "café\xA9")
end
test "a ? or + with nothing to quantify is literal" do
assert m?("?a", "?a")
refute m?("?a", "a")
assert m?("+a", "+a")
assert m?("*?", "x?")
refute m?("*?", "x")
assert m?("a++", "aa+")
refute m?("a++", "aaa")
end
test "character classes and ranges" do
assert m?("[ab].txt", "a.txt")
assert m?("[ab].txt", "b.txt")
refute m?("[ab].txt", "c.txt")
assert m?("v[0-9]", "v7")
refute m?("v[0-9]", "vx")
assert m?("[CB]at", "Cat")
assert m?("[CB]at", "Bat")
refute m?("[CB]at", "cat")
assert m?("[a-zA-Z0-9]", "Q")
end
test "a bracket the cheat sheet doesn't allow is literal" do
assert m?("a[b", "a[b")
assert m?("[!a]", "[!a]")
refute m?("[!a]", "b")
assert m?("[^a]", "[^a]")
assert m?("[.]", "[.]")
assert m?("[]", "[]")
assert m?("[a-Z]", "[a-Z]")
end
test "a backslash escapes a special character" do
assert m?("a\\*b", "a*b")
refute m?("a\\*b", "axb")
assert m?("\\[x]", "[x]")
refute m?("\\[x]", "x")
assert m?("\\!a", "!a")
assert m?("a\\?", "a?")
refute m?("a\\?", "a")
end
test "dots and other regex characters are literal" do
assert m?("mix.exs", "mix.exs")
refute m?("mix.exs", "mixxexs")
assert m?("a(b|c).txt", "a(b|c).txt")
refute m?("a(b|c).txt", "ab.txt")
end
test "patterns are anchored at both ends" do
refute m?("lib", "lib/a.ex")
refute m?("a.ex", "lib/a.ex")
end
test "a compiled pattern can be reused" do
regex = Glob.compile("lib/**")
assert Glob.match?(regex, "lib/a.ex")
refute Glob.match?(regex, "test/a.exs")
end
describe "select?/2" do
test "the last matching pattern decides" do
assert Glob.select?(["releases/**", "!releases/**-alpha"], "releases/1.0")
refute Glob.select?(["releases/**", "!releases/**-alpha"], "releases/1.0-alpha")
assert Glob.select?(["*", "!b*", "beta"], "beta")
refute Glob.select?(["*", "!b*", "beta"], "bravo")
end
test "nothing matching selects nothing" do
refute Glob.select?(["main"], "topic")
refute Glob.select?([], "topic")
end
@tag :capture_log
test "a list of only negative patterns selects nothing" do
refute Glob.select?(["!main"], "topic")
refute Glob.select?(["!main"], "main")
end
test "an escaped ! is a positive, literal pattern" do
assert Glob.select?(["\\!x"], "!x")
end
test "takes a compiled list" do
rules = Glob.compile_list(["src/**", "!src/gen/**"])
assert Glob.select?(rules, "src/a")
refute Glob.select?(rules, "src/gen/a")
end
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
4.7 KiB · text
History
91138c0