summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Samson <samson.etienne@gmail.com>2016-05-13 02:20:36 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2017-03-12 15:16:29 +0100
commit559f8d57ac0e28991987dff5128cd6c72c8e5d58 (patch)
tree5c881ee89e7c6155957f948632c2f61e8a462d8b
parent53454be87f9b14f5df79a5917ce3986590438748 (diff)
downloadlibgit2-559f8d57ac0e28991987dff5128cd6c72c8e5d58.tar.gz
Weak-link against libssh2 and load it at runtime
-rw-r--r--CMakeLists.txt7
-rw-r--r--src/transports/ssh.c43
2 files changed, 49 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5bf21f54..98c3c8c24 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -362,7 +362,12 @@ IF (LIBSSH2_FOUND)
LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
#SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${LIBSSH2_LDFLAGS}")
- SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
+ IF (WIN32)
+ SET(WEAK_LINK "TODO")
+ ELSE()
+ SET(WEAK_LINK -Wl,-weak-l)
+ ENDIF()
+ SET(SSH_LIBRARIES ${WEAK_LINK} ${LIBSSH2_LIBRARIES})
CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS)
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 44d02e522..bdf7dc798 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -8,6 +8,7 @@
#ifdef GIT_SSH
#include <libssh2.h>
#endif
+#include <dlfcn.h>
#include "git2.h"
#include "buffer.h"
@@ -15,6 +16,7 @@
#include "smart.h"
#include "cred.h"
#include "socket_stream.h"
+#include "global.h"
#include "ssh.h"
#ifdef GIT_SSH
@@ -817,6 +819,8 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use
}
#endif
+static void *libssh2_handle = NULL;
+
int git_smart_subtransport_ssh(
git_smart_subtransport **out, git_transport *owner, void *param)
{
@@ -827,6 +831,13 @@ int git_smart_subtransport_ssh(
GIT_UNUSED(param);
+ if (libssh2_handle == NULL) {
+ *out = NULL;
+
+ giterr_set(GITERR_INVALID, "Cannot create SSH transport. SSH support unavailable");
+ return -1;
+ }
+
t = git__calloc(sizeof(ssh_subtransport), 1);
GITERR_CHECK_ALLOC(t);
@@ -863,6 +874,15 @@ int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *p
NULL,
};
+ assert(out);
+
+ if (libssh2_handle == NULL) {
+ *out = NULL;
+
+ giterr_set(GITERR_INVALID, "Cannot create SSH transport. SSH support unavailable");
+ return -1;
+ }
+
if (paths->count != 2) {
giterr_set(GITERR_SSH, "invalid ssh paths, must be two strings");
return GIT_EINVALIDSPEC;
@@ -893,9 +913,24 @@ int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *p
#endif
}
+void git_transport_ssh_global_shutdown(void);
+
int git_transport_ssh_global_init(void)
{
#ifdef GIT_SSH
+#ifdef GIT_WIN32
+ const char *(*libssh2_version)(int) = NULL;
+#else
+ libssh2_handle = dlopen("libssh2.dylib", RTLD_LAZY);
+ const char *(*libssh2_version)(int) = dlsym(libssh2_handle, "libssh2_version");
+#endif
+
+ // Check that libssh2's version is sufficient for us
+ if (!libssh2_version || !libssh2_version(LIBSSH2_VERSION_NUM)) {
+ return 0;
+ }
+
+ git__on_shutdown(git_transport_ssh_global_shutdown);
libssh2_init(0);
return 0;
@@ -904,6 +939,14 @@ int git_transport_ssh_global_init(void)
/* Nothing to initialize */
return 0;
+#endif
+}
+void git_transport_ssh_global_shutdown(void)
+{
+#ifdef WIN
+
+#else
+ dlclose(libssh2_handle);
#endif
}