diff options
Diffstat (limited to 'http-push.c')
-rw-r--r-- | http-push.c | 149 |
1 files changed, 62 insertions, 87 deletions
diff --git a/http-push.c b/http-push.c index bc94a3f6ab..48f39b7f71 100644 --- a/http-push.c +++ b/http-push.c @@ -10,6 +10,7 @@ #include "remote.h" #include "list-objects.h" #include "sigchain.h" +#include "argv-array.h" #ifdef EXPAT_NEEDS_XMLPARSE_H #include <xmlparse.h> @@ -316,7 +317,6 @@ static void start_fetch_packed(struct transfer_request *request) preq = new_http_pack_request(target, repo->url); if (preq == NULL) { - release_http_pack_request(preq); repo->can_update_info_refs = 0; return; } @@ -362,10 +362,9 @@ static void start_put(struct transfer_request *request) git_zstream stream; unpacked = read_sha1_file(request->obj->sha1, &type, &len); - hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1; + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), len) + 1; /* Set it up */ - memset(&stream, 0, sizeof(stream)); git_deflate_init(&stream, zlib_compression_level); size = git_deflate_bound(&stream, len + hdrlen); strbuf_init(&request->buffer.buf, size); @@ -719,14 +718,10 @@ static int fetch_indices(void) return ret; } -static void one_remote_object(const char *hex) +static void one_remote_object(const unsigned char *sha1) { - unsigned char sha1[20]; struct object *obj; - if (get_sha1_hex(hex, sha1) != 0) - return; - obj = lookup_object(sha1); if (!obj) obj = parse_object(sha1); @@ -767,15 +762,13 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed) if (tag_closed && ctx->cdata) { if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) { - lock->owner = xmalloc(strlen(ctx->cdata) + 1); - strcpy(lock->owner, ctx->cdata); + lock->owner = xstrdup(ctx->cdata); } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) { - if (starts_with(ctx->cdata, "Second-")) - lock->timeout = - strtol(ctx->cdata + 7, NULL, 10); + const char *arg; + if (skip_prefix(ctx->cdata, "Second-", &arg)) + lock->timeout = strtol(arg, NULL, 10); } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) { - lock->token = xmalloc(strlen(ctx->cdata) + 1); - strcpy(lock->token, ctx->cdata); + lock->token = xstrdup(ctx->cdata); git_SHA1_Init(&sha_ctx); git_SHA1_Update(&sha_ctx, lock->token, strlen(lock->token)); @@ -794,21 +787,21 @@ 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; + int old_namelen, new_len; if (c == NULL) c = name; else c++; - new_len = strlen(ctx->name) + strlen(c) + 2; + old_namelen = strlen(ctx->name); + new_len = old_namelen + 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); + xsnprintf(ctx->name + old_namelen, ctx->len - old_namelen, ".%s", c); free(ctx->cdata); ctx->cdata = NULL; @@ -856,8 +849,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout) struct xml_ctx ctx; char *escaped; - url = xmalloc(strlen(repo->url) + strlen(path) + 1); - sprintf(url, "%s%s", repo->url, path); + url = xstrfmt("%s%s", repo->url, path); /* Make sure leading directories exist for the remote ref */ ep = strchr(url + strlen(repo->url) + 1, '/'); @@ -890,7 +882,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout) strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped); free(escaped); - sprintf(timeout_header, "Timeout: Second-%ld", timeout); + xsnprintf(timeout_header, sizeof(timeout_header), "Timeout: Second-%ld", timeout); dav_headers = curl_slist_append(dav_headers, timeout_header); dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); @@ -1020,26 +1012,38 @@ static void remote_ls(const char *path, int flags, void (*userFunc)(struct remote_ls_ctx *ls), void *userData); +/* extract hex from sharded "xx/x{40}" filename */ +static int get_sha1_hex_from_objpath(const char *path, unsigned char *sha1) +{ + char hex[40]; + + if (strlen(path) != 41) + return -1; + + memcpy(hex, path, 2); + path += 2; + path++; /* skip '/' */ + memcpy(hex, path, 38); + + return get_sha1_hex(hex, sha1); +} + static void process_ls_object(struct remote_ls_ctx *ls) { unsigned int *parent = (unsigned int *)ls->userData; - char *path = ls->dentry_name; - char *obj_hex; + const char *path = ls->dentry_name; + unsigned char sha1[20]; if (!strcmp(ls->path, ls->dentry_name) && (ls->flags & IS_DIR)) { remote_dir_exists[*parent] = 1; return; } - if (strlen(path) != 49) + if (!skip_prefix(path, "objects/", &path) || + get_sha1_hex_from_objpath(path, sha1)) return; - path += 8; - obj_hex = xmalloc(strlen(path)); - /* NB: path is not null-terminated, can not use strlcpy here */ - memcpy(obj_hex, path, 2); - strcpy(obj_hex + 2, path + 3); - one_remote_object(obj_hex); - free(obj_hex); + + one_remote_object(sha1); } static void process_ls_ref(struct remote_ls_ctx *ls) @@ -1117,7 +1121,7 @@ static void remote_ls(const char *path, int flags, void (*userFunc)(struct remote_ls_ctx *ls), void *userData) { - char *url = xmalloc(strlen(repo->url) + strlen(path) + 1); + char *url = xstrfmt("%s%s", repo->url, path); struct active_request_slot *slot; struct slot_results results; struct strbuf in_buffer = STRBUF_INIT; @@ -1133,8 +1137,6 @@ static void remote_ls(const char *path, int flags, ls.userData = userData; ls.userFunc = userFunc; - sprintf(url, "%s%s", repo->url, path); - strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST); dav_headers = curl_slist_append(dav_headers, "Depth: 1"); @@ -1458,8 +1460,6 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls) { struct strbuf *buf = (struct strbuf *)ls->userData; struct object *o; - int len; - char *ref_info; struct ref *ref; ref = alloc_ref(ls->dentry_name); @@ -1483,23 +1483,14 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls) return; } - len = strlen(ls->dentry_name) + 42; - ref_info = xcalloc(len + 1, 1); - sprintf(ref_info, "%s %s\n", - sha1_to_hex(ref->old_sha1), ls->dentry_name); - fwrite_buffer(ref_info, 1, len, buf); - free(ref_info); + strbuf_addf(buf, "%s\t%s\n", + sha1_to_hex(ref->old_sha1), ls->dentry_name); if (o->type == OBJ_TAG) { o = deref_tag(o, ls->dentry_name, 0); - if (o) { - len = strlen(ls->dentry_name) + 45; - ref_info = xcalloc(len + 1, 1); - sprintf(ref_info, "%s %s^{}\n", - sha1_to_hex(o->sha1), ls->dentry_name); - fwrite_buffer(ref_info, 1, len, buf); - free(ref_info); - } + if (o) + strbuf_addf(buf, "%s\t%s^{}\n", + sha1_to_hex(o->sha1), ls->dentry_name); } free(ref); } @@ -1536,10 +1527,9 @@ static void update_remote_info_refs(struct remote_lock *lock) static int remote_exists(const char *path) { - char *url = xmalloc(strlen(repo->url) + strlen(path) + 1); + char *url = xstrfmt("%s%s", repo->url, path); int ret; - sprintf(url, "%s%s", repo->url, path); switch (http_get_strbuf(url, NULL, NULL)) { case HTTP_OK: @@ -1559,11 +1549,9 @@ static int remote_exists(const char *path) static void fetch_symref(const char *path, char **symref, unsigned char *sha1) { - char *url; + char *url = xstrfmt("%s%s", repo->url, path); struct strbuf buffer = STRBUF_INIT; - - url = xmalloc(strlen(repo->url) + strlen(path) + 1); - sprintf(url, "%s%s", repo->url, path); + const char *name; if (http_get_strbuf(url, &buffer, NULL) != HTTP_OK) die("Couldn't get %s for remote symref\n%s", url, @@ -1577,9 +1565,12 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) if (buffer.len == 0) return; + /* Cut off trailing newline. */ + strbuf_rtrim(&buffer); + /* If it's a symref, set the refname; otherwise try for a sha1 */ - if (starts_with((char *)buffer.buf, "ref: ")) { - *symref = xmemdupz((char *)buffer.buf + 5, buffer.len - 6); + if (skip_prefix(buffer.buf, "ref: ", &name)) { + *symref = xmemdupz(name, buffer.len - (name - buffer.buf)); } else { get_sha1_hex(buffer.buf, sha1); } @@ -1673,8 +1664,7 @@ static int delete_remote_branch(const char *pattern, int force) fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name); if (dry_run) return 0; - url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1); - sprintf(url, "%s%s", repo->url, remote_ref->name); + url = xstrfmt("%s%s", repo->url, remote_ref->name); slot = get_active_slot(); slot->results = &results; curl_setup_http_get(slot->curl, url, DAV_DELETE); @@ -1866,10 +1856,7 @@ int main(int argc, char **argv) new_refs = 0; for (ref = remote_refs; ref; ref = ref->next) { - char old_hex[60], *new_hex; - const char *commit_argv[5]; - int commit_argc; - char *new_sha1_hex, *old_sha1_hex; + struct argv_array commit_argv = ARGV_ARRAY_INIT; if (!ref->peer_ref) continue; @@ -1923,13 +1910,12 @@ int main(int argc, char **argv) } hashcpy(ref->new_sha1, ref->peer_ref->new_sha1); new_refs++; - strcpy(old_hex, sha1_to_hex(ref->old_sha1)); - new_hex = sha1_to_hex(ref->new_sha1); fprintf(stderr, "updating '%s'", ref->name); if (strcmp(ref->name, ref->peer_ref->name)) fprintf(stderr, " using '%s'", ref->peer_ref->name); - fprintf(stderr, "\n from %s\n to %s\n", old_hex, new_hex); + fprintf(stderr, "\n from %s\n to %s\n", + sha1_to_hex(ref->old_sha1), sha1_to_hex(ref->new_sha1)); if (dry_run) { if (helper_status) printf("ok %s\n", ref->name); @@ -1948,27 +1934,15 @@ int main(int argc, char **argv) } /* Set up revision info for this refspec */ - commit_argc = 3; - new_sha1_hex = xstrdup(sha1_to_hex(ref->new_sha1)); - old_sha1_hex = NULL; - commit_argv[1] = "--objects"; - commit_argv[2] = new_sha1_hex; - if (!push_all && !is_null_sha1(ref->old_sha1)) { - old_sha1_hex = xmalloc(42); - sprintf(old_sha1_hex, "^%s", - sha1_to_hex(ref->old_sha1)); - commit_argv[3] = old_sha1_hex; - commit_argc++; - } - commit_argv[commit_argc] = NULL; + argv_array_push(&commit_argv, ""); /* ignored */ + argv_array_push(&commit_argv, "--objects"); + argv_array_push(&commit_argv, sha1_to_hex(ref->new_sha1)); + if (!push_all && !is_null_sha1(ref->old_sha1)) + argv_array_pushf(&commit_argv, "^%s", + sha1_to_hex(ref->old_sha1)); init_revisions(&revs, setup_git_directory()); - setup_revisions(commit_argc, commit_argv, &revs, NULL); + setup_revisions(commit_argv.argc, commit_argv.argv, &revs, NULL); revs.edge_hint = 0; /* just in case */ - free(new_sha1_hex); - if (old_sha1_hex) { - free(old_sha1_hex); - commit_argv[1] = NULL; - } /* Generate a list of objects that need to be pushed */ pushing = 0; @@ -1997,6 +1971,7 @@ int main(int argc, char **argv) printf("%s %s\n", !rc ? "ok" : "error", ref->name); unlock_remote(ref_lock); check_locks(); + argv_array_clear(&commit_argv); } /* Update remote server info if appropriate */ |