Commit 4e913309 by Carlos Martín Nieto

Move transports to an inheritance model

Rather than an 'private' pointer, make the private structures inherit
from the generic git_transport struct. This way, we only have to worry
about one memory allocation instead of two. The structures are so
simple that this may even make the code use less memory overall.

Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
parent 0a9a38e5
......@@ -52,4 +52,5 @@ struct git_pkt_ref {
};
int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len);
int git_pkt_send_flush(int s);
void git_pkt_free(git_pkt *pkt);
......@@ -177,7 +177,7 @@ typedef struct git_transport git_transport;
/** Whether to push or pull */
typedef enum git_net_direction git_net_direction;
typedef int (*git_transport_cb)(git_transport *transport);
typedef int (*git_transport_cb)(git_transport **transport);
typedef struct git_remote_head git_remote_head;
typedef struct git_headarray git_headarray;
......
......@@ -17,7 +17,7 @@ struct {
{NULL, 0}
};
static git_transport_cb transport_fill_fn(const char *url)
static git_transport_cb transport_new_fn(const char *url)
{
int i = 0;
......@@ -43,7 +43,7 @@ static git_transport_cb transport_fill_fn(const char *url)
* Public API *
**************/
int git_transport_dummy(git_transport *GIT_UNUSED(transport))
int git_transport_dummy(git_transport **GIT_UNUSED(transport))
{
GIT_UNUSED_ARG(transport);
return git__throw(GIT_ENOTIMPLEMENTED, "This protocol isn't implemented. Sorry");
......@@ -55,13 +55,11 @@ int git_transport_new(git_transport **out, git_repository *repo, const char *url
git_transport *transport;
int error;
fn = transport_fill_fn(url);
fn = transport_new_fn(url);
transport = git__malloc(sizeof(git_transport));
if (transport == NULL)
return GIT_ENOMEM;
memset(transport, 0x0, sizeof(git_transport));
error = fn(&transport);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create new transport");
transport->url = git__strdup(url);
if (transport->url == NULL)
......@@ -69,10 +67,6 @@ int git_transport_new(git_transport **out, git_repository *repo, const char *url
transport->repo = repo;
error = fn(transport);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create new transport");
*out = transport;
return GIT_SUCCESS;
......
......@@ -78,8 +78,8 @@ struct git_transport {
void (*free)(struct git_transport *transport);
};
int git_transport_local(struct git_transport *transport);
int git_transport_git(struct git_transport *transport);
int git_transport_dummy(struct git_transport *transport);
int git_transport_local(struct git_transport **transport);
int git_transport_git(struct git_transport **transport);
int git_transport_dummy(struct git_transport **transport);
#endif
......@@ -45,10 +45,12 @@
#include "netops.h"
typedef struct {
git_transport parent;
int socket;
git_vector refs;
git_remote_head **heads;
} git_priv;
} transport_git;
/*
* Create a git procol request.
*
......@@ -141,7 +143,7 @@ static int extract_host_and_port(char **host, char **port, const char *url)
* out. For convenience this also takes care of asking for the remote
* refs
*/
static int do_connect(git_priv *priv, const char *url)
static int do_connect(transport_git *t, const char *url)
{
int s = -1;
char *host, *port;
......@@ -155,7 +157,7 @@ static int do_connect(git_priv *priv, const char *url)
s = gitno_connect(host, port);
connected = 1;
error = send_request(s, NULL, url);
priv->socket = s;
t->socket = s;
free(host);
free(port);
......@@ -171,10 +173,10 @@ static int do_connect(git_priv *priv, const char *url)
/*
* Read from the socket and store the references in the vector
*/
static int store_refs(git_priv *priv)
static int store_refs(transport_git *t)
{
int s = priv->socket;
git_vector *refs = &priv->refs;
int s = t->socket;
git_vector *refs = &t->refs;
int error = GIT_SUCCESS;
char buffer[1024];
const char *line_end, *ptr;
......@@ -239,33 +241,26 @@ static int store_refs(git_priv *priv)
*/
static int git_connect(git_transport *transport, git_net_direction direction)
{
git_priv *priv;
transport_git *t = (transport_git *) transport;
int error = GIT_SUCCESS;
if (direction == INTENT_PUSH)
return git__throw(GIT_EINVALIDARGS, "Pushing is not supported with the git protocol");
priv = git__malloc(sizeof(git_priv));
if (priv == NULL)
return GIT_ENOMEM;
memset(priv, 0x0, sizeof(git_priv));
transport->private = priv;
error = git_vector_init(&priv->refs, 16, NULL);
error = git_vector_init(&t->refs, 16, NULL);
if (error < GIT_SUCCESS)
goto cleanup;
/* Connect and ask for the refs */
error = do_connect(priv, transport->url);
error = do_connect(t, transport->url);
if (error < GIT_SUCCESS)
return error;
error = store_refs(priv);
error = store_refs(t);
cleanup:
if (error < GIT_SUCCESS) {
git_vector_free(&priv->refs);
free(priv);
git_vector_free(&t->refs);
}
return error;
......@@ -273,8 +268,8 @@ cleanup:
static int git_ls(git_transport *transport, git_headarray *array)
{
git_priv *priv = transport->private;
git_vector *refs = &priv->refs;
transport_git *t = (transport_git *) transport;
git_vector *refs = &t->refs;
int len = 0;
unsigned int i;
......@@ -291,19 +286,19 @@ static int git_ls(git_transport *transport, git_headarray *array)
array->heads[i] = &(((git_pkt_ref *) p)->head);
}
array->len = len;
priv->heads = array->heads;
t->heads = array->heads;
return GIT_SUCCESS;
}
static int git_close(git_transport *transport)
{
git_priv *priv = transport->private;
int s = priv->socket;
transport_git *t = (transport_git*) transport;
int s = t->socket;
int error;
/* FIXME: We probably want to send a flush pkt back */
/* Can't do anything if there's an error, so don't bother checking */
git_pkt_send_flush(s);
error = close(s);
if (error < 0)
error = git__throw(GIT_EOSERR, "Failed to close socket");
......@@ -313,8 +308,8 @@ static int git_close(git_transport *transport)
static void git_free(git_transport *transport)
{
git_priv *priv = transport->private;
git_vector *refs = &priv->refs;
transport_git *t = (transport_git *) transport;
git_vector *refs = &t->refs;
unsigned int i;
for (i = 0; i < refs->length; ++i) {
......@@ -323,18 +318,25 @@ static void git_free(git_transport *transport)
}
git_vector_free(refs);
free(priv->heads);
free(priv);
free(transport->url);
free(transport);
free(t->heads);
free(t->parent.url);
free(t);
}
int git_transport_git(git_transport *transport)
int git_transport_git(git_transport **out)
{
transport->connect = git_connect;
transport->ls = git_ls;
transport->close = git_close;
transport->free = git_free;
transport_git *t;
t = git__malloc(sizeof(transport_git));
if (t == NULL)
return GIT_ENOMEM;
t->parent.connect = git_connect;
t->parent.ls = git_ls;
t->parent.close = git_close;
t->parent.free = git_free;
*out = (git_transport *) t;
return GIT_SUCCESS;
}
......@@ -9,9 +9,10 @@
#include "transport.h"
typedef struct {
git_transport parent;
git_repository *repo;
git_vector *refs;
} local_priv;
} transport_local;
static int cmp_refs(const void *a, const void *b)
{
......@@ -29,7 +30,7 @@ static int local_connect(git_transport *transport, git_net_direction GIT_UNUSED(
{
git_repository *repo;
int error;
local_priv *priv;
transport_local *t = (transport_local *) transport;
const char *path;
const char file_prefix[] = "file://";
GIT_UNUSED_ARG(dir);
......@@ -44,17 +45,8 @@ static int local_connect(git_transport *transport, git_net_direction GIT_UNUSED(
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open remote");
priv = git__malloc(sizeof(local_priv));
if (priv == NULL) {
git_repository_free(repo);
return GIT_ENOMEM;
}
priv->repo = repo;
transport->private = priv;
transport->connected = 1;
t->repo = repo;
t->parent.connected = 1;
return GIT_SUCCESS;
}
......@@ -135,11 +127,11 @@ static int local_ls(git_transport *transport, git_headarray *array)
git_repository *repo;
git_vector *vec;
git_strarray refs;
local_priv *priv = transport->private;
transport_local *t = (transport_local *) transport;
assert(transport && transport->connected);
repo = priv->repo;
repo = t->repo;
error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
if (error < GIT_SUCCESS)
......@@ -172,7 +164,7 @@ static int local_ls(git_transport *transport, git_headarray *array)
array->len = vec->length;
array->heads = (git_remote_head **)vec->contents;
priv->refs = vec;
t->refs = vec;
out:
......@@ -191,8 +183,8 @@ static int local_close(git_transport *GIT_UNUSED(transport))
static void local_free(git_transport *transport)
{
unsigned int i;
local_priv *priv = transport->private;
git_vector *vec = priv->refs;
transport_local *t = (transport_local *) transport;
git_vector *vec = t->refs;
assert(transport);
......@@ -203,22 +195,29 @@ static void local_free(git_transport *transport)
}
git_vector_free(vec);
free(vec);
git_repository_free(priv->repo);
free(priv);
free(transport->url);
free(transport);
git_repository_free(t->repo);
free(t->parent.url);
free(t);
}
/**************
* Public API *
**************/
int git_transport_local(git_transport *transport)
int git_transport_local(git_transport **out)
{
transport->connect = local_connect;
transport->ls = local_ls;
transport->close = local_close;
transport->free = local_free;
transport_local *t;
t = git__malloc(sizeof(transport_local));
if (t == NULL)
return GIT_ENOMEM;
t->parent.connect = local_connect;
t->parent.ls = local_ls;
t->parent.close = local_close;
t->parent.free = local_free;
*out = (git_transport *) t;
return GIT_SUCCESS;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment