From c982647310fc5acd0bd6ebc408e70470447b387f Mon Sep 17 00:00:00 2001 From: Nick Hengeveld Date: Wed, 15 Mar 2006 08:59:52 -0800 Subject: Fix broken slot reuse when fetching alternates When fetching alternates, http-fetch may reuse the slot to fetch non-http alternates if http-alternates does not exist. When doing so, it now needs to update the slot's finished status so run_active_slot waits for the non-http alternates request to finish. Signed-off-by: Nick Hengeveld Signed-off-by: Junio C Hamano --- http-fetch.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 8fd9de081..7de818b10 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -468,9 +468,13 @@ static void process_alternates_response(void *callback_data) alt_req->url); active_requests++; slot->in_use = 1; + if (slot->finished != NULL) + (*slot->finished) = 0; if (!start_active_slot(slot)) { got_alternates = -1; slot->in_use = 0; + if (slot->finished != NULL) + (*slot->finished) = 1; } return; } -- cgit v1.2.1 From bb52807916598301e670963e6cc5f1f5cdca3ad7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 20 Mar 2006 14:07:59 -0800 Subject: http-fetch: nicer warning for a server with unreliable 404 status When a repository otherwise properly prepared is served by a dumb HTTP server that sends "No such page" output with 200 status for human consumption to a request for a page that does not exist, the users will get an alarming "File X corrupt" error message. Hint that they might be dealing with such a server at the end and suggest running fsck-objects to check if the result is OK (the pack-fallback code does the right thing in this case so unless a loose object file was actually corrupt the result should check OK). Signed-off-by: Junio C Hamano --- http-fetch.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 7de818b10..dc67218ae 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -8,6 +8,7 @@ #define RANGE_HEADER_SIZE 30 static int got_alternates = -1; +static int corrupt_object_found = 0; static struct curl_slist *no_pragma_header; @@ -834,6 +835,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) obj_req->errorstr, obj_req->curl_result, obj_req->http_code, hex); } else if (obj_req->zret != Z_STREAM_END) { + corrupt_object_found++; ret = error("File %s (%s) corrupt", hex, obj_req->url); } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) { ret = error("File %s has bad hash", hex); @@ -993,5 +995,11 @@ int main(int argc, char **argv) http_cleanup(); + if (corrupt_object_found) { + fprintf(stderr, +"Some loose object were found to be corrupt, but they might be just\n" +"a false '404 Not Found' error message sent with incorrect HTTP\n" +"status code. Suggest running git fsck-objects.\n"); + } return rc; } -- cgit v1.2.1 From 8d9fbe57b3acf756a9325884d11f004ef6f7e884 Mon Sep 17 00:00:00 2001 From: Nick Hengeveld Date: Tue, 4 Apr 2006 05:33:18 -0700 Subject: http-fetch: add optional DAV-based pack list If git is not built with NO_EXPAT, this patch changes git-http-fetch to attempt using DAV to get a list of remote packs and fall back to using objects/info/packs if the DAV request fails. Signed-off-by: Nick Hengeveld Signed-off-by: Junio C Hamano --- http-fetch.c | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index dc67218ae..71a7dafd6 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -4,6 +4,35 @@ #include "fetch.h" #include "http.h" +#ifndef NO_EXPAT +#include + +/* Definitions for DAV requests */ +#define DAV_PROPFIND "PROPFIND" +#define DAV_PROPFIND_RESP ".multistatus.response" +#define DAV_PROPFIND_NAME ".multistatus.response.href" +#define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection" +#define PROPFIND_ALL_REQUEST "\n\n\n" + +/* Definitions for processing XML DAV responses */ +#ifndef XML_STATUS_OK +enum XML_Status { + XML_STATUS_OK = 1, + XML_STATUS_ERROR = 0 +}; +#define XML_STATUS_OK 1 +#define XML_STATUS_ERROR 0 +#endif + +/* Flags that control remote_ls processing */ +#define PROCESS_FILES (1u << 0) +#define PROCESS_DIRS (1u << 1) +#define RECURSIVE (1u << 2) + +/* Flags that remote_ls passes to callback functions */ +#define IS_DIR (1u << 0) +#endif + #define PREV_BUF_SIZE 4096 #define RANGE_HEADER_SIZE 30 @@ -15,6 +44,7 @@ static struct curl_slist *no_pragma_header; struct alt_base { char *base; + int path_len; int got_indices; struct packed_git *packs; struct alt_base *next; @@ -58,6 +88,30 @@ struct alternates_request { int http_specific; }; +#ifndef NO_EXPAT +struct xml_ctx +{ + char *name; + int len; + char *cdata; + void (*userFunc)(struct xml_ctx *ctx, int tag_closed); + void *userData; +}; + +struct remote_ls_ctx +{ + struct alt_base *repo; + char *path; + void (*userFunc)(struct remote_ls_ctx *ls); + void *userData; + int flags; + char *dentry_name; + int dentry_flags; + int rc; + struct remote_ls_ctx *parent; +}; +#endif + static struct object_request *object_queue_head = NULL; static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, @@ -500,6 +554,7 @@ static void process_alternates_response(void *callback_data) int serverlen = 0; struct alt_base *newalt; char *target = NULL; + char *path; if (data[i] == '/') { serverlen = strchr(base + 8, '/') - base; okay = 1; @@ -540,6 +595,13 @@ static void process_alternates_response(void *callback_data) newalt->base = target; newalt->got_indices = 0; newalt->packs = NULL; + path = strstr(target, "//"); + if (path) { + path = index(path+2, '/'); + if (path) + newalt->path_len = strlen(path); + } + while (tail->next != NULL) tail = tail->next; tail->next = newalt; @@ -611,6 +673,209 @@ static void fetch_alternates(char *base) free(url); } +#ifndef NO_EXPAT +static void +xml_start_tag(void *userData, const char *name, const char **atts) +{ + struct xml_ctx *ctx = (struct xml_ctx *)userData; + const char *c = index(name, ':'); + int new_len; + + if (c == NULL) + c = name; + else + c++; + + new_len = strlen(ctx->name) + strlen(c) + 2; + + if (new_len > ctx->len) { + ctx->name = xrealloc(ctx->name, new_len); + ctx->len = new_len; + } + strcat(ctx->name, "."); + strcat(ctx->name, c); + + if (ctx->cdata) { + free(ctx->cdata); + ctx->cdata = NULL; + } + + ctx->userFunc(ctx, 0); +} + +static void +xml_end_tag(void *userData, const char *name) +{ + struct xml_ctx *ctx = (struct xml_ctx *)userData; + const char *c = index(name, ':'); + char *ep; + + ctx->userFunc(ctx, 1); + + if (c == NULL) + c = name; + else + c++; + + ep = ctx->name + strlen(ctx->name) - strlen(c) - 1; + *ep = 0; +} + +static void +xml_cdata(void *userData, const XML_Char *s, int len) +{ + struct xml_ctx *ctx = (struct xml_ctx *)userData; + if (ctx->cdata) + free(ctx->cdata); + ctx->cdata = xcalloc(len+1, 1); + strncpy(ctx->cdata, s, len); +} + +static int remote_ls(struct alt_base *repo, const char *path, int flags, + void (*userFunc)(struct remote_ls_ctx *ls), + void *userData); + +static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed) +{ + struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData; + + if (tag_closed) { + if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) { + if (ls->dentry_flags & IS_DIR) { + if (ls->flags & PROCESS_DIRS) { + ls->userFunc(ls); + } + if (strcmp(ls->dentry_name, ls->path) && + ls->flags & RECURSIVE) { + ls->rc = remote_ls(ls->repo, + ls->dentry_name, + ls->flags, + ls->userFunc, + ls->userData); + } + } else if (ls->flags & PROCESS_FILES) { + ls->userFunc(ls); + } + } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) { + ls->dentry_name = xmalloc(strlen(ctx->cdata) - + ls->repo->path_len + 1); + strcpy(ls->dentry_name, ctx->cdata + ls->repo->path_len); + } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) { + ls->dentry_flags |= IS_DIR; + } + } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) { + if (ls->dentry_name) { + free(ls->dentry_name); + } + ls->dentry_name = NULL; + ls->dentry_flags = 0; + } +} + +static int remote_ls(struct alt_base *repo, const char *path, int flags, + void (*userFunc)(struct remote_ls_ctx *ls), + void *userData) +{ + char *url = xmalloc(strlen(repo->base) + strlen(path) + 1); + struct active_request_slot *slot; + struct slot_results results; + struct buffer in_buffer; + struct buffer out_buffer; + char *in_data; + char *out_data; + XML_Parser parser = XML_ParserCreate(NULL); + enum XML_Status result; + struct curl_slist *dav_headers = NULL; + struct xml_ctx ctx; + struct remote_ls_ctx ls; + + ls.flags = flags; + ls.repo = repo; + ls.path = strdup(path); + ls.dentry_name = NULL; + ls.dentry_flags = 0; + ls.userData = userData; + ls.userFunc = userFunc; + ls.rc = 0; + + sprintf(url, "%s%s", repo->base, path); + + out_buffer.size = strlen(PROPFIND_ALL_REQUEST); + out_data = xmalloc(out_buffer.size + 1); + snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST); + out_buffer.posn = 0; + out_buffer.buffer = out_data; + + in_buffer.size = 4096; + in_data = xmalloc(in_buffer.size); + in_buffer.posn = 0; + in_buffer.buffer = in_data; + + dav_headers = curl_slist_append(dav_headers, "Depth: 1"); + dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); + + slot = get_active_slot(); + slot->results = &results; + curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer); + curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size); + curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer); + curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); + curl_easy_setopt(slot->curl, CURLOPT_URL, url); + curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1); + curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); + + if (start_active_slot(slot)) { + run_active_slot(slot); + if (results.curl_result == CURLE_OK) { + ctx.name = xcalloc(10, 1); + ctx.len = 0; + ctx.cdata = NULL; + ctx.userFunc = handle_remote_ls_ctx; + ctx.userData = &ls; + XML_SetUserData(parser, &ctx); + XML_SetElementHandler(parser, xml_start_tag, + xml_end_tag); + XML_SetCharacterDataHandler(parser, xml_cdata); + result = XML_Parse(parser, in_buffer.buffer, + in_buffer.posn, 1); + free(ctx.name); + + if (result != XML_STATUS_OK) { + ls.rc = error("XML error: %s", + XML_ErrorString( + XML_GetErrorCode(parser))); + } + } else { + ls.rc = -1; + } + } else { + ls.rc = error("Unable to start PROPFIND request"); + } + + free(ls.path); + free(url); + free(out_data); + free(in_buffer.buffer); + curl_slist_free_all(dav_headers); + + return ls.rc; +} + +static void process_ls_pack(struct remote_ls_ctx *ls) +{ + unsigned char sha1[20]; + + if (strlen(ls->dentry_name) == 63 && + !strncmp(ls->dentry_name, "objects/pack/pack-", 18) && + !strncmp(ls->dentry_name+58, ".pack", 5)) { + get_sha1_hex(ls->dentry_name + 18, sha1); + setup_index(ls->repo, sha1); + } +} +#endif + static int fetch_indices(struct alt_base *repo) { unsigned char sha1[20]; @@ -633,6 +898,12 @@ static int fetch_indices(struct alt_base *repo) if (get_verbosely) fprintf(stderr, "Getting pack list for %s\n", repo->base); +#ifndef NO_EXPAT + if (remote_ls(repo, "objects/pack/", PROCESS_FILES, + process_ls_pack, NULL) == 0) + return 0; +#endif + url = xmalloc(strlen(repo->base) + 21); sprintf(url, "%s/objects/info/packs", repo->base); @@ -947,6 +1218,7 @@ int main(int argc, char **argv) { char *commit_id; char *url; + char *path; int arg = 1; int rc = 0; @@ -987,6 +1259,12 @@ int main(int argc, char **argv) alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; + path = strstr(url, "//"); + if (path) { + path = index(path+2, '/'); + if (path) + alt->path_len = strlen(path); + } if (pull(commit_id)) rc = 1; -- cgit v1.2.1 From ef9e58c826a4fcaa13457cd8177518163f82972a Mon Sep 17 00:00:00 2001 From: Dennis Stosberg Date: Tue, 11 Apr 2006 18:37:58 +0200 Subject: Replace index() with strchr(). strchr() is more portable than index() and is used everywhere in git already. Signed-off-by: Junio C Hamano --- http-fetch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 71a7dafd6..861644b27 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -597,7 +597,7 @@ static void process_alternates_response(void *callback_data) newalt->packs = NULL; path = strstr(target, "//"); if (path) { - path = index(path+2, '/'); + path = strchr(path+2, '/'); if (path) newalt->path_len = strlen(path); } @@ -678,7 +678,7 @@ static void xml_start_tag(void *userData, const char *name, const char **atts) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); int new_len; if (c == NULL) @@ -707,7 +707,7 @@ static void xml_end_tag(void *userData, const char *name) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); char *ep; ctx->userFunc(ctx, 1); @@ -1261,7 +1261,7 @@ int main(int argc, char **argv) alt->next = NULL; path = strstr(url, "//"); if (path) { - path = index(path+2, '/'); + path = strchr(path+2, '/'); if (path) alt->path_len = strlen(path); } -- cgit v1.2.1 From d0740d92beb019a7b02678e5acea79c0ff67e3ee Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Fri, 19 May 2006 03:29:26 -0400 Subject: Log ref updates made by fetch. If a ref is changed by http-fetch, local-fetch or ssh-fetch record the change and the remote URL/name in the log for the ref. This requires loading the config file to check logAllRefUpdates. Also fixed a bug in the ref lock generation; the log file name was not being produced right due to a bad prefix length. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http-fetch.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 861644b27..cc7bd1f36 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1223,6 +1223,7 @@ int main(int argc, char **argv) int rc = 0; setup_git_directory(); + git_config(git_default_config); while (arg < argc && argv[arg][0] == '-') { if (argv[arg][1] == 't') { @@ -1249,6 +1250,7 @@ int main(int argc, char **argv) } commit_id = argv[arg]; url = argv[arg + 1]; + write_ref_log_details = url; http_init(); -- cgit v1.2.1 From 07001f95a60149619bed62af7ad59052ace7ac92 Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 20 May 2006 18:46:33 -0400 Subject: Remove possible segfault in http-fetch. Free the curl string lists after running http_cleanup to avoid an occasional segfault in the curl library. Seems to only occur if the website returns a 405 error. Signed-off-by: Sean Estabrooks Signed-off-by: Junio C Hamano --- http-fetch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 861644b27..178f1ee31 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1269,10 +1269,10 @@ int main(int argc, char **argv) if (pull(commit_id)) rc = 1; - curl_slist_free_all(no_pragma_header); - http_cleanup(); + curl_slist_free_all(no_pragma_header); + if (corrupt_object_found) { fprintf(stderr, "Some loose object were found to be corrupt, but they might be just\n" -- cgit v1.2.1 From e8dff6ba8b12db94b728ff4d0ebf65040de92c37 Mon Sep 17 00:00:00 2001 From: Nick Hengeveld Date: Tue, 6 Jun 2006 22:22:35 -0700 Subject: http-fetch: fix possible segfault Initialize an object request's slot to a safe value. A non-NULL value can cause a segfault if the request is aborted before it starts. Signed-off-by: Nick Hengeveld Signed-off-by: Junio C Hamano --- http-fetch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 661c90915..d3602b7d7 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -399,6 +399,7 @@ void prefetch(unsigned char *sha1) snprintf(newreq->filename, sizeof(newreq->filename), "%s", filename); snprintf(newreq->tmpfile, sizeof(newreq->tmpfile), "%s.temp", filename); + newreq->slot = NULL; newreq->next = NULL; if (object_queue_head == NULL) { -- cgit v1.2.1 From bfbd0bb6ecbbbf75a5caaff6afaf5a6af8fa518e Mon Sep 17 00:00:00 2001 From: Peter Eriksen Date: Sun, 11 Jun 2006 14:03:28 +0200 Subject: Implement safe_strncpy() as strlcpy() and use it more. Signed-off-by: Peter Eriksen Signed-off-by: Junio C Hamano --- http-fetch.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index d3602b7d7..da1a7f541 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -584,10 +584,8 @@ static void process_alternates_response(void *callback_data) // skip 'objects' at end if (okay) { target = xmalloc(serverlen + posn - i - 6); - strncpy(target, base, serverlen); - strncpy(target + serverlen, data + i, - posn - i - 7); - target[serverlen + posn - i - 7] = '\0'; + safe_strncpy(target, base, serverlen); + safe_strncpy(target + serverlen, data + i, posn - i - 6); if (get_verbosely) fprintf(stderr, "Also look at %s\n", target); @@ -728,8 +726,8 @@ xml_cdata(void *userData, const XML_Char *s, int len) struct xml_ctx *ctx = (struct xml_ctx *)userData; if (ctx->cdata) free(ctx->cdata); - ctx->cdata = xcalloc(len+1, 1); - strncpy(ctx->cdata, s, len); + ctx->cdata = xmalloc(len + 1); + safe_strncpy(ctx->cdata, s, len + 1); } static int remote_ls(struct alt_base *repo, const char *path, int flags, -- cgit v1.2.1 From cfd432e63d77478d913497a62827ed95c56dda73 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 18 Jun 2006 17:18:03 +0200 Subject: Remove ranges from switch statements. Though very nice and readable, the "case 'a'...'z':" construct is not ANSI C99 compliant. This patch unfolds the range in `quote.c' and substitutes the switch-statement with an if-statement in `http-fetch.c' and `http-push.c'. Signed-off-by: Florian Forster Signed-off-by: Junio C Hamano --- http-fetch.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index da1a7f541..3a2cb5e1f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1136,13 +1136,14 @@ int fetch(unsigned char *sha1) static inline int needs_quote(int ch) { - switch (ch) { - case '/': case '-': case '.': - case 'A'...'Z': case 'a'...'z': case '0'...'9': + if (((ch >= 'A') && (ch <= 'Z')) + || ((ch >= 'a') && (ch <= 'z')) + || ((ch >= '0') && (ch <= '9')) + || (ch == '/') + || (ch == '-') + || (ch == '.')) return 0; - default: - return 1; - } + return 1; } static inline int hex(int v) -- cgit v1.2.1 From 1d7f171c3a456b980d821ee0f68e01535a5f7e36 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 18 Jun 2006 17:18:09 +0200 Subject: Remove all void-pointer arithmetic. ANSI C99 doesn't allow void-pointer arithmetic. This patch fixes this in various ways. Usually the strategy that required the least changes was used. Signed-off-by: Florian Forster Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 3a2cb5e1f..2b63d8950 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -123,7 +123,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, struct object_request *obj_req = (struct object_request *)data; do { ssize_t retval = write(obj_req->local, - ptr + posn, size - posn); + (char *) ptr + posn, size - posn); if (retval < 0) return posn; posn += retval; -- cgit v1.2.1 From 817151e61a74241df5b5dd206d27086283f28b84 Mon Sep 17 00:00:00 2001 From: Peter Eriksen Date: Sat, 24 Jun 2006 16:01:25 +0200 Subject: Rename safe_strncpy() to strlcpy(). This cleans up the use of safe_strncpy() even more. Since it has the same semantics as strlcpy() use this name instead. Also move the definition from inside path.c to its own file compat/strlcpy.c, and use it conditionally at compile time, since some platforms already has strlcpy(). It's included in the same way as compat/setenv.c. Signed-off-by: Peter Eriksen Signed-off-by: Junio C Hamano --- http-fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 2b63d8950..44eba5fd0 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -584,8 +584,8 @@ static void process_alternates_response(void *callback_data) // skip 'objects' at end if (okay) { target = xmalloc(serverlen + posn - i - 6); - safe_strncpy(target, base, serverlen); - safe_strncpy(target + serverlen, data + i, posn - i - 6); + strlcpy(target, base, serverlen); + strlcpy(target + serverlen, data + i, posn - i - 6); if (get_verbosely) fprintf(stderr, "Also look at %s\n", target); @@ -727,7 +727,7 @@ xml_cdata(void *userData, const XML_Char *s, int len) if (ctx->cdata) free(ctx->cdata); ctx->cdata = xmalloc(len + 1); - safe_strncpy(ctx->cdata, s, len + 1); + strlcpy(ctx->cdata, s, len + 1); } static int remote_ls(struct alt_base *repo, const char *path, int flags, -- cgit v1.2.1 From a9486b02ec7e03d17317fe538b0d06ca04379f23 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 10 Jul 2006 02:57:51 -0400 Subject: Avoid C99 comments, use old-style C comments instead. This doesn't make the code uglier or harder to read, yet it makes the code more portable. This also simplifies checking for other potential incompatibilities. "gcc -std=c89 -pedantic" can flag many incompatible constructs as warnings, but C99 comments will cause it to emit an error. Signed-off-by: Pavel Roskin Signed-off-by: Junio C Hamano --- http-fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 44eba5fd0..12493fbed 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -490,7 +490,7 @@ static int setup_index(struct alt_base *repo, unsigned char *sha1) { struct packed_git *new_pack; if (has_pack_file(sha1)) - return 0; // don't list this as something we can get + return 0; /* don't list this as something we can get */ if (fetch_index(repo, sha1)) return -1; @@ -570,7 +570,7 @@ static void process_alternates_response(void *callback_data) base[serverlen - 1] != '/'); i += 3; } - // If the server got removed, give up. + /* If the server got removed, give up. */ okay = strchr(base, ':') - base + 3 < serverlen; } else if (alt_req->http_specific) { @@ -581,7 +581,7 @@ static void process_alternates_response(void *callback_data) okay = 1; } } - // skip 'objects' at end + /* skip 'objects' at end */ if (okay) { target = xmalloc(serverlen + posn - i - 6); strlcpy(target, base, serverlen); -- cgit v1.2.1 From cc41cd2e60da8224dcd04f23d837853cff5d4eda Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 27 Jul 2006 20:58:53 +0200 Subject: Remove -d from *-fetch usage strings This is a really ancient remnant of the short era of delta objects stored directly in the object database. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 12493fbed..dc286b79f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1245,7 +1245,7 @@ int main(int argc, char **argv) arg++; } if (argc < arg + 2) { - usage("git-http-fetch [-c] [-t] [-a] [-d] [-v] [--recover] [-w ref] commit-id url"); + usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url"); return 1; } commit_id = argv[arg]; -- cgit v1.2.1 From c6b69bdbc1b0b914aa0d1e59a29305fce82d6f06 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 27 Jul 2006 23:56:14 +0200 Subject: Make pull() take some implicit data as explicit arguments Currently it's a bit weird that pull() takes a single argument describing the commit but takes the write_ref from a global variable. This makes it take that as a parameter as well, which might be nicer for the libification in the future, but especially it will make for nicer code when we implement pull()ing multiple commits at once. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- http-fetch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index dc286b79f..963d439f8 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1216,6 +1216,7 @@ int fetch_ref(char *ref, unsigned char *sha1) int main(int argc, char **argv) { + const char *write_ref = NULL; char *commit_id; char *url; char *path; @@ -1250,7 +1251,6 @@ int main(int argc, char **argv) } commit_id = argv[arg]; url = argv[arg + 1]; - write_ref_log_details = url; http_init(); @@ -1268,7 +1268,7 @@ int main(int argc, char **argv) alt->path_len = strlen(path); } - if (pull(commit_id)) + if (pull(commit_id, write_ref, url)) rc = 1; http_cleanup(); -- cgit v1.2.1 From 4211e4d10cd98b1aeed97bdb6cdebb9411956bb5 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 27 Jul 2006 23:56:17 +0200 Subject: Make pull() support fetching multiple targets at once pull() now takes an array of arguments instead of just one of each kind. Currently, no users use the new capability, but that'll change. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 963d439f8..bc67db1ad 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1268,7 +1268,7 @@ int main(int argc, char **argv) alt->path_len = strlen(path); } - if (pull(commit_id, write_ref, url)) + if (pull(1, &commit_id, &write_ref, url)) rc = 1; http_cleanup(); -- cgit v1.2.1 From 8e29f6a07e321a24f1d4f579817f5a8a43cdac05 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 27 Jul 2006 23:56:22 +0200 Subject: Teach git-http-fetch the --stdin switch Speeds up things quite a lot when fetching tags with Cogito. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- http-fetch.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index bc67db1ad..1aad39b4d 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -36,6 +36,8 @@ enum XML_Status { #define PREV_BUF_SIZE 4096 #define RANGE_HEADER_SIZE 30 +static int commits_on_stdin = 0; + static int got_alternates = -1; static int corrupt_object_found = 0; @@ -43,7 +45,7 @@ static struct curl_slist *no_pragma_header; struct alt_base { - char *base; + const char *base; int path_len; int got_indices; struct packed_git *packs; @@ -81,7 +83,7 @@ struct object_request }; struct alternates_request { - char *base; + const char *base; char *url; struct buffer *buffer; struct active_request_slot *slot; @@ -142,7 +144,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, return size; } -static void fetch_alternates(char *base); +static void fetch_alternates(const char *base); static void process_object_response(void *callback_data); @@ -507,7 +509,7 @@ static void process_alternates_response(void *callback_data) (struct alternates_request *)callback_data; struct active_request_slot *slot = alt_req->slot; struct alt_base *tail = alt; - char *base = alt_req->base; + const char *base = alt_req->base; static const char null_byte = '\0'; char *data; int i = 0; @@ -612,7 +614,7 @@ static void process_alternates_response(void *callback_data) got_alternates = 1; } -static void fetch_alternates(char *base) +static void fetch_alternates(const char *base) { struct buffer buffer; char *url; @@ -1185,7 +1187,7 @@ int fetch_ref(char *ref, unsigned char *sha1) char *url; char hex[42]; struct buffer buffer; - char *base = alt->base; + const char *base = alt->base; struct active_request_slot *slot; struct slot_results results; buffer.size = 41; @@ -1214,11 +1216,12 @@ int fetch_ref(char *ref, unsigned char *sha1) return 0; } -int main(int argc, char **argv) +int main(int argc, const char **argv) { - const char *write_ref = NULL; - char *commit_id; - char *url; + int commits; + const char **write_ref = NULL; + char **commit_id; + const char *url; char *path; int arg = 1; int rc = 0; @@ -1238,19 +1241,26 @@ int main(int argc, char **argv) } else if (argv[arg][1] == 'v') { get_verbosely = 1; } else if (argv[arg][1] == 'w') { - write_ref = argv[arg + 1]; + write_ref = &argv[arg + 1]; arg++; } else if (!strcmp(argv[arg], "--recover")) { get_recover = 1; + } else if (!strcmp(argv[arg], "--stdin")) { + commits_on_stdin = 1; } arg++; } - if (argc < arg + 2) { - usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url"); + if (argc < arg + 2 - commits_on_stdin) { + usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); return 1; } - commit_id = argv[arg]; - url = argv[arg + 1]; + if (commits_on_stdin) { + commits = pull_targets_stdin(&commit_id, &write_ref); + } else { + commit_id = (char **) &argv[arg++]; + commits = 1; + } + url = argv[arg]; http_init(); @@ -1268,13 +1278,16 @@ int main(int argc, char **argv) alt->path_len = strlen(path); } - if (pull(1, &commit_id, &write_ref, url)) + if (pull(commits, commit_id, write_ref, url)) rc = 1; http_cleanup(); curl_slist_free_all(no_pragma_header); + if (commits_on_stdin) + pull_targets_free(commits, commit_id, write_ref); + if (corrupt_object_found) { fprintf(stderr, "Some loose object were found to be corrupt, but they might be just\n" -- cgit v1.2.1 From 19c4588178463cd8f0745d430159ab806d9fa6e4 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 4 Aug 2006 22:01:34 +0100 Subject: commit walkers: setup_ident() to record correct committer in ref-log. The function pull() in fetch.c calls write_ref_sha1(), which may need committer identity to update the ref-log, so they need to call setup_ident() before calling git_config() function. Acked-by: Shawn Pearce Signed-off-by: Junio C Hamano --- http-fetch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 1aad39b4d..36af3e5b9 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1226,6 +1226,7 @@ int main(int argc, const char **argv) int arg = 1; int rc = 0; + setup_ident(); setup_git_directory(); git_config(git_default_config); -- cgit v1.2.1 From 83a2b841d6b90e6f4b797df40ed3a105364574b6 Mon Sep 17 00:00:00 2001 From: Rene Scharfe Date: Thu, 10 Aug 2006 17:02:30 +0200 Subject: Add has_extension() The little helper has_extension() documents through its name what we are trying to do and makes sure we don't forget the underrun check. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 36af3e5b9..6ea39f058 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -870,7 +870,7 @@ static void process_ls_pack(struct remote_ls_ctx *ls) if (strlen(ls->dentry_name) == 63 && !strncmp(ls->dentry_name, "objects/pack/pack-", 18) && - !strncmp(ls->dentry_name+58, ".pack", 5)) { + has_extension(ls->dentry_name, 63, ".pack")) { get_sha1_hex(ls->dentry_name + 18, sha1); setup_index(ls->repo, sha1); } -- cgit v1.2.1 From 5bb1cda5f73988963e7470f3cd75a380751f6d99 Mon Sep 17 00:00:00 2001 From: Rene Scharfe Date: Fri, 11 Aug 2006 14:01:45 +0200 Subject: drop length argument of has_extension As Fredrik points out the current interface of has_extension() is potentially confusing. Its parameters include both a nul-terminated string and a length-limited string. This patch drops the length argument, requiring two nul-terminated strings; all callsites are updated. I checked that all of them indeed provide nul-terminated strings. Filenames need to be nul-terminated anyway if they are to be passed to open() etc. The performance penalty of the additional strlen() is negligible compared to the system calls which inevitably surround has_extension() calls. Additionally, change has_extension() to use size_t inside instead of int, as that is the exact type strlen() returns and memcmp() expects. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 6ea39f058..de5fc44e6 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -870,7 +870,7 @@ static void process_ls_pack(struct remote_ls_ctx *ls) if (strlen(ls->dentry_name) == 63 && !strncmp(ls->dentry_name, "objects/pack/pack-", 18) && - has_extension(ls->dentry_name, 63, ".pack")) { + has_extension(ls->dentry_name, ".pack")) { get_sha1_hex(ls->dentry_name + 18, sha1); setup_index(ls->repo, sha1); } -- cgit v1.2.1 From 96f1e58f524fac8607cfc38896b365b6e8365b51 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 15 Aug 2006 10:23:48 -0700 Subject: remove unnecessary initializations [jc: I needed to hand merge the changes to the updated codebase, so the result needs to be checked.] Signed-off-by: David Rientjes Signed-off-by: Junio C Hamano --- http-fetch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index de5fc44e6..7f07d2a96 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -36,10 +36,10 @@ enum XML_Status { #define PREV_BUF_SIZE 4096 #define RANGE_HEADER_SIZE 30 -static int commits_on_stdin = 0; +static int commits_on_stdin; static int got_alternates = -1; -static int corrupt_object_found = 0; +static int corrupt_object_found; static struct curl_slist *no_pragma_header; @@ -52,7 +52,7 @@ struct alt_base struct alt_base *next; }; -static struct alt_base *alt = NULL; +static struct alt_base *alt; enum object_request_state { WAITING, @@ -114,7 +114,7 @@ struct remote_ls_ctx }; #endif -static struct object_request *object_queue_head = NULL; +static struct object_request *object_queue_head; static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, void *data) -- cgit v1.2.1 From a89fccd28197fa179828c8596791ff16e2268d20 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Thu, 17 Aug 2006 11:54:57 -0700 Subject: Do not use memcmp(sha1_1, sha1_2, 20) with hardcoded length. Introduces global inline: hashcmp(const unsigned char *sha1, const unsigned char *sha2) Uses memcmp for comparison and returns the result based on the length of the hash name (a future runtime decision). Acked-by: Alex Riesen Signed-off-by: David Rientjes Signed-off-by: Junio C Hamano --- http-fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 7f07d2a96..d1f74b443 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -301,7 +301,7 @@ static void finish_object_request(struct object_request *obj_req) unlink(obj_req->tmpfile); return; } - if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) { + if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { unlink(obj_req->tmpfile); return; } @@ -1070,7 +1070,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) int ret = 0; struct object_request *obj_req = object_queue_head; - while (obj_req != NULL && memcmp(obj_req->sha1, sha1, 20)) + while (obj_req != NULL && hashcmp(obj_req->sha1, sha1)) obj_req = obj_req->next; if (obj_req == NULL) return error("Couldn't find request for %s in the queue", hex); @@ -1109,7 +1109,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) } else if (obj_req->zret != Z_STREAM_END) { corrupt_object_found++; ret = error("File %s (%s) corrupt", hex, obj_req->url); - } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) { + } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { ret = error("File %s has bad hash", hex); } else if (obj_req->rename < 0) { ret = error("unable to write sha1 filename %s", -- cgit v1.2.1 From e702496e434a160f798447b95b9cea3cd138c140 Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Wed, 23 Aug 2006 02:49:00 -0400 Subject: Convert memcpy(a,b,20) to hashcpy(a,b). This abstracts away the size of the hash values when copying them from memory location to memory location, much as the introduction of hashcmp abstracted away hash value comparsion. A few call sites were using char* rather than unsigned char* so I added the cast rather than open hashcpy to be void*. This is a reasonable tradeoff as most call sites already use unsigned char* and the existing hashcmp is also declared to be unsigned char*. [jc: Splitted the patch to "master" part, to be followed by a patch for merge-recursive.c which is not in "master" yet. Fixed the cast in the latter hunk to combine-diff.c which was wrong in the original. Also converted ones left-over in combine-diff.c, diff-lib.c and upload-pack.c ] Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index d1f74b443..7619b338f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -393,7 +393,7 @@ void prefetch(unsigned char *sha1) char *filename = sha1_file_name(sha1); newreq = xmalloc(sizeof(*newreq)); - memcpy(newreq->sha1, sha1, 20); + hashcpy(newreq->sha1, sha1); newreq->repo = alt; newreq->url = NULL; newreq->local = -1; -- cgit v1.2.1 From 4cac42b1324951579036a9d3ac403f5c2c3eeed8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 27 Aug 2006 21:19:39 -0700 Subject: free(NULL) is perfectly valid. Jonas noticed some places say "if (X) free(X)" which is totally unnecessary. Signed-off-by: Junio C Hamano --- http-fetch.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 7619b338f..6806f3678 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -696,10 +696,8 @@ xml_start_tag(void *userData, const char *name, const char **atts) strcat(ctx->name, "."); strcat(ctx->name, c); - if (ctx->cdata) { - free(ctx->cdata); - ctx->cdata = NULL; - } + free(ctx->cdata); + ctx->cdata = NULL; ctx->userFunc(ctx, 0); } @@ -726,8 +724,7 @@ static void xml_cdata(void *userData, const XML_Char *s, int len) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - if (ctx->cdata) - free(ctx->cdata); + free(ctx->cdata); ctx->cdata = xmalloc(len + 1); strlcpy(ctx->cdata, s, len + 1); } @@ -765,9 +762,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed) ls->dentry_flags |= IS_DIR; } } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) { - if (ls->dentry_name) { - free(ls->dentry_name); - } + free(ls->dentry_name); ls->dentry_name = NULL; ls->dentry_flags = 0; } -- cgit v1.2.1 From 9befac470b4cfad529032dbcffcb71242ec71f91 Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Sat, 2 Sep 2006 00:16:31 -0400 Subject: Replace uses of strdup with xstrdup. Like xmalloc and xrealloc xstrdup dies with a useful message if the native strdup() implementation returns NULL rather than a valid pointer. I just tried to use xstrdup in new code and found it to be missing. However I expected it to be present as xmalloc and xrealloc are already commonly used throughout the code. [jc: removed the part that deals with last_XXX, which I am finding more and more dubious these days.] Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 6806f3678..fac17607b 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -787,7 +787,7 @@ static int remote_ls(struct alt_base *repo, const char *path, int flags, ls.flags = flags; ls.repo = repo; - ls.path = strdup(path); + ls.path = xstrdup(path); ls.dentry_name = NULL; ls.dentry_flags = 0; ls.userData = userData; -- cgit v1.2.1 From 5df1e0d05cc42aeef9bf2fce243375fb6dac2121 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 12 Sep 2006 23:53:27 -0700 Subject: http-fetch: fix alternates handling. Fetch over http from a repository that uses alternates to borrow from neighbouring repositories were quite broken, apparently for some time now. We parse input and count bytes to allocate the new buffer, and when we copy into that buffer we know exactly how many bytes we want to copy from where. Using strlcpy for it was simply stupid, and the code forgot to take it into account that strlcpy terminated the string with NUL. Signed-off-by: Junio C Hamano --- http-fetch.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index fac17607b..a113bb8c4 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -559,9 +559,36 @@ static void process_alternates_response(void *callback_data) char *target = NULL; char *path; if (data[i] == '/') { - serverlen = strchr(base + 8, '/') - base; - okay = 1; + /* This counts + * http://git.host/pub/scm/linux.git/ + * -----------here^ + * so memcpy(dst, base, serverlen) will + * copy up to "...git.host". + */ + const char *colon_ss = strstr(base,"://"); + if (colon_ss) { + serverlen = (strchr(colon_ss + 3, '/') + - base); + okay = 1; + } } else if (!memcmp(data + i, "../", 3)) { + /* Relative URL; chop the corresponding + * number of subpath from base (and ../ + * from data), and concatenate the result. + * + * The code first drops ../ from data, and + * then drops one ../ from data and one path + * from base. IOW, one extra ../ is dropped + * from data than path is dropped from base. + * + * This is not wrong. The alternate in + * http://git.host/pub/scm/linux.git/ + * to borrow from + * http://git.host/pub/scm/linus.git/ + * is ../../linus.git/objects/. You need + * two ../../ to borrow from your direct + * neighbour. + */ i += 3; serverlen = strlen(base); while (i + 2 < posn && @@ -583,11 +610,13 @@ static void process_alternates_response(void *callback_data) okay = 1; } } - /* skip 'objects' at end */ + /* skip "objects\n" at end */ if (okay) { target = xmalloc(serverlen + posn - i - 6); - strlcpy(target, base, serverlen); - strlcpy(target + serverlen, data + i, posn - i - 6); + memcpy(target, base, serverlen); + memcpy(target + serverlen, data + i, + posn - i - 7); + target[serverlen + posn - i - 7] = 0; if (get_verbosely) fprintf(stderr, "Also look at %s\n", target); -- cgit v1.2.1 From be4a015b0fed2bd96e509f45b80b63db056b9ca9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Sep 2006 10:58:20 -0700 Subject: http-fetch.c: consolidate code to detect missing fetch target At a handful places we check two error codes from curl library to see if the file we asked was missing from the remote (e.g. we asked for a loose object when it is in a pack) to decide what to do next. This consolidates the check into a single function. NOTE: the original did not check for HTTP_RETURNED_ERROR when error code is 404, but this version does to make sure 404 is from HTTP and not some other protcol. Signed-off-by: Junio C Hamano --- http-fetch.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index a113bb8c4..98cf52db4 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -144,6 +144,17 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, return size; } +static int missing__target(int code, int result) +{ + return /* file:// URL -- do we ever use one??? */ + (result == CURLE_FILE_COULDNT_READ_FILE) || + /* http:// and https:// URL */ + (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) + ; +} + +#define missing_target(a) missing__target((a)->http_code, (a)->curl_result) + static void fetch_alternates(const char *base); static void process_object_response(void *callback_data); @@ -323,8 +334,7 @@ static void process_object_response(void *callback_data) obj_req->state = COMPLETE; /* Use alternates if necessary */ - if (obj_req->http_code == 404 || - obj_req->curl_result == CURLE_FILE_COULDNT_READ_FILE) { + if (missing_target(obj_req)) { fetch_alternates(alt->base); if (obj_req->repo->next != NULL) { obj_req->repo = @@ -537,8 +547,7 @@ static void process_alternates_response(void *callback_data) return; } } else if (slot->curl_result != CURLE_OK) { - if (slot->http_code != 404 && - slot->curl_result != CURLE_FILE_COULDNT_READ_FILE) { + if (!missing_target(slot)) { got_alternates = -1; return; } @@ -941,8 +950,7 @@ static int fetch_indices(struct alt_base *repo) if (start_active_slot(slot)) { run_active_slot(slot); if (results.curl_result != CURLE_OK) { - if (results.http_code == 404 || - results.curl_result == CURLE_FILE_COULDNT_READ_FILE) { + if (missing_target(&results)) { repo->got_indices = 1; free(buffer.buffer); return 0; @@ -1123,8 +1131,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) ret = error("Request for %s aborted", hex); } else if (obj_req->curl_result != CURLE_OK && obj_req->http_code != 416) { - if (obj_req->http_code == 404 || - obj_req->curl_result == CURLE_FILE_COULDNT_READ_FILE) + if (missing_target(obj_req)) ret = -1; /* Be silent, it is probably in a pack. */ else ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)", -- cgit v1.2.1 From 4adffc7b54e8c5d8fc7510007dd9b8235a67430f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Sep 2006 11:06:02 -0700 Subject: Add ftp:// protocol support for git-http-fetch Based on Sasha Khapyorsky's patch but adjusted to the refactored "missing target" detection code. It might have been better if the program were called git-url-fetch but it is too late now ;-). Signed-off-by: Junio C Hamano --- http-fetch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 98cf52db4..bc74f30f7 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -149,7 +149,9 @@ static int missing__target(int code, int result) return /* file:// URL -- do we ever use one??? */ (result == CURLE_FILE_COULDNT_READ_FILE) || /* http:// and https:// URL */ - (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) + (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) || + /* ftp:// URL */ + (code == 550 && result == CURLE_FTP_COULDNT_RETR_FILE) ; } -- cgit v1.2.1 From adc446fe5d5f6dc1fb5edeaa9aa016ef94e70da1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 8 Oct 2006 12:56:19 -0700 Subject: Add WEBDAV timeout to http-fetch. Sean writes: > On Sat, 07 Oct 2006 21:52:02 -0700 > Junio C Hamano wrote: > >> Using DAV, if it works with the server, has the advantage of not >> having to keep objects/info/packs up-to-date from repository >> owner's point of view. But the repository owner ends up keeping >> up-to-date as a side effect of keeping info/refs up-to-date >> anyway (as I do not see a code to read that information over >> DAV), so there is no point doing this over DAV in practice. >> >> Perhaps we should remove call to remote_ls() from >> fetch_indices() unconditionally, not just protected with >> NO_EXPAT and be done with it? > > That makes a lot of sense. A server really has to always provide > a objects/info/packs anyway, just to be fetchable today by clients > that are compiled with NO_EXPAT. And even for an isolated group where everybody knows that everybody else runs DAV-enabled clients, they need info/refs prepared for ls-remote and git-fetch script, which means you will run update-server-info to keep objects/info/packs up to date. Nick, do you see holes in my logic? -- >8 -- http-fetch.c: drop remote_ls() While doing remote_ls() over DAV potentially allows the server side not to keep objects/info/pack up-to-date, misconfigured or buggy servers can silently ignore or not to respond to DAV requests and makes the client hang. The server side (unfortunately) needs to run git-update-server-info even if remote_ls() removes the need to keep objects/info/pack file up-to-date, because the caller of git-http-fetch (git-fetch) and other clients that interact with the repository (e.g. git-ls-remote) need to read from info/refs file (there is no code to make that unnecessary by using DAV yet). Perhaps the right solution in the longer-term is to make info/refs also unnecessary by using DAV, and we would want to resurrect the code this patch removes when we do so, but let's drop remote_ls() implementation for now. It is causing problems without really helping anything yet. git will keep it for us until we need it next time. Signed-off-by: Junio C Hamano --- http-fetch.c | 257 ----------------------------------------------------------- 1 file changed, 257 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index bc74f30f7..396552da0 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -4,35 +4,6 @@ #include "fetch.h" #include "http.h" -#ifndef NO_EXPAT -#include - -/* Definitions for DAV requests */ -#define DAV_PROPFIND "PROPFIND" -#define DAV_PROPFIND_RESP ".multistatus.response" -#define DAV_PROPFIND_NAME ".multistatus.response.href" -#define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection" -#define PROPFIND_ALL_REQUEST "\n\n\n" - -/* Definitions for processing XML DAV responses */ -#ifndef XML_STATUS_OK -enum XML_Status { - XML_STATUS_OK = 1, - XML_STATUS_ERROR = 0 -}; -#define XML_STATUS_OK 1 -#define XML_STATUS_ERROR 0 -#endif - -/* Flags that control remote_ls processing */ -#define PROCESS_FILES (1u << 0) -#define PROCESS_DIRS (1u << 1) -#define RECURSIVE (1u << 2) - -/* Flags that remote_ls passes to callback functions */ -#define IS_DIR (1u << 0) -#endif - #define PREV_BUF_SIZE 4096 #define RANGE_HEADER_SIZE 30 @@ -90,30 +61,6 @@ struct alternates_request { int http_specific; }; -#ifndef NO_EXPAT -struct xml_ctx -{ - char *name; - int len; - char *cdata; - void (*userFunc)(struct xml_ctx *ctx, int tag_closed); - void *userData; -}; - -struct remote_ls_ctx -{ - struct alt_base *repo; - char *path; - void (*userFunc)(struct remote_ls_ctx *ls); - void *userData; - int flags; - char *dentry_name; - int dentry_flags; - int rc; - struct remote_ls_ctx *parent; -}; -#endif - static struct object_request *object_queue_head; static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, @@ -714,204 +661,6 @@ static void fetch_alternates(const char *base) free(url); } -#ifndef NO_EXPAT -static void -xml_start_tag(void *userData, const char *name, const char **atts) -{ - struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = strchr(name, ':'); - int new_len; - - if (c == NULL) - c = name; - else - c++; - - new_len = strlen(ctx->name) + strlen(c) + 2; - - if (new_len > ctx->len) { - ctx->name = xrealloc(ctx->name, new_len); - ctx->len = new_len; - } - strcat(ctx->name, "."); - strcat(ctx->name, c); - - free(ctx->cdata); - ctx->cdata = NULL; - - ctx->userFunc(ctx, 0); -} - -static void -xml_end_tag(void *userData, const char *name) -{ - struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = strchr(name, ':'); - char *ep; - - ctx->userFunc(ctx, 1); - - if (c == NULL) - c = name; - else - c++; - - ep = ctx->name + strlen(ctx->name) - strlen(c) - 1; - *ep = 0; -} - -static void -xml_cdata(void *userData, const XML_Char *s, int len) -{ - struct xml_ctx *ctx = (struct xml_ctx *)userData; - free(ctx->cdata); - ctx->cdata = xmalloc(len + 1); - strlcpy(ctx->cdata, s, len + 1); -} - -static int remote_ls(struct alt_base *repo, const char *path, int flags, - void (*userFunc)(struct remote_ls_ctx *ls), - void *userData); - -static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed) -{ - struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData; - - if (tag_closed) { - if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) { - if (ls->dentry_flags & IS_DIR) { - if (ls->flags & PROCESS_DIRS) { - ls->userFunc(ls); - } - if (strcmp(ls->dentry_name, ls->path) && - ls->flags & RECURSIVE) { - ls->rc = remote_ls(ls->repo, - ls->dentry_name, - ls->flags, - ls->userFunc, - ls->userData); - } - } else if (ls->flags & PROCESS_FILES) { - ls->userFunc(ls); - } - } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) { - ls->dentry_name = xmalloc(strlen(ctx->cdata) - - ls->repo->path_len + 1); - strcpy(ls->dentry_name, ctx->cdata + ls->repo->path_len); - } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) { - ls->dentry_flags |= IS_DIR; - } - } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) { - free(ls->dentry_name); - ls->dentry_name = NULL; - ls->dentry_flags = 0; - } -} - -static int remote_ls(struct alt_base *repo, const char *path, int flags, - void (*userFunc)(struct remote_ls_ctx *ls), - void *userData) -{ - char *url = xmalloc(strlen(repo->base) + strlen(path) + 1); - struct active_request_slot *slot; - struct slot_results results; - struct buffer in_buffer; - struct buffer out_buffer; - char *in_data; - char *out_data; - XML_Parser parser = XML_ParserCreate(NULL); - enum XML_Status result; - struct curl_slist *dav_headers = NULL; - struct xml_ctx ctx; - struct remote_ls_ctx ls; - - ls.flags = flags; - ls.repo = repo; - ls.path = xstrdup(path); - ls.dentry_name = NULL; - ls.dentry_flags = 0; - ls.userData = userData; - ls.userFunc = userFunc; - ls.rc = 0; - - sprintf(url, "%s%s", repo->base, path); - - out_buffer.size = strlen(PROPFIND_ALL_REQUEST); - out_data = xmalloc(out_buffer.size + 1); - snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST); - out_buffer.posn = 0; - out_buffer.buffer = out_data; - - in_buffer.size = 4096; - in_data = xmalloc(in_buffer.size); - in_buffer.posn = 0; - in_buffer.buffer = in_data; - - dav_headers = curl_slist_append(dav_headers, "Depth: 1"); - dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); - - slot = get_active_slot(); - slot->results = &results; - curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer); - curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size); - curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer); - curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1); - curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); - - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result == CURLE_OK) { - ctx.name = xcalloc(10, 1); - ctx.len = 0; - ctx.cdata = NULL; - ctx.userFunc = handle_remote_ls_ctx; - ctx.userData = &ls; - XML_SetUserData(parser, &ctx); - XML_SetElementHandler(parser, xml_start_tag, - xml_end_tag); - XML_SetCharacterDataHandler(parser, xml_cdata); - result = XML_Parse(parser, in_buffer.buffer, - in_buffer.posn, 1); - free(ctx.name); - - if (result != XML_STATUS_OK) { - ls.rc = error("XML error: %s", - XML_ErrorString( - XML_GetErrorCode(parser))); - } - } else { - ls.rc = -1; - } - } else { - ls.rc = error("Unable to start PROPFIND request"); - } - - free(ls.path); - free(url); - free(out_data); - free(in_buffer.buffer); - curl_slist_free_all(dav_headers); - - return ls.rc; -} - -static void process_ls_pack(struct remote_ls_ctx *ls) -{ - unsigned char sha1[20]; - - if (strlen(ls->dentry_name) == 63 && - !strncmp(ls->dentry_name, "objects/pack/pack-", 18) && - has_extension(ls->dentry_name, ".pack")) { - get_sha1_hex(ls->dentry_name + 18, sha1); - setup_index(ls->repo, sha1); - } -} -#endif - static int fetch_indices(struct alt_base *repo) { unsigned char sha1[20]; @@ -934,12 +683,6 @@ static int fetch_indices(struct alt_base *repo) if (get_verbosely) fprintf(stderr, "Getting pack list for %s\n", repo->base); -#ifndef NO_EXPAT - if (remote_ls(repo, "objects/pack/", PROCESS_FILES, - process_ls_pack, NULL) == 0) - return 0; -#endif - url = xmalloc(strlen(repo->base) + 21); sprintf(url, "%s/objects/info/packs", repo->base); -- cgit v1.2.1 From 93d26e4cb9cec2eb8abb4f37e6dda2c86fcceeac Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Mon, 8 Jan 2007 15:58:08 +0000 Subject: short i/o: fix calls to read to use xread or read_in_full We have a number of badly checked read() calls. Often we are expecting read() to read exactly the size we requested or fail, this fails to handle interrupts or short reads. Add a read_in_full() providing those semantics. Otherwise we at a minimum need to check for EINTR and EAGAIN, where this is appropriate use xread(). Signed-off-by: Andy Whitcroft Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 396552da0..50a3b005a 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -175,7 +175,7 @@ static void start_object_request(struct object_request *obj_req) prevlocal = open(prevfile, O_RDONLY); if (prevlocal != -1) { do { - prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE); + prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE); if (prev_read>0) { if (fwrite_sha1_file(prev_buf, 1, -- cgit v1.2.1 From 93822c2239a336e5cb583549071c59202ef6c5b2 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Mon, 8 Jan 2007 15:58:23 +0000 Subject: short i/o: fix calls to write to use xwrite or write_in_full We have a number of badly checked write() calls. Often we are expecting write() to write exactly the size we requested or fail, this fails to handle interrupts or short writes. Switch to using the new write_in_full(). Otherwise we at a minimum need to check for EINTR and EAGAIN, where this is appropriate use xwrite(). Note, the changes to config handling are much larger and handled in the next patch in the sequence. Signed-off-by: Andy Whitcroft Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 50a3b005a..fe8cd7bdc 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -71,7 +71,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, int posn = 0; struct object_request *obj_req = (struct object_request *)data; do { - ssize_t retval = write(obj_req->local, + ssize_t retval = xwrite(obj_req->local, (char *) ptr + posn, size - posn); if (retval < 0) return posn; -- cgit v1.2.1 From 1c23d794bfa3b9f3e03b18bb7e542615a924dbe3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 9 Jan 2007 20:04:52 -0500 Subject: Don't die in git-http-fetch when fetching packs. My sp/mmap changes to pack-check.c modified the function such that it expects packed_git.pack_size to be populated with the total bytecount of the packfile by the caller. But that isn't the case for packs obtained by git-http-fetch as pack_size was not initialized before being accessed. This caused verify_pack to think it had 2^32-21 bytes available when the downloaded pack perhaps was only 305 bytes in length. The use_pack function then later dies with "offset beyond end of packfile" when computing the overall file checksum. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http-fetch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index fe8cd7bdc..67dfb0a03 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -809,6 +809,7 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1) return error("Unable to start request"); } + target->pack_size = ftell(packfile); fclose(packfile); ret = move_temp_to_file(tmpfile, filename); -- cgit v1.2.1 From 01754769ab9bf9ff2fe2b12590e7ee2c7c3448ca Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 28 Jan 2007 00:50:53 -0800 Subject: Don't force everybody to call setup_ident(). Back when only handful commands that created commit and tag were the only users of committer identity information, it made sense to explicitly call setup_ident() to pre-fill the default value from the gecos information. But it is much simpler for programs to make the call automatic when get_ident() is called these days, since many more programs want to use the information when updating the reflog. Signed-off-by: Junio C Hamano --- http-fetch.c | 1 - 1 file changed, 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 67dfb0a03..efd494a47 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1003,7 +1003,6 @@ int main(int argc, const char **argv) int arg = 1; int rc = 0; - setup_ident(); setup_git_directory(); git_config(git_default_config); -- cgit v1.2.1 From df391b192d285646fe80ca4d3cfe3c0a3beb5989 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 28 Jan 2007 16:33:58 -0800 Subject: git-fsck-objects is now synonym to git-fsck Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index efd494a47..9f790a08e 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1069,7 +1069,7 @@ int main(int argc, const char **argv) fprintf(stderr, "Some loose object were found to be corrupt, but they might be just\n" "a false '404 Not Found' error message sent with incorrect HTTP\n" -"status code. Suggest running git fsck-objects.\n"); +"status code. Suggest running git-fsck.\n"); } return rc; } -- cgit v1.2.1 From cc44c7655fe2dd0cfb46e841156634fe622df397 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 20 Feb 2007 01:53:29 -0800 Subject: Mechanical conversion to use prefixcmp() This mechanically converts strncmp() to use prefixcmp(), but only when the parameters match specific patterns, so that they can be verified easily. Leftover from this will be fixed in a separate step, including idiotic conversions like if (!strncmp("foo", arg, 3)) => if (!(-prefixcmp(arg, "foo"))) This was done by using this script in px.perl #!/usr/bin/perl -i.bak -p if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) { s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|; } if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) { s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|; } and running: $ git grep -l strncmp -- '*.c' | xargs perl px.perl Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 9f790a08e..d9a4561c8 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -717,7 +717,7 @@ static int fetch_indices(struct alt_base *repo) case 'P': i++; if (i + 52 <= buffer.posn && - !strncmp(data + i, " pack-", 6) && + !prefixcmp(data + i, " pack-") && !strncmp(data + i + 46, ".pack\n", 6)) { get_sha1_hex(data + i + 6, sha1); setup_index(repo, sha1); -- cgit v1.2.1 From 1968d77dd632a9a9e5c6f5681649e5e65ed13088 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 20 Feb 2007 01:55:07 -0800 Subject: prefixcmp(): fix-up leftover strncmp(). There were instances of strncmp() that were formatted improperly (e.g. whitespace around parameter before closing parenthesis) that caused the earlier mechanical conversion step to miss them. This step cleans them up. Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index d9a4561c8..e6cd11db7 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -718,7 +718,7 @@ static int fetch_indices(struct alt_base *repo) i++; if (i + 52 <= buffer.posn && !prefixcmp(data + i, " pack-") && - !strncmp(data + i + 46, ".pack\n", 6)) { + !prefixcmp(data + i + 46, ".pack\n")) { get_sha1_hex(data + i + 6, sha1); setup_index(repo, sha1); i += 51; -- cgit v1.2.1 From 2afea3bcd2a2b3327d7e8bdabc9aebd6bef24c6e Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 28 Mar 2007 09:46:15 +0000 Subject: http-fetch: don't use double-slash as directory separator in URLs Please see http://bugs.debian.org/409887 http-fetch expected the URL given at the command line to have a trailing slash anyway, and then added '/objects...' when requesting objects files from the http server. Now it doesn't require the trailing slash in anymore, and strips trailing slashes if given nonetheless. Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- http-fetch.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index e6cd11db7..58b77a7a1 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -16,7 +16,7 @@ static struct curl_slist *no_pragma_header; struct alt_base { - const char *base; + char *base; int path_len; int got_indices; struct packed_git *packs; @@ -158,12 +158,12 @@ static void start_object_request(struct object_request *obj_req) SHA1_Init(&obj_req->c); - url = xmalloc(strlen(obj_req->repo->base) + 50); - obj_req->url = xmalloc(strlen(obj_req->repo->base) + 50); + url = xmalloc(strlen(obj_req->repo->base) + 51); + obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); strcpy(url, obj_req->repo->base); posn = url + strlen(obj_req->repo->base); - strcpy(posn, "objects/"); - posn += 8; + strcpy(posn, "/objects/"); + posn += 9; memcpy(posn, hex, 2); posn += 2; *(posn++) = '/'; @@ -938,14 +938,14 @@ static char *quote_ref_url(const char *base, const char *ref) int len, baselen, ch; baselen = strlen(base); - len = baselen + 6; /* "refs/" + NUL */ + len = baselen + 7; /* "/refs/" + NUL */ for (cp = ref; (ch = *cp) != 0; cp++, len++) if (needs_quote(ch)) len += 2; /* extra two hex plus replacement % */ qref = xmalloc(len); memcpy(qref, base, baselen); - memcpy(qref + baselen, "refs/", 5); - for (cp = ref, dp = qref + baselen + 5; (ch = *cp) != 0; cp++) { + memcpy(qref + baselen, "/refs/", 6); + for (cp = ref, dp = qref + baselen + 6; (ch = *cp) != 0; cp++) { if (needs_quote(ch)) { *dp++ = '%'; *dp++ = hex((ch >> 4) & 0xF); @@ -1044,7 +1044,10 @@ int main(int argc, const char **argv) no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); alt = xmalloc(sizeof(*alt)); - alt->base = url; + alt->base = xmalloc(strlen(url) + 1); + strcpy(alt->base, url); + for (path = alt->base + strlen(alt->base) - 1; *path == '/'; --path) + *path = 0; alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; -- cgit v1.2.1 From 9c880b3ea56a7ff2f66dcf12eb2351f0f51a54ef Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 28 Mar 2007 09:47:35 +0000 Subject: http-fetch: remove path_len from struct alt_base, it was computed but never used Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- http-fetch.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 58b77a7a1..557b40322 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -17,7 +17,6 @@ static struct curl_slist *no_pragma_header; struct alt_base { char *base; - int path_len; int got_indices; struct packed_git *packs; struct alt_base *next; @@ -515,7 +514,6 @@ static void process_alternates_response(void *callback_data) int serverlen = 0; struct alt_base *newalt; char *target = NULL; - char *path; if (data[i] == '/') { /* This counts * http://git.host/pub/scm/linux.git/ @@ -583,12 +581,6 @@ static void process_alternates_response(void *callback_data) newalt->base = target; newalt->got_indices = 0; newalt->packs = NULL; - path = strstr(target, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - newalt->path_len = strlen(path); - } while (tail->next != NULL) tail = tail->next; @@ -999,7 +991,7 @@ int main(int argc, const char **argv) const char **write_ref = NULL; char **commit_id; const char *url; - char *path; + char *s; int arg = 1; int rc = 0; @@ -1046,17 +1038,11 @@ int main(int argc, const char **argv) alt = xmalloc(sizeof(*alt)); alt->base = xmalloc(strlen(url) + 1); strcpy(alt->base, url); - for (path = alt->base + strlen(alt->base) - 1; *path == '/'; --path) - *path = 0; + for (s = alt->base + strlen(alt->base) - 1; *s == '/'; --s) + *s = 0; alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; - path = strstr(url, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - alt->path_len = strlen(path); - } if (pull(commits, commit_id, write_ref, url)) rc = 1; -- cgit v1.2.1 From b5da24679ec73f458988523dce9dd17b4e9b0e02 Mon Sep 17 00:00:00 2001 From: Dana How Date: Thu, 5 Apr 2007 12:05:57 -0700 Subject: Fix lseek(2) calls with args 2 and 3 swapped Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 557b40322..09baedc18 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -198,7 +198,7 @@ static void start_object_request(struct object_request *obj_req) SHA1_Init(&obj_req->c); if (prev_posn>0) { prev_posn = 0; - lseek(obj_req->local, SEEK_SET, 0); + lseek(obj_req->local, 0, SEEK_SET); ftruncate(obj_req->local, 0); } } -- cgit v1.2.1 From a6080a0a44d5ead84db3dabbbc80e82df838533d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 7 Jun 2007 00:04:01 -0700 Subject: War on whitespace This uses "git-apply --whitespace=strip" to fix whitespace errors that have crept in to our source files over time. There are a few files that need to have trailing whitespaces (most notably, test vectors). The results still passes the test, and build result in Documentation/ area is unchanged. Signed-off-by: Junio C Hamano --- http-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 09baedc18..202fae0ba 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -828,7 +828,7 @@ static void abort_object_request(struct object_request *obj_req) } unlink(obj_req->tmpfile); if (obj_req->slot) { - release_active_slot(obj_req->slot); + release_active_slot(obj_req->slot); obj_req->slot = NULL; } release_object_request(obj_req); -- cgit v1.2.1 From 45c1741235a1fbd54484fa1c67ea68569dcfa23e Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:28 -0400 Subject: Refactor http.h USE_CURL_MULTI fill_active_slots(). This removes all of the boilerplate and http-internal stuff from fill_active_slots() and makes it easy to turn into a callback. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 202fae0ba..e9b9f307f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -317,30 +317,21 @@ static void release_object_request(struct object_request *obj_req) } #ifdef USE_CURL_MULTI -void fill_active_slots(void) +int fill_active_slot(void) { - struct object_request *obj_req = object_queue_head; - struct active_request_slot *slot = active_queue_head; - int num_transfers; + struct object_request *obj_req; - while (active_requests < max_requests && obj_req != NULL) { + for (obj_req = object_queue_head; obj_req; obj_req = obj_req->next) { if (obj_req->state == WAITING) { if (has_sha1_file(obj_req->sha1)) obj_req->state = COMPLETE; - else + else { start_object_request(obj_req); - curl_multi_perform(curlm, &num_transfers); - } - obj_req = obj_req->next; - } - - while (slot != NULL) { - if (!slot->in_use && slot->curl != NULL) { - curl_easy_cleanup(slot->curl); - slot->curl = NULL; + return 1; + } } - slot = slot->next; } + return 0; } #endif -- cgit v1.2.1 From fc57b6aaa5bc59ecbe0c052b98196a93b35760a5 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:34 -0400 Subject: Make function to refill http queue a callback This eliminates the last function provided by the code using http.h as a global symbol, so it should be possible to have multiple programs using http.h in the same executable, and it also adds an argument to that callback, so that info can be passed into the callback without being global. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index e9b9f307f..7786110ff 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -317,7 +317,7 @@ static void release_object_request(struct object_request *obj_req) } #ifdef USE_CURL_MULTI -int fill_active_slot(void) +static int fill_active_slot(void *unused) { struct object_request *obj_req; @@ -1035,6 +1035,10 @@ int main(int argc, const char **argv) alt->packs = NULL; alt->next = NULL; +#ifdef USE_CURL_MULTI + add_fill_function(NULL, fill_active_slot); +#endif + if (pull(commits, commit_id, write_ref, url)) rc = 1; -- cgit v1.2.1 From 30ae764b1e11f10b5fca723a876a0f3de3ca11ab Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:45 -0400 Subject: Modularize commit-walker This turns the extern functions to be provided by the backend into a struct of pointers, renames the functions to be more namespace-friendly, and updates http-fetch to this interface. It removes the unused include from http-push.c. It makes git-http-fetch a builtin (with the implementation a separate file, accessible directly). Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 1059 ---------------------------------------------------------- 1 file changed, 1059 deletions(-) delete mode 100644 http-fetch.c (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c deleted file mode 100644 index 7786110ff..000000000 --- a/http-fetch.c +++ /dev/null @@ -1,1059 +0,0 @@ -#include "cache.h" -#include "commit.h" -#include "pack.h" -#include "fetch.h" -#include "http.h" - -#define PREV_BUF_SIZE 4096 -#define RANGE_HEADER_SIZE 30 - -static int commits_on_stdin; - -static int got_alternates = -1; -static int corrupt_object_found; - -static struct curl_slist *no_pragma_header; - -struct alt_base -{ - char *base; - int got_indices; - struct packed_git *packs; - struct alt_base *next; -}; - -static struct alt_base *alt; - -enum object_request_state { - WAITING, - ABORTED, - ACTIVE, - COMPLETE, -}; - -struct object_request -{ - unsigned char sha1[20]; - struct alt_base *repo; - char *url; - char filename[PATH_MAX]; - char tmpfile[PATH_MAX]; - int local; - enum object_request_state state; - CURLcode curl_result; - char errorstr[CURL_ERROR_SIZE]; - long http_code; - unsigned char real_sha1[20]; - SHA_CTX c; - z_stream stream; - int zret; - int rename; - struct active_request_slot *slot; - struct object_request *next; -}; - -struct alternates_request { - const char *base; - char *url; - struct buffer *buffer; - struct active_request_slot *slot; - int http_specific; -}; - -static struct object_request *object_queue_head; - -static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, - void *data) -{ - unsigned char expn[4096]; - size_t size = eltsize * nmemb; - int posn = 0; - struct object_request *obj_req = (struct object_request *)data; - do { - ssize_t retval = xwrite(obj_req->local, - (char *) ptr + posn, size - posn); - if (retval < 0) - return posn; - posn += retval; - } while (posn < size); - - obj_req->stream.avail_in = size; - obj_req->stream.next_in = ptr; - do { - obj_req->stream.next_out = expn; - obj_req->stream.avail_out = sizeof(expn); - obj_req->zret = inflate(&obj_req->stream, Z_SYNC_FLUSH); - SHA1_Update(&obj_req->c, expn, - sizeof(expn) - obj_req->stream.avail_out); - } while (obj_req->stream.avail_in && obj_req->zret == Z_OK); - data_received++; - return size; -} - -static int missing__target(int code, int result) -{ - return /* file:// URL -- do we ever use one??? */ - (result == CURLE_FILE_COULDNT_READ_FILE) || - /* http:// and https:// URL */ - (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) || - /* ftp:// URL */ - (code == 550 && result == CURLE_FTP_COULDNT_RETR_FILE) - ; -} - -#define missing_target(a) missing__target((a)->http_code, (a)->curl_result) - -static void fetch_alternates(const char *base); - -static void process_object_response(void *callback_data); - -static void start_object_request(struct object_request *obj_req) -{ - char *hex = sha1_to_hex(obj_req->sha1); - char prevfile[PATH_MAX]; - char *url; - char *posn; - int prevlocal; - unsigned char prev_buf[PREV_BUF_SIZE]; - ssize_t prev_read = 0; - long prev_posn = 0; - char range[RANGE_HEADER_SIZE]; - struct curl_slist *range_header = NULL; - struct active_request_slot *slot; - - snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename); - unlink(prevfile); - rename(obj_req->tmpfile, prevfile); - unlink(obj_req->tmpfile); - - if (obj_req->local != -1) - error("fd leakage in start: %d", obj_req->local); - obj_req->local = open(obj_req->tmpfile, - O_WRONLY | O_CREAT | O_EXCL, 0666); - /* This could have failed due to the "lazy directory creation"; - * try to mkdir the last path component. - */ - if (obj_req->local < 0 && errno == ENOENT) { - char *dir = strrchr(obj_req->tmpfile, '/'); - if (dir) { - *dir = 0; - mkdir(obj_req->tmpfile, 0777); - *dir = '/'; - } - obj_req->local = open(obj_req->tmpfile, - O_WRONLY | O_CREAT | O_EXCL, 0666); - } - - if (obj_req->local < 0) { - obj_req->state = ABORTED; - error("Couldn't create temporary file %s for %s: %s", - obj_req->tmpfile, obj_req->filename, strerror(errno)); - return; - } - - memset(&obj_req->stream, 0, sizeof(obj_req->stream)); - - inflateInit(&obj_req->stream); - - SHA1_Init(&obj_req->c); - - url = xmalloc(strlen(obj_req->repo->base) + 51); - obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); - strcpy(url, obj_req->repo->base); - posn = url + strlen(obj_req->repo->base); - strcpy(posn, "/objects/"); - posn += 9; - memcpy(posn, hex, 2); - posn += 2; - *(posn++) = '/'; - strcpy(posn, hex + 2); - strcpy(obj_req->url, url); - - /* If a previous temp file is present, process what was already - fetched. */ - prevlocal = open(prevfile, O_RDONLY); - if (prevlocal != -1) { - do { - prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE); - if (prev_read>0) { - if (fwrite_sha1_file(prev_buf, - 1, - prev_read, - obj_req) == prev_read) { - prev_posn += prev_read; - } else { - prev_read = -1; - } - } - } while (prev_read > 0); - close(prevlocal); - } - unlink(prevfile); - - /* Reset inflate/SHA1 if there was an error reading the previous temp - file; also rewind to the beginning of the local file. */ - if (prev_read == -1) { - memset(&obj_req->stream, 0, sizeof(obj_req->stream)); - inflateInit(&obj_req->stream); - SHA1_Init(&obj_req->c); - if (prev_posn>0) { - prev_posn = 0; - lseek(obj_req->local, 0, SEEK_SET); - ftruncate(obj_req->local, 0); - } - } - - slot = get_active_slot(); - slot->callback_func = process_object_response; - slot->callback_data = obj_req; - obj_req->slot = slot; - - curl_easy_setopt(slot->curl, CURLOPT_FILE, obj_req); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); - curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, obj_req->errorstr); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); - - /* If we have successfully processed data from a previous fetch - attempt, only fetch the data we don't already have. */ - if (prev_posn>0) { - if (get_verbosely) - fprintf(stderr, - "Resuming fetch of object %s at byte %ld\n", - hex, prev_posn); - sprintf(range, "Range: bytes=%ld-", prev_posn); - range_header = curl_slist_append(range_header, range); - curl_easy_setopt(slot->curl, - CURLOPT_HTTPHEADER, range_header); - } - - /* Try to get the request started, abort the request on error */ - obj_req->state = ACTIVE; - if (!start_active_slot(slot)) { - obj_req->state = ABORTED; - obj_req->slot = NULL; - close(obj_req->local); obj_req->local = -1; - free(obj_req->url); - return; - } -} - -static void finish_object_request(struct object_request *obj_req) -{ - struct stat st; - - fchmod(obj_req->local, 0444); - close(obj_req->local); obj_req->local = -1; - - if (obj_req->http_code == 416) { - fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n"); - } else if (obj_req->curl_result != CURLE_OK) { - if (stat(obj_req->tmpfile, &st) == 0) - if (st.st_size == 0) - unlink(obj_req->tmpfile); - return; - } - - inflateEnd(&obj_req->stream); - SHA1_Final(obj_req->real_sha1, &obj_req->c); - if (obj_req->zret != Z_STREAM_END) { - unlink(obj_req->tmpfile); - return; - } - if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { - unlink(obj_req->tmpfile); - return; - } - obj_req->rename = - move_temp_to_file(obj_req->tmpfile, obj_req->filename); - - if (obj_req->rename == 0) - pull_say("got %s\n", sha1_to_hex(obj_req->sha1)); -} - -static void process_object_response(void *callback_data) -{ - struct object_request *obj_req = - (struct object_request *)callback_data; - - obj_req->curl_result = obj_req->slot->curl_result; - obj_req->http_code = obj_req->slot->http_code; - obj_req->slot = NULL; - obj_req->state = COMPLETE; - - /* Use alternates if necessary */ - if (missing_target(obj_req)) { - fetch_alternates(alt->base); - if (obj_req->repo->next != NULL) { - obj_req->repo = - obj_req->repo->next; - close(obj_req->local); - obj_req->local = -1; - start_object_request(obj_req); - return; - } - } - - finish_object_request(obj_req); -} - -static void release_object_request(struct object_request *obj_req) -{ - struct object_request *entry = object_queue_head; - - if (obj_req->local != -1) - error("fd leakage in release: %d", obj_req->local); - if (obj_req == object_queue_head) { - object_queue_head = obj_req->next; - } else { - while (entry->next != NULL && entry->next != obj_req) - entry = entry->next; - if (entry->next == obj_req) - entry->next = entry->next->next; - } - - free(obj_req->url); - free(obj_req); -} - -#ifdef USE_CURL_MULTI -static int fill_active_slot(void *unused) -{ - struct object_request *obj_req; - - for (obj_req = object_queue_head; obj_req; obj_req = obj_req->next) { - if (obj_req->state == WAITING) { - if (has_sha1_file(obj_req->sha1)) - obj_req->state = COMPLETE; - else { - start_object_request(obj_req); - return 1; - } - } - } - return 0; -} -#endif - -void prefetch(unsigned char *sha1) -{ - struct object_request *newreq; - struct object_request *tail; - char *filename = sha1_file_name(sha1); - - newreq = xmalloc(sizeof(*newreq)); - hashcpy(newreq->sha1, sha1); - newreq->repo = alt; - newreq->url = NULL; - newreq->local = -1; - newreq->state = WAITING; - snprintf(newreq->filename, sizeof(newreq->filename), "%s", filename); - snprintf(newreq->tmpfile, sizeof(newreq->tmpfile), - "%s.temp", filename); - newreq->slot = NULL; - newreq->next = NULL; - - if (object_queue_head == NULL) { - object_queue_head = newreq; - } else { - tail = object_queue_head; - while (tail->next != NULL) { - tail = tail->next; - } - tail->next = newreq; - } - -#ifdef USE_CURL_MULTI - fill_active_slots(); - step_active_slots(); -#endif -} - -static int fetch_index(struct alt_base *repo, unsigned char *sha1) -{ - char *hex = sha1_to_hex(sha1); - char *filename; - char *url; - char tmpfile[PATH_MAX]; - long prev_posn = 0; - char range[RANGE_HEADER_SIZE]; - struct curl_slist *range_header = NULL; - - FILE *indexfile; - struct active_request_slot *slot; - struct slot_results results; - - if (has_pack_index(sha1)) - return 0; - - if (get_verbosely) - fprintf(stderr, "Getting index for pack %s\n", hex); - - url = xmalloc(strlen(repo->base) + 64); - sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex); - - filename = sha1_pack_index_name(sha1); - snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); - indexfile = fopen(tmpfile, "a"); - if (!indexfile) - return error("Unable to open local file %s for pack index", - filename); - - slot = get_active_slot(); - slot->results = &results; - curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); - slot->local = indexfile; - - /* If there is data present from a previous transfer attempt, - resume where it left off */ - prev_posn = ftell(indexfile); - if (prev_posn>0) { - if (get_verbosely) - fprintf(stderr, - "Resuming fetch of index for pack %s at byte %ld\n", - hex, prev_posn); - sprintf(range, "Range: bytes=%ld-", prev_posn); - range_header = curl_slist_append(range_header, range); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header); - } - - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result != CURLE_OK) { - fclose(indexfile); - return error("Unable to get pack index %s\n%s", url, - curl_errorstr); - } - } else { - fclose(indexfile); - return error("Unable to start request"); - } - - fclose(indexfile); - - return move_temp_to_file(tmpfile, filename); -} - -static int setup_index(struct alt_base *repo, unsigned char *sha1) -{ - struct packed_git *new_pack; - if (has_pack_file(sha1)) - return 0; /* don't list this as something we can get */ - - if (fetch_index(repo, sha1)) - return -1; - - new_pack = parse_pack_index(sha1); - new_pack->next = repo->packs; - repo->packs = new_pack; - return 0; -} - -static void process_alternates_response(void *callback_data) -{ - struct alternates_request *alt_req = - (struct alternates_request *)callback_data; - struct active_request_slot *slot = alt_req->slot; - struct alt_base *tail = alt; - const char *base = alt_req->base; - static const char null_byte = '\0'; - char *data; - int i = 0; - - if (alt_req->http_specific) { - if (slot->curl_result != CURLE_OK || - !alt_req->buffer->posn) { - - /* Try reusing the slot to get non-http alternates */ - alt_req->http_specific = 0; - sprintf(alt_req->url, "%s/objects/info/alternates", - base); - curl_easy_setopt(slot->curl, CURLOPT_URL, - alt_req->url); - active_requests++; - slot->in_use = 1; - if (slot->finished != NULL) - (*slot->finished) = 0; - if (!start_active_slot(slot)) { - got_alternates = -1; - slot->in_use = 0; - if (slot->finished != NULL) - (*slot->finished) = 1; - } - return; - } - } else if (slot->curl_result != CURLE_OK) { - if (!missing_target(slot)) { - got_alternates = -1; - return; - } - } - - fwrite_buffer(&null_byte, 1, 1, alt_req->buffer); - alt_req->buffer->posn--; - data = alt_req->buffer->buffer; - - while (i < alt_req->buffer->posn) { - int posn = i; - while (posn < alt_req->buffer->posn && data[posn] != '\n') - posn++; - if (data[posn] == '\n') { - int okay = 0; - int serverlen = 0; - struct alt_base *newalt; - char *target = NULL; - if (data[i] == '/') { - /* This counts - * http://git.host/pub/scm/linux.git/ - * -----------here^ - * so memcpy(dst, base, serverlen) will - * copy up to "...git.host". - */ - const char *colon_ss = strstr(base,"://"); - if (colon_ss) { - serverlen = (strchr(colon_ss + 3, '/') - - base); - okay = 1; - } - } else if (!memcmp(data + i, "../", 3)) { - /* Relative URL; chop the corresponding - * number of subpath from base (and ../ - * from data), and concatenate the result. - * - * The code first drops ../ from data, and - * then drops one ../ from data and one path - * from base. IOW, one extra ../ is dropped - * from data than path is dropped from base. - * - * This is not wrong. The alternate in - * http://git.host/pub/scm/linux.git/ - * to borrow from - * http://git.host/pub/scm/linus.git/ - * is ../../linus.git/objects/. You need - * two ../../ to borrow from your direct - * neighbour. - */ - i += 3; - serverlen = strlen(base); - while (i + 2 < posn && - !memcmp(data + i, "../", 3)) { - do { - serverlen--; - } while (serverlen && - base[serverlen - 1] != '/'); - i += 3; - } - /* If the server got removed, give up. */ - okay = strchr(base, ':') - base + 3 < - serverlen; - } else if (alt_req->http_specific) { - char *colon = strchr(data + i, ':'); - char *slash = strchr(data + i, '/'); - if (colon && slash && colon < data + posn && - slash < data + posn && colon < slash) { - okay = 1; - } - } - /* skip "objects\n" at end */ - if (okay) { - target = xmalloc(serverlen + posn - i - 6); - memcpy(target, base, serverlen); - memcpy(target + serverlen, data + i, - posn - i - 7); - target[serverlen + posn - i - 7] = 0; - if (get_verbosely) - fprintf(stderr, - "Also look at %s\n", target); - newalt = xmalloc(sizeof(*newalt)); - newalt->next = NULL; - newalt->base = target; - newalt->got_indices = 0; - newalt->packs = NULL; - - while (tail->next != NULL) - tail = tail->next; - tail->next = newalt; - } - } - i = posn + 1; - } - - got_alternates = 1; -} - -static void fetch_alternates(const char *base) -{ - struct buffer buffer; - char *url; - char *data; - struct active_request_slot *slot; - struct alternates_request alt_req; - - /* If another request has already started fetching alternates, - wait for them to arrive and return to processing this request's - curl message */ -#ifdef USE_CURL_MULTI - while (got_alternates == 0) { - step_active_slots(); - } -#endif - - /* Nothing to do if they've already been fetched */ - if (got_alternates == 1) - return; - - /* Start the fetch */ - got_alternates = 0; - - data = xmalloc(4096); - buffer.size = 4096; - buffer.posn = 0; - buffer.buffer = data; - - if (get_verbosely) - fprintf(stderr, "Getting alternates list for %s\n", base); - - url = xmalloc(strlen(base) + 31); - sprintf(url, "%s/objects/info/http-alternates", base); - - /* Use a callback to process the result, since another request - may fail and need to have alternates loaded before continuing */ - slot = get_active_slot(); - slot->callback_func = process_alternates_response; - slot->callback_data = &alt_req; - - curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - - alt_req.base = base; - alt_req.url = url; - alt_req.buffer = &buffer; - alt_req.http_specific = 1; - alt_req.slot = slot; - - if (start_active_slot(slot)) - run_active_slot(slot); - else - got_alternates = -1; - - free(data); - free(url); -} - -static int fetch_indices(struct alt_base *repo) -{ - unsigned char sha1[20]; - char *url; - struct buffer buffer; - char *data; - int i = 0; - - struct active_request_slot *slot; - struct slot_results results; - - if (repo->got_indices) - return 0; - - data = xmalloc(4096); - buffer.size = 4096; - buffer.posn = 0; - buffer.buffer = data; - - if (get_verbosely) - fprintf(stderr, "Getting pack list for %s\n", repo->base); - - url = xmalloc(strlen(repo->base) + 21); - sprintf(url, "%s/objects/info/packs", repo->base); - - slot = get_active_slot(); - slot->results = &results; - curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL); - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result != CURLE_OK) { - if (missing_target(&results)) { - repo->got_indices = 1; - free(buffer.buffer); - return 0; - } else { - repo->got_indices = 0; - free(buffer.buffer); - return error("%s", curl_errorstr); - } - } - } else { - repo->got_indices = 0; - free(buffer.buffer); - return error("Unable to start request"); - } - - data = buffer.buffer; - while (i < buffer.posn) { - switch (data[i]) { - case 'P': - i++; - if (i + 52 <= buffer.posn && - !prefixcmp(data + i, " pack-") && - !prefixcmp(data + i + 46, ".pack\n")) { - get_sha1_hex(data + i + 6, sha1); - setup_index(repo, sha1); - i += 51; - break; - } - default: - while (i < buffer.posn && data[i] != '\n') - i++; - } - i++; - } - - free(buffer.buffer); - repo->got_indices = 1; - return 0; -} - -static int fetch_pack(struct alt_base *repo, unsigned char *sha1) -{ - char *url; - struct packed_git *target; - struct packed_git **lst; - FILE *packfile; - char *filename; - char tmpfile[PATH_MAX]; - int ret; - long prev_posn = 0; - char range[RANGE_HEADER_SIZE]; - struct curl_slist *range_header = NULL; - - struct active_request_slot *slot; - struct slot_results results; - - if (fetch_indices(repo)) - return -1; - target = find_sha1_pack(sha1, repo->packs); - if (!target) - return -1; - - if (get_verbosely) { - fprintf(stderr, "Getting pack %s\n", - sha1_to_hex(target->sha1)); - fprintf(stderr, " which contains %s\n", - sha1_to_hex(sha1)); - } - - url = xmalloc(strlen(repo->base) + 65); - sprintf(url, "%s/objects/pack/pack-%s.pack", - repo->base, sha1_to_hex(target->sha1)); - - filename = sha1_pack_name(target->sha1); - snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); - packfile = fopen(tmpfile, "a"); - if (!packfile) - return error("Unable to open local file %s for pack", - filename); - - slot = get_active_slot(); - slot->results = &results; - curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); - slot->local = packfile; - - /* If there is data present from a previous transfer attempt, - resume where it left off */ - prev_posn = ftell(packfile); - if (prev_posn>0) { - if (get_verbosely) - fprintf(stderr, - "Resuming fetch of pack %s at byte %ld\n", - sha1_to_hex(target->sha1), prev_posn); - sprintf(range, "Range: bytes=%ld-", prev_posn); - range_header = curl_slist_append(range_header, range); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header); - } - - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result != CURLE_OK) { - fclose(packfile); - return error("Unable to get pack file %s\n%s", url, - curl_errorstr); - } - } else { - fclose(packfile); - return error("Unable to start request"); - } - - target->pack_size = ftell(packfile); - fclose(packfile); - - ret = move_temp_to_file(tmpfile, filename); - if (ret) - return ret; - - lst = &repo->packs; - while (*lst != target) - lst = &((*lst)->next); - *lst = (*lst)->next; - - if (verify_pack(target, 0)) - return -1; - install_packed_git(target); - - return 0; -} - -static void abort_object_request(struct object_request *obj_req) -{ - if (obj_req->local >= 0) { - close(obj_req->local); - obj_req->local = -1; - } - unlink(obj_req->tmpfile); - if (obj_req->slot) { - release_active_slot(obj_req->slot); - obj_req->slot = NULL; - } - release_object_request(obj_req); -} - -static int fetch_object(struct alt_base *repo, unsigned char *sha1) -{ - char *hex = sha1_to_hex(sha1); - int ret = 0; - struct object_request *obj_req = object_queue_head; - - while (obj_req != NULL && hashcmp(obj_req->sha1, sha1)) - obj_req = obj_req->next; - if (obj_req == NULL) - return error("Couldn't find request for %s in the queue", hex); - - if (has_sha1_file(obj_req->sha1)) { - abort_object_request(obj_req); - return 0; - } - -#ifdef USE_CURL_MULTI - while (obj_req->state == WAITING) { - step_active_slots(); - } -#else - start_object_request(obj_req); -#endif - - while (obj_req->state == ACTIVE) { - run_active_slot(obj_req->slot); - } - if (obj_req->local != -1) { - close(obj_req->local); obj_req->local = -1; - } - - if (obj_req->state == ABORTED) { - ret = error("Request for %s aborted", hex); - } else if (obj_req->curl_result != CURLE_OK && - obj_req->http_code != 416) { - if (missing_target(obj_req)) - ret = -1; /* Be silent, it is probably in a pack. */ - else - ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)", - obj_req->errorstr, obj_req->curl_result, - obj_req->http_code, hex); - } else if (obj_req->zret != Z_STREAM_END) { - corrupt_object_found++; - ret = error("File %s (%s) corrupt", hex, obj_req->url); - } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { - ret = error("File %s has bad hash", hex); - } else if (obj_req->rename < 0) { - ret = error("unable to write sha1 filename %s", - obj_req->filename); - } - - release_object_request(obj_req); - return ret; -} - -int fetch(unsigned char *sha1) -{ - struct alt_base *altbase = alt; - - if (!fetch_object(altbase, sha1)) - return 0; - while (altbase) { - if (!fetch_pack(altbase, sha1)) - return 0; - fetch_alternates(alt->base); - altbase = altbase->next; - } - return error("Unable to find %s under %s", sha1_to_hex(sha1), - alt->base); -} - -static inline int needs_quote(int ch) -{ - if (((ch >= 'A') && (ch <= 'Z')) - || ((ch >= 'a') && (ch <= 'z')) - || ((ch >= '0') && (ch <= '9')) - || (ch == '/') - || (ch == '-') - || (ch == '.')) - return 0; - return 1; -} - -static inline int hex(int v) -{ - if (v < 10) return '0' + v; - else return 'A' + v - 10; -} - -static char *quote_ref_url(const char *base, const char *ref) -{ - const char *cp; - char *dp, *qref; - int len, baselen, ch; - - baselen = strlen(base); - len = baselen + 7; /* "/refs/" + NUL */ - for (cp = ref; (ch = *cp) != 0; cp++, len++) - if (needs_quote(ch)) - len += 2; /* extra two hex plus replacement % */ - qref = xmalloc(len); - memcpy(qref, base, baselen); - memcpy(qref + baselen, "/refs/", 6); - for (cp = ref, dp = qref + baselen + 6; (ch = *cp) != 0; cp++) { - if (needs_quote(ch)) { - *dp++ = '%'; - *dp++ = hex((ch >> 4) & 0xF); - *dp++ = hex(ch & 0xF); - } - else - *dp++ = ch; - } - *dp = 0; - - return qref; -} - -int fetch_ref(char *ref, unsigned char *sha1) -{ - char *url; - char hex[42]; - struct buffer buffer; - const char *base = alt->base; - struct active_request_slot *slot; - struct slot_results results; - buffer.size = 41; - buffer.posn = 0; - buffer.buffer = hex; - hex[41] = '\0'; - - url = quote_ref_url(base, ref); - slot = get_active_slot(); - slot->results = &results; - curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result != CURLE_OK) - return error("Couldn't get %s for %s\n%s", - url, ref, curl_errorstr); - } else { - return error("Unable to start request"); - } - - hex[40] = '\0'; - get_sha1_hex(hex, sha1); - return 0; -} - -int main(int argc, const char **argv) -{ - int commits; - const char **write_ref = NULL; - char **commit_id; - const char *url; - char *s; - int arg = 1; - int rc = 0; - - setup_git_directory(); - git_config(git_default_config); - - while (arg < argc && argv[arg][0] == '-') { - if (argv[arg][1] == 't') { - get_tree = 1; - } else if (argv[arg][1] == 'c') { - get_history = 1; - } else if (argv[arg][1] == 'a') { - get_all = 1; - get_tree = 1; - get_history = 1; - } else if (argv[arg][1] == 'v') { - get_verbosely = 1; - } else if (argv[arg][1] == 'w') { - write_ref = &argv[arg + 1]; - arg++; - } else if (!strcmp(argv[arg], "--recover")) { - get_recover = 1; - } else if (!strcmp(argv[arg], "--stdin")) { - commits_on_stdin = 1; - } - arg++; - } - if (argc < arg + 2 - commits_on_stdin) { - usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); - return 1; - } - if (commits_on_stdin) { - commits = pull_targets_stdin(&commit_id, &write_ref); - } else { - commit_id = (char **) &argv[arg++]; - commits = 1; - } - url = argv[arg]; - - http_init(); - - no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); - - alt = xmalloc(sizeof(*alt)); - alt->base = xmalloc(strlen(url) + 1); - strcpy(alt->base, url); - for (s = alt->base + strlen(alt->base) - 1; *s == '/'; --s) - *s = 0; - alt->got_indices = 0; - alt->packs = NULL; - alt->next = NULL; - -#ifdef USE_CURL_MULTI - add_fill_function(NULL, fill_active_slot); -#endif - - if (pull(commits, commit_id, write_ref, url)) - rc = 1; - - http_cleanup(); - - curl_slist_free_all(no_pragma_header); - - if (commits_on_stdin) - pull_targets_free(commits, commit_id, write_ref); - - if (corrupt_object_found) { - fprintf(stderr, -"Some loose object were found to be corrupt, but they might be just\n" -"a false '404 Not Found' error message sent with incorrect HTTP\n" -"status code. Suggest running git-fsck.\n"); - } - return rc; -} -- cgit v1.2.1 From 1088261f6fc90324014b5306cca4171987da85ce Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 5 Aug 2009 01:01:59 -0400 Subject: git-http-fetch: not a builtin This splits up git-http-fetch so that it isn't built-in. It also removes the general dependency on curl, because it is no longer used by any built-in code. Because they are no longer LIB_OBJS, add LIB_H to the dependencies of http-related object files, and remove http.h from the dependencies of transport.o Signed-off-by: Linus Torvalds Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 http-fetch.c (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c new file mode 100644 index 000000000..e8f44babd --- /dev/null +++ b/http-fetch.c @@ -0,0 +1,89 @@ +#include "cache.h" +#include "walker.h" + +int main(int argc, const char **argv) +{ + const char *prefix; + struct walker *walker; + int commits_on_stdin = 0; + int commits; + const char **write_ref = NULL; + char **commit_id; + const char *url; + char *rewritten_url = NULL; + int arg = 1; + int rc = 0; + int get_tree = 0; + int get_history = 0; + int get_all = 0; + int get_verbosely = 0; + int get_recover = 0; + + prefix = setup_git_directory(); + + git_config(git_default_config, NULL); + + while (arg < argc && argv[arg][0] == '-') { + if (argv[arg][1] == 't') { + get_tree = 1; + } else if (argv[arg][1] == 'c') { + get_history = 1; + } else if (argv[arg][1] == 'a') { + get_all = 1; + get_tree = 1; + get_history = 1; + } else if (argv[arg][1] == 'v') { + get_verbosely = 1; + } else if (argv[arg][1] == 'w') { + write_ref = &argv[arg + 1]; + arg++; + } else if (!strcmp(argv[arg], "--recover")) { + get_recover = 1; + } else if (!strcmp(argv[arg], "--stdin")) { + commits_on_stdin = 1; + } + arg++; + } + if (argc < arg + 2 - commits_on_stdin) { + usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); + return 1; + } + if (commits_on_stdin) { + commits = walker_targets_stdin(&commit_id, &write_ref); + } else { + commit_id = (char **) &argv[arg++]; + commits = 1; + } + url = argv[arg]; + if (url && url[strlen(url)-1] != '/') { + rewritten_url = xmalloc(strlen(url)+2); + strcpy(rewritten_url, url); + strcat(rewritten_url, "/"); + url = rewritten_url; + } + + walker = get_http_walker(url, NULL); + walker->get_tree = get_tree; + walker->get_history = get_history; + walker->get_all = get_all; + walker->get_verbosely = get_verbosely; + walker->get_recover = get_recover; + + rc = walker_fetch(walker, commits, commit_id, write_ref, url); + + if (commits_on_stdin) + walker_targets_free(commits, commit_id, write_ref); + + if (walker->corrupt_object_found) { + fprintf(stderr, +"Some loose object were found to be corrupt, but they might be just\n" +"a false '404 Not Found' error message sent with incorrect HTTP\n" +"status code. Suggest running 'git fsck'.\n"); + } + + walker_free(walker); + + free(rewritten_url); + + return rc; +} -- cgit v1.2.1 From f01d74960363736caaf4d98d39555e99bdc72c25 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Mon, 9 Nov 2009 09:05:00 -0600 Subject: http-fetch: add missing initialization of argv0_path According to c6dfb39 (remote-curl: add missing initialization of argv0_path, 2009-10-13), programs with "main" must call this to work correctly on MinGW. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- http-fetch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index e8f44babd..88f7dc884 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "exec_cmd.h" #include "walker.h" int main(int argc, const char **argv) @@ -19,8 +20,8 @@ int main(int argc, const char **argv) int get_verbosely = 0; int get_recover = 0; + git_extract_argv0_path(argv[0]); prefix = setup_git_directory(); - git_config(git_default_config, NULL); while (arg < argc && argv[arg][0] == '-') { -- cgit v1.2.1 From 616f86d71325da1ce692f8e878fe066758f88554 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Mon, 9 Nov 2009 09:04:59 -0600 Subject: Let 'git http-fetch -h' show usage outside any git repository Delay search for a git directory until option parsing has finished. None of the functions used in option parsing look for or read any files other than stdin, so this is safe. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- http-fetch.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 88f7dc884..ffd0ad7e2 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -2,6 +2,9 @@ #include "exec_cmd.h" #include "walker.h" +static const char http_fetch_usage[] = "git http-fetch " +"[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"; + int main(int argc, const char **argv) { const char *prefix; @@ -21,8 +24,6 @@ int main(int argc, const char **argv) int get_recover = 0; git_extract_argv0_path(argv[0]); - prefix = setup_git_directory(); - git_config(git_default_config, NULL); while (arg < argc && argv[arg][0] == '-') { if (argv[arg][1] == 't') { @@ -38,6 +39,8 @@ int main(int argc, const char **argv) } else if (argv[arg][1] == 'w') { write_ref = &argv[arg + 1]; arg++; + } else if (argv[arg][1] == 'h') { + usage(http_fetch_usage); } else if (!strcmp(argv[arg], "--recover")) { get_recover = 1; } else if (!strcmp(argv[arg], "--stdin")) { @@ -45,10 +48,8 @@ int main(int argc, const char **argv) } arg++; } - if (argc < arg + 2 - commits_on_stdin) { - usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); - return 1; - } + if (argc != arg + 2 - commits_on_stdin) + usage(http_fetch_usage); if (commits_on_stdin) { commits = walker_targets_stdin(&commit_id, &write_ref); } else { @@ -56,6 +57,11 @@ int main(int argc, const char **argv) commits = 1; } url = argv[arg]; + + prefix = setup_git_directory(); + + git_config(git_default_config, NULL); + if (url && url[strlen(url)-1] != '/') { rewritten_url = xmalloc(strlen(url)+2); strcpy(rewritten_url, url); -- cgit v1.2.1 From 888692b733b3109874bb570bb0680e93287ed338 Mon Sep 17 00:00:00 2001 From: Tay Ray Chuan Date: Tue, 2 Mar 2010 18:49:29 +0800 Subject: http: init and cleanup separately from http-walker Previously, all our http operations were done with http-walker. With the new remote-curl helper, we find ourselves using http methods outside of http-walker - for example, fetching info/refs. Accomodate this by separating http_init() and http_cleanup() invocations from http-walker. Signed-off-by: Tay Ray Chuan Signed-off-by: Junio C Hamano --- http-fetch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index ffd0ad7e2..762c750d7 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1,5 +1,6 @@ #include "cache.h" #include "exec_cmd.h" +#include "http.h" #include "walker.h" static const char http_fetch_usage[] = "git http-fetch " @@ -69,7 +70,8 @@ int main(int argc, const char **argv) url = rewritten_url; } - walker = get_http_walker(url, NULL); + http_init(NULL); + walker = get_http_walker(url); walker->get_tree = get_tree; walker->get_history = get_history; walker->get_all = get_all; @@ -89,6 +91,7 @@ int main(int argc, const char **argv) } walker_free(walker); + http_cleanup(); free(rewritten_url); -- cgit v1.2.1 From 6f5185bd2d87dff587e4900aa022f6f9bd088f20 Mon Sep 17 00:00:00 2001 From: Tay Ray Chuan Date: Thu, 25 Nov 2010 16:21:10 +0800 Subject: http-fetch: rework url handling Do away with a second url variable, rewritten_url, and make url non-const. This is safe because the functions called with url (ie. get_http_walker() and walker_fetch()) do not modify it (ie. marked with const char *). Also, replace code that adds a trailing slash with a call to str_end_url_with_slash(). Signed-off-by: Tay Ray Chuan Signed-off-by: Junio C Hamano --- http-fetch.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 762c750d7..923904f97 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -14,8 +14,7 @@ int main(int argc, const char **argv) int commits; const char **write_ref = NULL; char **commit_id; - const char *url; - char *rewritten_url = NULL; + char *url = NULL; int arg = 1; int rc = 0; int get_tree = 0; @@ -57,19 +56,14 @@ int main(int argc, const char **argv) commit_id = (char **) &argv[arg++]; commits = 1; } - url = argv[arg]; + + if (argv[arg]) + str_end_url_with_slash(argv[arg], &url); prefix = setup_git_directory(); git_config(git_default_config, NULL); - if (url && url[strlen(url)-1] != '/') { - rewritten_url = xmalloc(strlen(url)+2); - strcpy(rewritten_url, url); - strcat(rewritten_url, "/"); - url = rewritten_url; - } - http_init(NULL); walker = get_http_walker(url); walker->get_tree = get_tree; @@ -93,7 +87,7 @@ int main(int argc, const char **argv) walker_free(walker); http_cleanup(); - free(rewritten_url); + free(url); return rc; } -- cgit v1.2.1 From 13ee1384ef0004bd9fa6e4d2b832b49ce2e8a032 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 27 Mar 2011 20:32:19 -0500 Subject: Fix two unused variable warnings in gcc 4.6 Seen with -Wunused-but-set-variable. Signed-off-by: Dan McGee Signed-off-by: Junio C Hamano --- http-fetch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 923904f97..3af4c71bd 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -8,7 +8,6 @@ static const char http_fetch_usage[] = "git http-fetch " int main(int argc, const char **argv) { - const char *prefix; struct walker *walker; int commits_on_stdin = 0; int commits; @@ -60,7 +59,7 @@ int main(int argc, const char **argv) if (argv[arg]) str_end_url_with_slash(argv[arg], &url); - prefix = setup_git_directory(); + setup_git_directory(); git_config(git_default_config, NULL); -- cgit v1.2.1 From a6c786fce8da4143ea8bb3ab41ce8531192c5126 Mon Sep 17 00:00:00 2001 From: Ben Walton Date: Tue, 23 Aug 2011 20:29:51 -0400 Subject: Mark http-fetch without -a as deprecated As the use of http-fetch without -a can create an object store that is invalid to the point where it cannot even be fsck'd, mark it as deprecated. A future release should change the default and then remove the option entirely. Signed-off-by: Ben Walton Signed-off-by: Junio C Hamano --- http-fetch.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'http-fetch.c') diff --git a/http-fetch.c b/http-fetch.c index 3af4c71bd..8c4c5d222 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -56,6 +56,10 @@ int main(int argc, const char **argv) commits = 1; } + if (get_all == 0) + warning("http-fetch: use without -a is deprecated.\n" + "In a future release, -a will become the default."); + if (argv[arg]) str_end_url_with_slash(argv[arg], &url); -- cgit v1.2.1