diff options
Diffstat (limited to 'http-push.c')
-rw-r--r-- | http-push.c | 133 |
1 files changed, 64 insertions, 69 deletions
diff --git a/http-push.c b/http-push.c index 822f326..1fe5122 100644 --- a/http-push.c +++ b/http-push.c @@ -1,19 +1,23 @@ -#include "cache.h" +#include "git-compat-util.h" +#include "environment.h" +#include "hex.h" #include "repository.h" #include "commit.h" #include "tag.h" #include "blob.h" #include "http.h" -#include "refs.h" #include "diff.h" #include "revision.h" -#include "exec-cmd.h" #include "remote.h" #include "list-objects.h" +#include "setup.h" #include "sigchain.h" -#include "argv-array.h" +#include "strvec.h" +#include "tree.h" +#include "tree-walk.h" +#include "url.h" #include "packfile.h" -#include "object-store.h" +#include "object-store-ll.h" #include "commit-reach.h" #ifdef EXPAT_NEEDS_XMLPARSE_H @@ -70,10 +74,10 @@ enum XML_Status { #define LOCK_REFRESH 30 /* Remember to update object flag allocation in object.h */ -#define LOCAL (1u<<16) -#define REMOTE (1u<<17) -#define FETCHING (1u<<18) -#define PUSHING (1u<<19) +#define LOCAL (1u<<11) +#define REMOTE (1u<<12) +#define FETCHING (1u<<13) +#define PUSHING (1u<<14) /* We allow "recursive" symbolic refs. Only within reason, though */ #define MAXDEPTH 5 @@ -117,6 +121,7 @@ enum transfer_state { struct transfer_request { struct object *obj; + struct packed_git *target; char *url; char *dest; struct remote_lock *lock; @@ -197,15 +202,13 @@ static void curl_setup_http(CURL *curl, const char *url, const char *custom_req, struct buffer *buffer, curl_write_callback write_fn) { - curl_easy_setopt(curl, CURLOPT_PUT, 1); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_INFILE, buffer); curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len); curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer); -#ifndef NO_CURL_IOCTL - curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer); - curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer); -#endif + curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer); + curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); @@ -248,15 +251,13 @@ static void process_response(void *callback_data) finish_request(request); } -#ifdef USE_CURL_MULTI - static void start_fetch_loose(struct transfer_request *request) { struct active_request_slot *slot; struct http_object_request *obj_req; obj_req = new_http_object_request(repo->url, &request->obj->oid); - if (obj_req == NULL) { + if (!obj_req) { request->state = ABORTED; return; } @@ -298,7 +299,6 @@ static void start_mkcol(struct transfer_request *request) FREE_AND_NULL(request->url); } } -#endif static void start_fetch_packed(struct transfer_request *request) { @@ -314,17 +314,18 @@ static void start_fetch_packed(struct transfer_request *request) release_request(request); return; } + close_pack_index(target); + request->target = target; fprintf(stderr, "Fetching pack %s\n", hash_to_hex(target->hash)); fprintf(stderr, " which contains %s\n", oid_to_hex(&request->obj->oid)); - preq = new_http_pack_request(target, repo->url); - if (preq == NULL) { + preq = new_http_pack_request(target->hash, repo->url); + if (!preq) { repo->can_update_info_refs = 0; return; } - preq->lst = &repo->packs; /* Make sure there isn't another open request for this pack */ while (check_request) { @@ -365,8 +366,9 @@ static void start_put(struct transfer_request *request) ssize_t size; git_zstream stream; - unpacked = read_object_file(&request->obj->oid, &type, &len); - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1; + unpacked = repo_read_object_file(the_repository, &request->obj->oid, + &type, &len); + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); /* Set it up */ git_deflate_init(&stream, zlib_compression_level); @@ -523,7 +525,7 @@ static void finish_request(struct transfer_request *request) /* Keep locks active */ check_locks(); - if (request->headers != NULL) + if (request->headers) curl_slist_free_all(request->headers); /* URL is reused for MOVE after PUT and used during FETCH */ @@ -597,13 +599,14 @@ static void finish_request(struct transfer_request *request) } if (fail) repo->can_update_info_refs = 0; + else + http_install_packfile(request->target, &repo->packs); release_request(request); } } -#ifdef USE_CURL_MULTI static int is_running_queue; -static int fill_active_slot(void *unused) +static int fill_active_slot(void *data UNUSED) { struct transfer_request *request; @@ -625,7 +628,6 @@ static int fill_active_slot(void *unused) } return 0; } -#endif static void get_remote_object_list(unsigned char parent); @@ -654,10 +656,8 @@ static void add_fetch_request(struct object *obj) request->next = request_queue_head; request_queue_head = request; -#ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); -#endif } static int add_send_request(struct object *obj, struct remote_lock *lock) @@ -692,10 +692,8 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) request->next = request_queue_head; request_queue_head = request; -#ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); -#endif return 1; } @@ -784,13 +782,13 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed) static void one_remote_ref(const char *refname); static void -xml_start_tag(void *userData, const char *name, const char **atts) +xml_start_tag(void *userData, const char *name, const char **atts UNUSED) { struct xml_ctx *ctx = (struct xml_ctx *)userData; const char *c = strchr(name, ':'); int old_namelen, new_len; - if (c == NULL) + if (!c) c = name; else c++; @@ -818,7 +816,7 @@ xml_end_tag(void *userData, const char *name) ctx->userFunc(ctx, 1); - if (c == NULL) + if (!c) c = name; else c++; @@ -890,9 +888,9 @@ static struct remote_lock *lock_remote(const char *path, long timeout) slot->results = &results; curl_setup_http(slot->curl, url, DAV_LOCK, &out_buffer, fwrite_buffer); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); - curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); + curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); - lock = xcalloc(1, sizeof(*lock)); + CALLOC_ARRAY(lock, 1); lock->timeout = -1; if (start_active_slot(slot)) { @@ -1018,6 +1016,8 @@ static void remote_ls(const char *path, int flags, /* extract hex from sharded "xx/x{38}" filename */ static int get_oid_hex_from_objpath(const char *path, struct object_id *oid) { + oid->algo = hash_algo_by_ptr(the_hash_algo); + if (strlen(path) != the_hash_algo->hexsz + 1) return -1; @@ -1147,7 +1147,7 @@ static void remote_ls(const char *path, int flags, curl_setup_http(slot->curl, url, DAV_PROPFIND, &out_buffer, fwrite_buffer); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); - curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); + curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); if (start_active_slot(slot)) { run_active_slot(slot); @@ -1221,7 +1221,7 @@ static int locking_available(void) curl_setup_http(slot->curl, repo->url, DAV_PROPFIND, &out_buffer, fwrite_buffer); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); - curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer); + curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); if (start_active_slot(slot)) { run_active_slot(slot); @@ -1307,7 +1307,7 @@ static struct object_list **process_tree(struct tree *tree, obj->flags |= SEEN; p = add_one_object(obj, p); - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) switch (object_type(entry.mode)) { @@ -1336,7 +1336,8 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock) int count = 0; while ((commit = get_revision(revs)) != NULL) { - p = process_tree(get_commit_tree(commit), p); + p = process_tree(repo_get_commit_tree(the_repository, commit), + p); commit->object.flags |= LOCAL; if (!(commit->object.flags & UNINTERESTING)) count += add_send_request(&commit->object, lock); @@ -1431,8 +1432,8 @@ static void one_remote_ref(const char *refname) * Fetch a copy of the object if it doesn't exist locally - it * may be required for updating server info later. */ - if (repo->can_update_info_refs && !has_object_file(&ref->old_oid)) { - obj = lookup_unknown_object(&ref->old_oid); + if (repo->can_update_info_refs && !repo_has_object_file(the_repository, &ref->old_oid)) { + obj = lookup_unknown_object(the_repository, &ref->old_oid); fprintf(stderr, " fetch %s for %s\n", oid_to_hex(&ref->old_oid), refname); add_fetch_request(obj); @@ -1574,8 +1575,11 @@ static int verify_merge_base(struct object_id *head_oid, struct ref *remote) struct commit *head = lookup_commit_or_die(head_oid, "HEAD"); struct commit *branch = lookup_commit_or_die(&remote->old_oid, remote->name); + int ret = repo_in_merge_bases(the_repository, branch, head); - return in_merge_bases(branch, head); + if (ret < 0) + exit(128); + return ret; } static int delete_remote_branch(const char *pattern, int force) @@ -1632,14 +1636,14 @@ static int delete_remote_branch(const char *pattern, int force) return error("Remote HEAD symrefs too deep"); if (is_null_oid(&head_oid)) return error("Unable to resolve remote HEAD"); - if (!has_object_file(&head_oid)) + if (!repo_has_object_file(the_repository, &head_oid)) return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", oid_to_hex(&head_oid)); /* Remote branch must resolve to a known object */ if (is_null_oid(&remote_ref->old_oid)) return error("Unable to resolve remote branch %s", remote_ref->name); - if (!has_object_file(&remote_ref->old_oid)) + if (!repo_has_object_file(the_repository, &remote_ref->old_oid)) return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, oid_to_hex(&remote_ref->old_oid)); /* Remote branch must be an ancestor of remote HEAD */ @@ -1676,21 +1680,15 @@ static int delete_remote_branch(const char *pattern, int force) static void run_request_queue(void) { -#ifdef USE_CURL_MULTI is_running_queue = 1; fill_active_slots(); add_fill_function(NULL, fill_active_slot); -#endif do { finish_all_active_slots(); -#ifdef USE_CURL_MULTI fill_active_slots(); -#endif } while (request_queue_head && !aborted); -#ifdef USE_CURL_MULTI is_running_queue = 0; -#endif } int cmd_main(int argc, const char **argv) @@ -1700,7 +1698,6 @@ int cmd_main(int argc, const char **argv) struct refspec rs = REFSPEC_INIT_PUSH; struct remote_lock *ref_lock = NULL; struct remote_lock *info_ref_lock = NULL; - struct rev_info revs; int delete_branch = 0; int force_delete = 0; int objects_to_send; @@ -1709,7 +1706,7 @@ int cmd_main(int argc, const char **argv) int new_refs; struct ref *ref, *local_refs; - repo = xcalloc(1, sizeof(*repo)); + CALLOC_ARRAY(repo, 1); argv++; for (i = 1; i < argc; i++, argv++) { @@ -1764,10 +1761,6 @@ int cmd_main(int argc, const char **argv) break; } -#ifndef USE_CURL_MULTI - die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI"); -#endif - if (!repo->url) usage(http_push_usage); @@ -1780,9 +1773,7 @@ int cmd_main(int argc, const char **argv) http_init(NULL, repo->url, 1); -#ifdef USE_CURL_MULTI is_running_queue = 0; -#endif /* Verify DAV compliance/lock support */ if (!locking_available()) { @@ -1842,7 +1833,8 @@ int cmd_main(int argc, const char **argv) new_refs = 0; for (ref = remote_refs; ref; ref = ref->next) { - struct argv_array commit_argv = ARGV_ARRAY_INIT; + struct rev_info revs; + struct strvec commit_argv = STRVEC_INIT; if (!ref->peer_ref) continue; @@ -1862,6 +1854,7 @@ int cmd_main(int argc, const char **argv) if (oideq(&ref->old_oid, &ref->peer_ref->new_oid)) { if (push_verbosely) + /* stable plumbing output; do not modify or localize */ fprintf(stderr, "'%s': up-to-date\n", ref->name); if (helper_status) printf("ok %s up to date\n", ref->name); @@ -1871,7 +1864,7 @@ int cmd_main(int argc, const char **argv) if (!force_all && !is_null_oid(&ref->old_oid) && !ref->force) { - if (!has_object_file(&ref->old_oid) || + if (!repo_has_object_file(the_repository, &ref->old_oid) || !ref_newer(&ref->peer_ref->new_oid, &ref->old_oid)) { /* @@ -1882,6 +1875,7 @@ int cmd_main(int argc, const char **argv) * commits at the remote end and likely * we were not up to date to begin with. */ + /* stable plumbing output; do not modify or localize */ error("remote '%s' is not an ancestor of\n" "local '%s'.\n" "Maybe you are not up-to-date and " @@ -1910,7 +1904,7 @@ int cmd_main(int argc, const char **argv) /* Lock remote branch ref */ ref_lock = lock_remote(ref->name, LOCK_TIME); - if (ref_lock == NULL) { + if (!ref_lock) { fprintf(stderr, "Unable to lock remote branch %s\n", ref->name); if (helper_status) @@ -1920,14 +1914,14 @@ int cmd_main(int argc, const char **argv) } /* Set up revision info for this refspec */ - argv_array_push(&commit_argv, ""); /* ignored */ - argv_array_push(&commit_argv, "--objects"); - argv_array_push(&commit_argv, oid_to_hex(&ref->new_oid)); + strvec_push(&commit_argv, ""); /* ignored */ + strvec_push(&commit_argv, "--objects"); + strvec_push(&commit_argv, oid_to_hex(&ref->new_oid)); if (!push_all && !is_null_oid(&ref->old_oid)) - argv_array_pushf(&commit_argv, "^%s", - oid_to_hex(&ref->old_oid)); + strvec_pushf(&commit_argv, "^%s", + oid_to_hex(&ref->old_oid)); repo_init_revisions(the_repository, &revs, setup_git_directory()); - setup_revisions(commit_argv.argc, commit_argv.argv, &revs, NULL); + setup_revisions(commit_argv.nr, commit_argv.v, &revs, NULL); revs.edge_hint = 0; /* just in case */ /* Generate a list of objects that need to be pushed */ @@ -1957,7 +1951,8 @@ int cmd_main(int argc, const char **argv) printf("%s %s\n", !rc ? "ok" : "error", ref->name); unlock_remote(ref_lock); check_locks(); - argv_array_clear(&commit_argv); + strvec_clear(&commit_argv); + release_revisions(&revs); } /* Update remote server info if appropriate */ |