Commit e02e6a5cd2484129e88447b2efb061c228a035d2

Edward Thomson 2022-01-11T10:19:40

url: introduce git_net_str_is_url We occasionally need to determine whether a given string is a URL or something else. (The "something else" may be a git path in a different format, like scp formatting, which needs to be handled differently.)

diff --git a/src/net.c b/src/net.c
index 1d4a391..a76fd1d 100644
--- a/src/net.c
+++ b/src/net.c
@@ -20,6 +20,24 @@
 #define DEFAULT_PORT_GIT   "9418"
 #define DEFAULT_PORT_SSH   "22"
 
+bool git_net_str_is_url(const char *str)
+{
+	const char *c;
+
+	for (c = str; *c; c++) {
+		if (*c == ':' && *(c+1) == '/' && *(c+2) == '/')
+			return true;
+
+		if ((*c < 'a' || *c > 'z') &&
+		    (*c < 'A' || *c > 'Z') &&
+		    (*c < '0' || *c > '9') &&
+		    (*c != '+' && *c != '-' && *c != '.'))
+			break;
+	}
+
+	return false;
+}
+
 static const char *default_port_for_scheme(const char *scheme)
 {
 	if (strcmp(scheme, "http") == 0)
@@ -28,7 +46,9 @@ static const char *default_port_for_scheme(const char *scheme)
 		return DEFAULT_PORT_HTTPS;
 	else if (strcmp(scheme, "git") == 0)
 		return DEFAULT_PORT_GIT;
-	else if (strcmp(scheme, "ssh") == 0)
+	else if (strcmp(scheme, "ssh") == 0 ||
+	         strcmp(scheme, "ssh+git") == 0 ||
+		 strcmp(scheme, "git+ssh") == 0)
 		return DEFAULT_PORT_SSH;
 
 	return NULL;
diff --git a/src/net.h b/src/net.h
index 739769a..499315e 100644
--- a/src/net.h
+++ b/src/net.h
@@ -21,6 +21,9 @@ typedef struct git_net_url {
 
 #define GIT_NET_URL_INIT { NULL }
 
+/** Is a given string a url? */
+extern bool git_net_str_is_url(const char *str);
+
 /** Duplicate a URL */
 extern int git_net_url_dup(git_net_url *out, git_net_url *in);
 
diff --git a/tests/network/url/valid.c b/tests/network/url/valid.c
new file mode 100644
index 0000000..2b2cb7b
--- /dev/null
+++ b/tests/network/url/valid.c
@@ -0,0 +1,17 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+void test_network_url_valid__test(void)
+{
+	cl_assert(git_net_str_is_url("http://example.com/"));
+	cl_assert(git_net_str_is_url("file://localhost/tmp/foo/"));
+	cl_assert(git_net_str_is_url("ssh://user@host:42/tmp"));
+	cl_assert(git_net_str_is_url("git+ssh://user@host:42/tmp"));
+	cl_assert(git_net_str_is_url("ssh+git://user@host:42/tmp"));
+	cl_assert(git_net_str_is_url("https://user:pass@example.com/foo/bar"));
+
+	cl_assert(!git_net_str_is_url("host:foo.git"));
+	cl_assert(!git_net_str_is_url("host:/foo.git"));
+	cl_assert(!git_net_str_is_url("[host:42]:/foo.git"));
+	cl_assert(!git_net_str_is_url("[user@host:42]:/foo.git"));
+}