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; }