implement support for username@host:path URLs in transport_find_fn()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
diff --git a/src/transport.c b/src/transport.c
index 672eb6e..523a9fc 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -10,6 +10,8 @@
#include "git2/net.h"
#include "transport.h"
+#include <regex.h>
+
static struct {
char *prefix;
git_transport_cb fn;
@@ -28,15 +30,35 @@ static struct {
static git_transport_cb transport_find_fn(const char *url)
{
size_t i = 0;
+ regex_t preg;
+ int error;
+ git_transport_cb output = NULL;
- /* TODO: Parse "example.com:project.git" as an SSH URL */
-
+ // First, check to see if it's an obvious URL, which a URL scheme
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
if (!strncasecmp(url, transports[i].prefix, strlen(transports[i].prefix)))
return transports[i].fn;
}
- return NULL;
+
+ // next, see if it matches un-schemed SSH paths used by Git
+ // if it does not match, it must be a local transport method
+ // use the slightly old fashioned :alnum: instead of \w or :word:, because
+ // both are Perl extensions to the Regular Expression language (and not available here)
+ error = regcomp(&preg, "^[[:alnum:]_]+@[[:alnum:]_]+\\.[[:alnum:]_]+:.+\\.git$", REG_EXTENDED);
+ if (error < 0)
+ goto cleanup;
+
+ int rc = regexec(&preg, url, 0, NULL, 0);
+ if ( rc == REG_NOMATCH )
+ output = NULL; // a match was not found - it's probably a file system path
+ else
+ output = &git_transport_git; // a match was found!
+
+cleanup:
+ regfree(&preg);
+
+ return output;
}
/**************
diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c
index 36b945f..4cf473d 100644
--- a/tests-clar/network/remotes.c
+++ b/tests-clar/network/remotes.c
@@ -30,6 +30,16 @@ void test_network_remotes__parsing(void)
cl_assert(!strcmp(git_remote_url(_remote), "git://github.com/libgit2/libgit2"));
}
+void test_network_remotes__parsing_ssh_remote(void)
+{
+ cl_assert( git_remote_valid_url("git@github.com:libgit2/libgit2.git") );
+}
+
+void test_network_remotes__parsing_local_path(void)
+{
+ cl_assert( !git_remote_valid_url("/home/git/repos/libgit2.git") );
+}
+
void test_network_remotes__refspec_parsing(void)
{
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));