Merge branch 'ssh-urls' into development
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
diff --git a/include/git2/remote.h b/include/git2/remote.h
index e6537ec..1830c72 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -198,6 +198,14 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote);
GIT_EXTERN(int) git_remote_valid_url(const char *url);
/**
+ * Return whether the passed URL is supported by this version of the library.
+ *
+ * @param url the url to check
+ * @return 1 if the url is supported, 0 otherwise
+*/
+GIT_EXTERN(int) git_remote_supported_url(const char* url);
+
+/**
* Get a list of the configured remotes for a repo
*
* The string array must be freed by the user.
diff --git a/src/transport.c b/src/transport.c
index 785ddc3..4910f24 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -9,6 +9,7 @@
#include "git2/remote.h"
#include "git2/net.h"
#include "transport.h"
+#include "path.h"
static struct {
char *prefix;
@@ -29,13 +30,20 @@ static git_transport_cb transport_find_fn(const char *url)
{
size_t i = 0;
- /* 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;
}
+ /* still here? Check to see if the path points to a file on the local file system */
+ if ((git_path_exists(url) == GIT_SUCCESS) && git_path_isdir(url))
+ return &git_transport_local;
+
+ /* It could be a SSH remote path. Check to see if there's a : */
+ if (strrchr(url, ':'))
+ return &git_transport_dummy; /* SSH is an unsupported transport mechanism in this version of libgit2 */
+
return NULL;
}
@@ -57,12 +65,8 @@ int git_transport_new(git_transport **out, const char *url)
fn = transport_find_fn(url);
- /*
- * If we haven't found the transport, we assume we mean a
- * local file.
- */
if (fn == NULL)
- fn = &git_transport_local;
+ return git__throw(GIT_EINVALIDARGS, "Unsupported URL or non-existent path");
error = fn(&transport);
if (error < GIT_SUCCESS)
@@ -83,3 +87,9 @@ int git_remote_valid_url(const char *url)
return transport_find_fn(url) != NULL;
}
+int git_remote_supported_url(const char* url)
+{
+ git_transport_cb transport_fn = transport_find_fn(url);
+
+ return ((transport_fn != NULL) && (transport_fn != &git_transport_dummy));
+}
diff --git a/src/transport.h b/src/transport.h
index 4c12357..63dd7da 100644
--- a/src/transport.h
+++ b/src/transport.h
@@ -102,6 +102,11 @@ int git_transport_local(struct git_transport **transport);
int git_transport_git(struct git_transport **transport);
int git_transport_http(struct git_transport **transport);
int git_transport_dummy(struct git_transport **transport);
+
+/**
+ Returns true if the passed URL is valid (a URL with a Git supported scheme,
+ or pointing to an existing path)
+*/
int git_transport_valid_url(const char *url);
typedef struct git_transport git_transport;
diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c
index 36b945f..add99c1 100644
--- a/tests-clar/network/remotes.c
+++ b/tests-clar/network/remotes.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "buffer.h"
#include "refspec.h"
+#include "transport.h"
static git_remote *_remote;
static git_repository *_repo;
@@ -30,6 +31,26 @@ 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_fails_if_path_not_found(void)
+{
+ cl_assert( !git_remote_valid_url("/home/git/repos/libgit2.git") );
+}
+
+void test_network_remotes__supported_transport_methods_are_supported(void)
+{
+ cl_assert( git_remote_supported_url("git://github.com/libgit2/libgit2") );
+}
+
+void test_network_remotes__unsupported_transport_methods_are_unsupported(void)
+{
+ cl_assert( !git_remote_supported_url("git@github.com:libgit2/libgit2.git") );
+}
+
void test_network_remotes__refspec_parsing(void)
{
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));