Refactor struct transport_ops inlined into struct transport
Aside from reducing the code by 20 lines this refactoring removes a level of indirection when trying to access the operations of a given transport "instance", making the code clearer and easier to follow. It also has the nice effect of giving us the benefits of C99 style struct initialization (namely ".fetch = X") without requiring that level of language support from our compiler. We don't need to worry about new operation methods being added as they will now be NULL'd out automatically by the xcalloc() we use to create the new struct transport we supply to the caller. This pattern already exists in struct walker, so we already have a precedent for it in Git. We also don't really need to worry about any sort of performance decreases that may occur as a result of filling out 4-8 op pointers when we make a "struct transport". The extra few CPU cycles this requires over filling in the "struct transport_ops" is killed by the time it will take Git to actually *use* one of those functions, as most transport operations are going over the wire or will be copying object data locally between two directories. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
28b91f8ad9
commit
824d5776c3
@ -392,8 +392,7 @@ static int do_fetch(struct transport *transport,
|
|||||||
if (transport->remote->fetch_tags == -1)
|
if (transport->remote->fetch_tags == -1)
|
||||||
no_tags = 1;
|
no_tags = 1;
|
||||||
|
|
||||||
if (!transport->ops || !transport->ops->get_refs_list ||
|
if (!transport->get_refs_list || !transport->fetch)
|
||||||
!transport->ops->fetch)
|
|
||||||
die("Don't know how to fetch from %s", transport->url);
|
die("Don't know how to fetch from %s", transport->url);
|
||||||
|
|
||||||
/* if not appending, truncate FETCH_HEAD */
|
/* if not appending, truncate FETCH_HEAD */
|
||||||
|
62
transport.c
62
transport.c
@ -44,8 +44,6 @@ static int disconnect_walker(struct transport *transport)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct transport_ops rsync_transport;
|
|
||||||
|
|
||||||
static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) {
|
static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
int argc;
|
int argc;
|
||||||
@ -199,14 +197,6 @@ static int fetch_objs_via_curl(struct transport *transport,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct transport_ops curl_transport = {
|
|
||||||
/* set_option */ NULL,
|
|
||||||
/* get_refs_list */ get_refs_via_curl,
|
|
||||||
/* fetch */ fetch_objs_via_curl,
|
|
||||||
/* push */ curl_transport_push,
|
|
||||||
/* disconnect */ disconnect_walker
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bundle_transport_data {
|
struct bundle_transport_data {
|
||||||
int fd;
|
int fd;
|
||||||
struct bundle_header header;
|
struct bundle_header header;
|
||||||
@ -249,14 +239,6 @@ static int close_bundle(struct transport *transport)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct transport_ops bundle_transport = {
|
|
||||||
/* set_option */ NULL,
|
|
||||||
/* get_refs_list */ get_refs_from_bundle,
|
|
||||||
/* fetch */ fetch_refs_from_bundle,
|
|
||||||
/* push */ NULL,
|
|
||||||
/* disconnect */ close_bundle
|
|
||||||
};
|
|
||||||
|
|
||||||
struct git_transport_data {
|
struct git_transport_data {
|
||||||
unsigned thin : 1;
|
unsigned thin : 1;
|
||||||
unsigned keep : 1;
|
unsigned keep : 1;
|
||||||
@ -401,13 +383,6 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const
|
|||||||
return !!err;
|
return !!err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct transport_ops git_transport = {
|
|
||||||
/* set_option */ set_git_option,
|
|
||||||
/* get_refs_list */ get_refs_via_connect,
|
|
||||||
/* fetch */ fetch_refs_via_pack,
|
|
||||||
/* push */ git_transport_push
|
|
||||||
};
|
|
||||||
|
|
||||||
static int is_local(const char *url)
|
static int is_local(const char *url)
|
||||||
{
|
{
|
||||||
const char *colon = strchr(url, ':');
|
const char *colon = strchr(url, ':');
|
||||||
@ -431,18 +406,31 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||||||
ret->url = url;
|
ret->url = url;
|
||||||
|
|
||||||
if (!prefixcmp(url, "rsync://")) {
|
if (!prefixcmp(url, "rsync://")) {
|
||||||
ret->ops = &rsync_transport;
|
/* not supported; don't populate any ops */
|
||||||
|
|
||||||
} else if (!prefixcmp(url, "http://")
|
} else if (!prefixcmp(url, "http://")
|
||||||
|| !prefixcmp(url, "https://")
|
|| !prefixcmp(url, "https://")
|
||||||
|| !prefixcmp(url, "ftp://")) {
|
|| !prefixcmp(url, "ftp://")) {
|
||||||
ret->ops = &curl_transport;
|
ret->get_refs_list = get_refs_via_curl;
|
||||||
|
ret->fetch = fetch_objs_via_curl;
|
||||||
|
ret->push = curl_transport_push;
|
||||||
|
ret->disconnect = disconnect_walker;
|
||||||
|
|
||||||
} else if (is_local(url) && is_file(url)) {
|
} else if (is_local(url) && is_file(url)) {
|
||||||
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
|
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
|
||||||
ret->data = data;
|
ret->data = data;
|
||||||
ret->ops = &bundle_transport;
|
ret->get_refs_list = get_refs_from_bundle;
|
||||||
|
ret->fetch = fetch_refs_from_bundle;
|
||||||
|
ret->disconnect = close_bundle;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
struct git_transport_data *data = xcalloc(1, sizeof(*data));
|
struct git_transport_data *data = xcalloc(1, sizeof(*data));
|
||||||
ret->data = data;
|
ret->data = data;
|
||||||
|
ret->set_option = set_git_option;
|
||||||
|
ret->get_refs_list = get_refs_via_connect;
|
||||||
|
ret->fetch = fetch_refs_via_pack;
|
||||||
|
ret->push = git_transport_push;
|
||||||
|
|
||||||
data->thin = 1;
|
data->thin = 1;
|
||||||
data->uploadpack = "git-upload-pack";
|
data->uploadpack = "git-upload-pack";
|
||||||
if (remote && remote->uploadpack)
|
if (remote && remote->uploadpack)
|
||||||
@ -451,7 +439,6 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||||||
if (remote && remote->receivepack)
|
if (remote && remote->receivepack)
|
||||||
data->receivepack = remote->receivepack;
|
data->receivepack = remote->receivepack;
|
||||||
data->unpacklimit = -1;
|
data->unpacklimit = -1;
|
||||||
ret->ops = &git_transport;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -460,24 +447,23 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||||||
int transport_set_option(struct transport *transport,
|
int transport_set_option(struct transport *transport,
|
||||||
const char *name, const char *value)
|
const char *name, const char *value)
|
||||||
{
|
{
|
||||||
if (transport->ops->set_option)
|
if (transport->set_option)
|
||||||
return transport->ops->set_option(transport, name, value);
|
return transport->set_option(transport, name, value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int transport_push(struct transport *transport,
|
int transport_push(struct transport *transport,
|
||||||
int refspec_nr, const char **refspec, int flags)
|
int refspec_nr, const char **refspec, int flags)
|
||||||
{
|
{
|
||||||
if (!transport->ops->push)
|
if (!transport->push)
|
||||||
return 1;
|
return 1;
|
||||||
return transport->ops->push(transport, refspec_nr, refspec, flags);
|
return transport->push(transport, refspec_nr, refspec, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ref *transport_get_remote_refs(struct transport *transport)
|
struct ref *transport_get_remote_refs(struct transport *transport)
|
||||||
{
|
{
|
||||||
if (!transport->remote_refs)
|
if (!transport->remote_refs)
|
||||||
transport->remote_refs =
|
transport->remote_refs = transport->get_refs_list(transport);
|
||||||
transport->ops->get_refs_list(transport);
|
|
||||||
return transport->remote_refs;
|
return transport->remote_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +482,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
|
|||||||
heads[nr_heads++] = rm;
|
heads[nr_heads++] = rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = transport->ops->fetch(transport, nr_heads, heads);
|
rc = transport->fetch(transport, nr_heads, heads);
|
||||||
free(heads);
|
free(heads);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -513,8 +499,8 @@ void transport_unlock_pack(struct transport *transport)
|
|||||||
int transport_disconnect(struct transport *transport)
|
int transport_disconnect(struct transport *transport)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (transport->ops->disconnect)
|
if (transport->disconnect)
|
||||||
ret = transport->ops->disconnect(transport);
|
ret = transport->disconnect(transport);
|
||||||
free(transport);
|
free(transport);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
16
transport.h
16
transport.h
@ -5,22 +5,11 @@
|
|||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
|
||||||
struct transport {
|
struct transport {
|
||||||
unsigned verbose : 1;
|
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
const char *url;
|
const char *url;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
struct ref *remote_refs;
|
struct ref *remote_refs;
|
||||||
|
|
||||||
const struct transport_ops *ops;
|
|
||||||
char *pack_lockfile;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TRANSPORT_PUSH_ALL 1
|
|
||||||
#define TRANSPORT_PUSH_FORCE 2
|
|
||||||
|
|
||||||
struct transport_ops {
|
|
||||||
/**
|
/**
|
||||||
* Returns 0 if successful, positive if the option is not
|
* Returns 0 if successful, positive if the option is not
|
||||||
* recognized or is inapplicable, and negative if the option
|
* recognized or is inapplicable, and negative if the option
|
||||||
@ -34,8 +23,13 @@ struct transport_ops {
|
|||||||
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
|
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
|
||||||
|
|
||||||
int (*disconnect)(struct transport *connection);
|
int (*disconnect)(struct transport *connection);
|
||||||
|
char *pack_lockfile;
|
||||||
|
unsigned verbose : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TRANSPORT_PUSH_ALL 1
|
||||||
|
#define TRANSPORT_PUSH_FORCE 2
|
||||||
|
|
||||||
/* Returns a transport suitable for the url */
|
/* Returns a transport suitable for the url */
|
||||||
struct transport *transport_get(struct remote *, const char *);
|
struct transport *transport_get(struct remote *, const char *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user