Commit 864ac49e317dc8dfd683a1017c05584bd7a8864c

Carlos Martín Nieto 2012-03-05T19:32:41

Merge branch 'ssh-urls' into development

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/*"));