summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-08-31 22:01:34 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2021-09-01 20:40:19 -0400
commit9e98e443ca5e95bfb570536187c6e155bc126e59 (patch)
treed1eccc035814b3628a795c4d0fcc058fd76f60ab
parente5ba0a3c37a5a1a24f1904d56ebf8d30df9df75f (diff)
downloadlibgit2-9e98e443ca5e95bfb570536187c6e155bc126e59.tar.gz
url: introduce `git_net_url_matches_pattern_list`
Provide a utility method on a url to determine if it matches any pattern in a comma-separated list, similar to what one would find in `NO_PROXY` environment variables.
-rw-r--r--src/net.c19
-rw-r--r--src/net.h3
-rw-r--r--tests/network/url/pattern.c49
3 files changed, 71 insertions, 0 deletions
diff --git a/src/net.c b/src/net.c
index f3cca5da7..3322f68c2 100644
--- a/src/net.c
+++ b/src/net.c
@@ -459,6 +459,25 @@ bool git_net_url_matches_pattern(git_net_url *url, const char *pattern)
return matches_pattern(url, pattern, strlen(pattern));
}
+bool git_net_url_matches_pattern_list(
+ git_net_url *url,
+ const char *pattern_list)
+{
+ const char *pattern, *pattern_end, *sep;
+
+ for (pattern = pattern_list;
+ pattern && *pattern;
+ pattern = sep ? sep + 1 : NULL) {
+ sep = strchr(pattern, ',');
+ pattern_end = sep ? sep : strchr(pattern, '\0');
+
+ if (matches_pattern(url, pattern, (pattern_end - pattern)))
+ return true;
+ }
+
+ return false;
+}
+
void git_net_url_dispose(git_net_url *url)
{
if (url->username)
diff --git a/src/net.h b/src/net.h
index 4d4c7c7fe..971e002b6 100644
--- a/src/net.h
+++ b/src/net.h
@@ -58,6 +58,9 @@ extern int git_net_url_fmt_path(git_buf *buf, git_net_url *url);
extern bool git_net_url_matches_pattern(
git_net_url *url,
const char *pattern);
+extern bool git_net_url_matches_pattern_list(
+ git_net_url *url,
+ const char *pattern_list);
/** Disposes the contents of the structure. */
extern void git_net_url_dispose(git_net_url *url);
diff --git a/tests/network/url/pattern.c b/tests/network/url/pattern.c
index fbe1f9e55..5e4495f70 100644
--- a/tests/network/url/pattern.c
+++ b/tests/network/url/pattern.c
@@ -52,3 +52,52 @@ void test_network_url_pattern__single(void)
git_net_url_dispose(&url);
}
}
+
+void test_network_url_pattern__list(void)
+{
+ git_net_url url;
+ size_t i;
+
+ struct url_pattern url_patterns[] = {
+ /* Wildcard matches */
+ { "https://example.com/", "", false },
+ { "https://example.com/", "*", true },
+ { "https://example.com/", ",example.com,", true },
+ { "https://example.com/", "foo,,example.com,,bar", true },
+ { "https://example.com/", "foo,,zzz,,*,,bar", true },
+
+ /* Literals */
+ { "https://example.com/", "example.com", true },
+ { "https://example.com/", "foo.bar,example.com", true },
+ { "https://example.com/", "foo.bar", false },
+ { "https://example.com/", "foo.bar,example.org", false },
+ { "https://www.example.com/", "foo.example.com,www.example.com,bar.example.com", true },
+ { "https://www.example.com/", "foo.example.com,baz.example.com,bar.example.com", false },
+ { "https://foo.example.com/", "www.example.com", false },
+ { "https://foo.example.com/", "bar.example.com,www.example.com,", false },
+
+ /* Wildcards */
+ { "https://example.com/", ".example.com", true },
+ { "https://example.com/", "*.example.com", true },
+ { "https://example.com/", "foo.com,bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,asdf.com", false },
+ { "https://example.com/", "*.foo,*.bar,*.example.com,*.asdf", true },
+ { "https://example.com/", "*.foo,*.bar,*.asdf", false },
+
+
+ /* Ports! */
+ { "https://example.com/", "example.com:443", true },
+ { "https://example.com/", "example.com:42,example.com:443,example.com:99", true },
+ { "https://example.com/", "example.com:42,example.com:80,example.org:443", false },
+ { "https://example.com:1443/", "example.com", true },
+ { "https://example.com:44/", "example.com:443", false },
+ { "https://example.com:443/", "example.com:44", false },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
+ cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
+ cl_assert_(git_net_url_matches_pattern_list(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
+ git_net_url_dispose(&url);
+ }
+}