Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

ssh: provide a factory function for setting ssh paths #2463

Merged
merged 1 commit into from

2 participants

@carlosmn
Owner

git allows you to set which paths to use for the git server programs
when connecting over ssh; and we want to provide something similar.

We do this by providing a factory function which can be set as the
remote's transport callback which will set the given paths upon
creation.

@carlosmn carlosmn referenced this pull request
Closed

Clone API completionism #1142

@carlosmn carlosmn changed the title from [WIP] ssh: provide a factory function for setting ssh paths to ssh: provide a factory function for setting ssh paths
@carlosmn carlosmn ssh: provide a factory function for setting ssh paths
git allows you to set which paths to use for the git server programs
when connecting over ssh; and we want to provide something similar.

We do this by providing a factory function which can be set as the
remote's transport callback which will set the given paths upon
creation.
d4256ed
@carlosmn
Owner

This should be ready to go in. The reset of the repository we use as scratch is due the clone trying to find a commit it didn't download, which is a bug in the default branch choosing.

@vmg vmg merged commit 44cfb6f into master

1 check passed

Details continuous-integration/travis-ci The Travis CI build passed
@carlosmn carlosmn deleted the cmn/ssh-factory-for-paths branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 7, 2014
  1. @carlosmn

    ssh: provide a factory function for setting ssh paths

    carlosmn authored
    git allows you to set which paths to use for the git server programs
    when connecting over ssh; and we want to provide something similar.
    
    We do this by providing a factory function which can be set as the
    remote's transport callback which will set the given paths upon
    creation.
This page is out of date. Refresh to see the latest.
View
4 CHANGELOG.md
@@ -15,6 +15,10 @@ v0.21 + 1
* The git_remote_set_transport function now sets a transport factory function,
rather than a pre-existing transport instance.
+* A factory function for ssh has been added which allows to change the
+ path of the programs to execute for receive-pack and upload-pack on
+ the server, git_transport_ssh_with_paths.
+
* The git_clone_options struct no longer provides the ignore_cert_errors or
remote_name members for remote customization.
View
16 include/git2/transport.h
@@ -336,6 +336,22 @@ GIT_EXTERN(int) git_transport_init(
*/
GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const char *url);
+/**
+ * Create an ssh transport with custom git command paths
+ *
+ * This is a factory function suitable for setting as the transport
+ * callback in a remote (or for a clone in the options).
+ *
+ * The payload argument must be a strarray pointer with the paths for
+ * the `git-upload-pack` and `git-receive-pack` at index 0 and 1.
+ *
+ * @param out the resulting transport
+ * @param owner the owning remote
+ * @param payload a strarray with the paths
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload);
+
/* Signature of a function which creates a transport */
typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
View
5 script/cibuild.sh
@@ -34,5 +34,8 @@ export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE=""
if [ -e ./libgit2_clar ]; then
- ./libgit2_clar -sonline::push -sonline::clone::cred_callback_failure
+ ./libgit2_clar -sonline::push -sonline::clone::cred_callback_failure &&
+ rm -rf $HOME/_temp/test.git &&
+ git init --bare $HOME/_temp/test.git && # create an empty one
+ ./libgit2_clar -sonline::clone::ssh_with_paths
fi
View
54 src/transports/ssh.c
@@ -37,6 +37,8 @@ typedef struct {
transport_smart *owner;
ssh_stream *current_stream;
git_cred *cred;
+ char *cmd_uploadpack;
+ char *cmd_receivepack;
} ssh_subtransport;
static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
@@ -504,7 +506,9 @@ static int ssh_uploadpack_ls(
const char *url,
git_smart_subtransport_stream **stream)
{
- if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0)
+ const char *cmd = t->cmd_uploadpack ? t->cmd_uploadpack : cmd_uploadpack;
+
+ if (_git_ssh_setup_conn(t, url, cmd, stream) < 0)
return -1;
return 0;
@@ -531,7 +535,9 @@ static int ssh_receivepack_ls(
const char *url,
git_smart_subtransport_stream **stream)
{
- if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0)
+ const char *cmd = t->cmd_receivepack ? t->cmd_receivepack : cmd_receivepack;
+
+ if (_git_ssh_setup_conn(t, url, cmd, stream) < 0)
return -1;
return 0;
@@ -596,6 +602,8 @@ static void _ssh_free(git_smart_subtransport *subtransport)
assert(!t->current_stream);
+ git__free(t->cmd_uploadpack);
+ git__free(t->cmd_receivepack);
git__free(t);
}
#endif
@@ -628,3 +636,45 @@ int git_smart_subtransport_ssh(
return -1;
#endif
}
+
+int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload)
+{
+#ifdef GIT_SSH
+ git_strarray *paths = (git_strarray *) payload;
+ git_transport *transport;
+ transport_smart *smart;
+ ssh_subtransport *t;
+ int error;
+ git_smart_subtransport_definition ssh_definition = {
+ git_smart_subtransport_ssh,
+ 0, /* no RPC */
+ };
+
+ if (paths->count != 2) {
+ giterr_set(GITERR_SSH, "invalid ssh paths, must be two strings");
+ return GIT_EINVALIDSPEC;
+ }
+
+ if ((error = git_transport_smart(&transport, owner, &ssh_definition)) < 0)
+ return error;
+
+ smart = (transport_smart *) transport;
+ t = (ssh_subtransport *) smart->wrapped;
+
+ t->cmd_uploadpack = git__strdup(paths->strings[0]);
+ GITERR_CHECK_ALLOC(t->cmd_uploadpack);
+ t->cmd_receivepack = git__strdup(paths->strings[1]);
+ GITERR_CHECK_ALLOC(t->cmd_receivepack);
+
+ *out = transport;
+ return 0;
+#else
+ GIT_UNUSED(owner);
+
+ assert(out);
+ *out = NULL;
+
+ giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support");
+ return -1;
+#endif
+}
View
65 tests/online/clone.c
@@ -288,8 +288,73 @@ void test_online_clone__can_cancel(void)
git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321);
}
+static int cred_cb(git_cred **cred, const char *url, const char *user_from_url,
+ unsigned int allowed_types, void *payload)
+{
+ const char *remote_user = cl_getenv("GITTEST_REMOTE_USER");
+ const char *pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY");
+ const char *privkey = cl_getenv("GITTEST_REMOTE_SSH_KEY");
+ const char *passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE");
+
+ GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload);
+
+ if (allowed_types & GIT_CREDTYPE_SSH_KEY)
+ return git_cred_ssh_key_new(cred, remote_user, pubkey, privkey, passphrase);
+
+ giterr_set(GITERR_NET, "unexpected cred type");
+ return -1;
+}
+
+static int custom_remote_ssh_with_paths(
+ git_remote **out,
+ git_repository *repo,
+ const char *name,
+ const char *url,
+ void *payload)
+{
+ int error;
+
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+
+ if ((error = git_remote_create(out, repo, name, url)) < 0)
+ return error;
+
+ if ((error = git_remote_set_transport(*out, git_transport_ssh_with_paths, payload)) < 0)
+ return error;
+ callbacks.credentials = cred_cb;
+ git_remote_set_callbacks(*out, &callbacks);
+ return 0;
+}
+
+void test_online_clone__ssh_with_paths(void)
+{
+ char *bad_paths[] = {
+ "/bin/yes",
+ "/bin/false",
+ };
+ char *good_paths[] = {
+ "/usr/bin/git-upload-pack",
+ "/usr/bin/git-receive-pack",
+ };
+ git_strarray arr = {
+ bad_paths,
+ 2,
+ };
+
+ const char *remote_url = cl_getenv("GITTEST_REMOTE_URL");
+ const char *remote_user = cl_getenv("GITTEST_REMOTE_USER");
+
+ if (!remote_url || !remote_user)
+ clar__skip();
+
+ g_options.remote_cb = custom_remote_ssh_with_paths;
+ g_options.remote_cb_payload = &arr;
+ cl_git_fail(git_clone(&g_repo, remote_url, "./foo", &g_options));
+ arr.strings = good_paths;
+ cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options));
+}
Something went wrong with that request. Please try again.