From 4e913309b92138cdc6ff31fbce4e8afa2ab5458e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 17 Jun 2011 16:38:21 +0200 Subject: [PATCH] Move transports to an inheritance model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- include/git2/pkt.h | 1 + include/git2/types.h | 2 +- src/transport.c | 18 ++++------- src/transport.h | 6 ++-- src/transport_git.c | 74 ++++++++++++++++++++++--------------------- src/transport_local.c | 53 +++++++++++++++---------------- 6 files changed, 75 insertions(+), 79 deletions(-) diff --git a/include/git2/pkt.h b/include/git2/pkt.h index 59826da8a..0b17b3eed 100644 --- a/include/git2/pkt.h +++ b/include/git2/pkt.h @@ -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); diff --git a/include/git2/types.h b/include/git2/types.h index ef80435c4..dae96cf22 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -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; diff --git a/src/transport.c b/src/transport.c index fb0dc32c9..59aecb4cf 100644 --- a/src/transport.c +++ b/src/transport.c @@ -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; diff --git a/src/transport.h b/src/transport.h index e951d4c6b..6d5f037b8 100644 --- a/src/transport.h +++ b/src/transport.h @@ -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 diff --git a/src/transport_git.c b/src/transport_git.c index eb5f70870..ca1f044e3 100644 --- a/src/transport_git.c +++ b/src/transport_git.c @@ -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; } diff --git a/src/transport_local.c b/src/transport_local.c index a096e48c3..5dc5c26ca 100644 --- a/src/transport_local.c +++ b/src/transport_local.c @@ -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; }