Skip to content

Commit

Permalink
Pass unknown protocols to external protocol handlers
Browse files Browse the repository at this point in the history
Change URL handling to allow external protocol handlers to implement
new protocols without the '::' syntax if helper name does not conflict
with any built-in protocol.

foo:// now invokes git-remote-foo with foo:// as the URL.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Ilari Liusvaara authored and Junio C Hamano committed Dec 9, 2009
1 parent 28ed5b3 commit 25d5cc4
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 16 deletions.
12 changes: 11 additions & 1 deletion transport-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ static void write_constant(int fd, const char *str)
die_errno("Full write to remote helper failed");
}

const char *remove_ext_force(const char *url)
{
if (url) {
const char *colon = strchr(url, ':');
if (colon && colon[1] == ':')
return colon + 2;
}
return url;
}

static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
Expand All @@ -83,7 +93,7 @@ static struct child_process *get_helper(struct transport *transport)
strbuf_addf(&buf, "remote-%s", data->name);
helper->argv[0] = strbuf_detach(&buf, NULL);
helper->argv[1] = transport->remote->name;
helper->argv[2] = transport->url;
helper->argv[2] = remove_ext_force(transport->url);
helper->git_cmd = 1;
if (start_command(helper))
die("Unable to run helper: git %s", helper->argv[0]);
Expand Down
76 changes: 61 additions & 15 deletions transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,44 @@ static int is_file(const char *url)
return S_ISREG(buf.st_mode);
}

static int is_url(const char *url)
{
const char *url2, *first_slash;

if (!url)
return 0;
url2 = url;
first_slash = strchr(url, '/');

/* Input with no slash at all or slash first can't be URL. */
if (!first_slash || first_slash == url)
return 0;
/* Character before must be : and next must be /. */
if (first_slash[-1] != ':' || first_slash[1] != '/')
return 0;
/* There must be something before the :// */
if (first_slash == url + 1)
return 0;
/*
* Check all characters up to first slash - 1. Only alphanum
* is allowed.
*/
url2 = url;
while (url2 < first_slash - 1) {
if (!isalnum((unsigned char)*url2))
return 0;
url2++;
}

/* Valid enough. */
return 1;
}

static int external_specification_len(const char *url)
{
return strchr(url, ':') - url;
}

struct transport *transport_get(struct remote *remote, const char *url)
{
struct transport *ret = xcalloc(1, sizeof(*ret));
Expand All @@ -805,30 +843,23 @@ struct transport *transport_get(struct remote *remote, const char *url)

if (remote && remote->foreign_vcs) {
transport_helper_init(ret, remote->foreign_vcs);
return ret;
}

if (!prefixcmp(url, "rsync:")) {
} else if (!prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;

} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
transport_helper_init(ret, "curl");
#ifdef NO_CURL
error("git was compiled without libcurl support.");
#endif

} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;

} else {
} else if (!is_url(url)
|| !prefixcmp(url, "file://")
|| !prefixcmp(url, "git://")
|| !prefixcmp(url, "ssh://")
|| !prefixcmp(url, "git+ssh://")
|| !prefixcmp(url, "ssh+git://")) {
/* These are builtin smart transports. */
struct git_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->set_option = set_git_option;
Expand All @@ -845,6 +876,21 @@ struct transport *transport_get(struct remote *remote, const char *url)
data->receivepack = "git-receive-pack";
if (remote->receivepack)
data->receivepack = remote->receivepack;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
/* These three are just plain special. */
transport_helper_init(ret, "curl");
#ifdef NO_CURL
error("git was compiled without libcurl support.");
#endif
} else {
/* Unknown protocol in URL. Pass to external handler. */
int len = external_specification_len(url);
char *handler = xmalloc(len + 1);
handler[len] = 0;
strncpy(handler, url, len);
transport_helper_init(ret, handler);
}

return ret;
Expand Down

0 comments on commit 25d5cc4

Please sign in to comment.