diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/branch.c | 6 | ||||
| -rw-r--r-- | src/checkout.c | 4 | ||||
| -rw-r--r-- | src/global.c | 6 | ||||
| -rw-r--r-- | src/indexer.c | 12 | ||||
| -rw-r--r-- | src/odb.c | 4 | ||||
| -rw-r--r-- | src/push.c | 70 | ||||
| -rw-r--r-- | src/push.h | 6 | ||||
| -rw-r--r-- | src/refspec.c | 6 | ||||
| -rw-r--r-- | src/remote.c | 66 | ||||
| -rw-r--r-- | src/transports/http.c | 1 | ||||
| -rw-r--r-- | src/transports/local.c | 4 | ||||
| -rw-r--r-- | src/transports/smart_protocol.c | 12 |
12 files changed, 127 insertions, 70 deletions
diff --git a/src/branch.c b/src/branch.c index 01402a2e9..b4e4b0564 100644 --- a/src/branch.c +++ b/src/branch.c @@ -400,6 +400,12 @@ int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *r if ((error = retrieve_upstream_configuration(&str, cfg, refname, "branch.%s.remote")) < 0) goto cleanup; + if (!*str) { + giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream remote", refname); + error = GIT_ENOTFOUND; + goto cleanup; + } + error = git_buf_puts(buf, str); cleanup: diff --git a/src/checkout.c b/src/checkout.c index 44e2f3b27..4e879e36f 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1145,12 +1145,16 @@ static int checkout_conflict_append_remove( checkout_data *data = payload; const char *name; + assert(ancestor || ours || theirs); + if (ancestor) name = git__strdup(ancestor->path); else if (ours) name = git__strdup(ours->path); else if (theirs) name = git__strdup(theirs->path); + else + abort(); GITERR_CHECK_ALLOC(name); diff --git a/src/global.c b/src/global.c index da903cb94..006202a2c 100644 --- a/src/global.c +++ b/src/global.c @@ -67,7 +67,13 @@ void openssl_locking_function(int mode, int n, const char *file, int line) static void shutdown_ssl_locking(void) { + int num_locks, i; + + num_locks = CRYPTO_num_locks(); CRYPTO_set_locking_callback(NULL); + + for (i = 0; i < num_locks; ++i) + git_mutex_free(openssl_locks); git__free(openssl_locks); } #endif diff --git a/src/indexer.c b/src/indexer.c index 620e8186b..0e682dd6e 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -120,6 +120,7 @@ int git_indexer_new( idx->progress_cb = progress_cb; idx->progress_payload = progress_payload; idx->mode = mode ? mode : GIT_PACK_FILE_MODE; + git_hash_ctx_init(&idx->hash_ctx); git_hash_ctx_init(&idx->trailer); error = git_buf_joinpath(&path, prefix, suff); @@ -265,7 +266,6 @@ static int store_object(git_indexer *idx) struct entry *entry; git_off_t entry_size; struct git_pack_entry *pentry; - git_hash_ctx *ctx = &idx->hash_ctx; git_off_t entry_start = idx->entry_start; entry = git__calloc(1, sizeof(*entry)); @@ -274,7 +274,7 @@ static int store_object(git_indexer *idx) pentry = git__calloc(1, sizeof(struct git_pack_entry)); GITERR_CHECK_ALLOC(pentry); - git_hash_final(&oid, ctx); + git_hash_final(&oid, &idx->hash_ctx); entry_size = idx->off - entry_start; if (entry_start > UINT31_MAX) { entry->offset = UINT32_MAX; @@ -557,7 +557,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran git_mwindow_close(&w); idx->entry_start = entry_start; - git_hash_ctx_init(&idx->hash_ctx); + git_hash_init(&idx->hash_ctx); if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) { error = advance_delta_offset(idx, type); @@ -843,12 +843,10 @@ static int update_header_and_rehash(git_indexer *idx, git_transfer_progress *sta git_mwindow *w = NULL; git_mwindow_file *mwf; unsigned int left; - git_hash_ctx *ctx; mwf = &idx->pack->mwf; - ctx = &idx->trailer; - git_hash_ctx_init(ctx); + git_hash_init(&idx->trailer); /* Update the header to include the numer of local objects we injected */ @@ -1061,5 +1059,7 @@ void git_indexer_free(git_indexer *idx) git_mutex_unlock(&git__mwindow_mutex); } + git_hash_ctx_cleanup(&idx->trailer); + git_hash_ctx_cleanup(&idx->hash_ctx); git__free(idx); } @@ -762,12 +762,12 @@ static int hardcoded_objects(git_rawobj *raw, const git_oid *id) if (!git_oid_cmp(id, &empty_blob)) { raw->type = GIT_OBJ_BLOB; raw->len = 0; - raw->data = NULL; + raw->data = git__calloc(1, sizeof(uint8_t)); return 0; } else if (!git_oid_cmp(id, &empty_tree)) { raw->type = GIT_OBJ_TREE; raw->len = 0; - raw->data = NULL; + raw->data = git__calloc(1, sizeof(uint8_t)); return 0; } else { return GIT_ENOTFOUND; diff --git a/src/push.c b/src/push.c index be5ec1c0e..6671da465 100644 --- a/src/push.c +++ b/src/push.c @@ -19,7 +19,7 @@ static int push_spec_rref_cmp(const void *a, const void *b) { const push_spec *push_spec_a = a, *push_spec_b = b; - return strcmp(push_spec_a->rref, push_spec_b->rref); + return strcmp(push_spec_a->refspec.dst, push_spec_b->refspec.dst); } static int push_status_ref_cmp(const void *a, const void *b) @@ -94,12 +94,7 @@ static void free_refspec(push_spec *spec) if (spec == NULL) return; - if (spec->lref) - git__free(spec->lref); - - if (spec->rref) - git__free(spec->rref); - + git_refspec__free(&spec->refspec); git__free(spec); } @@ -134,47 +129,25 @@ static int check_lref(git_push *push, char *ref) static int parse_refspec(git_push *push, push_spec **spec, const char *str) { push_spec *s; - char *delim; *spec = NULL; s = git__calloc(1, sizeof(*s)); GITERR_CHECK_ALLOC(s); - if (str[0] == '+') { - s->force = true; - str++; + if (git_refspec__parse(&s->refspec, str, false) < 0) { + giterr_set(GITERR_INVALID, "invalid refspec %s", str); + goto on_error; } - delim = strchr(str, ':'); - if (delim == NULL) { - s->lref = git__strdup(str); - if (!s->lref || check_lref(push, s->lref) < 0) - goto on_error; - } else { - if (delim - str) { - s->lref = git__strndup(str, delim - str); - if (!s->lref || check_lref(push, s->lref) < 0) - goto on_error; - } - - if (strlen(delim + 1)) { - s->rref = git__strdup(delim + 1); - if (!s->rref || check_rref(s->rref) < 0) - goto on_error; - } + if (s->refspec.src && s->refspec.src[0] != '\0' && + check_lref(push, s->refspec.src) < 0) { + goto on_error; } - if (!s->lref && !s->rref) + if (check_rref(s->refspec.dst) < 0) goto on_error; - /* If rref is ommitted, use the same ref name as lref */ - if (!s->rref) { - s->rref = git__strdup(s->lref); - if (!s->rref || check_rref(s->rref) < 0) - goto on_error; - } - *spec = s; return 0; @@ -220,7 +193,7 @@ int git_push_update_tips( /* Find matching push ref spec */ git_vector_foreach(&push->specs, j, push_spec) { - if (!strcmp(push_spec->rref, status->ref)) + if (!strcmp(push_spec->refspec.dst, status->ref)) break; } @@ -353,14 +326,15 @@ static int revwalk(git_vector *commits, git_push *push) } else if (git_revwalk_push(rw, &spec->loid) < 0) goto on_error; - if (!spec->force) { + if (!spec->refspec.force) { git_oid base; if (git_oid_iszero(&spec->roid)) continue; if (!git_odb_exists(push->repo->_odb, &spec->roid)) { - giterr_set(GITERR_REFERENCE, "Cannot push missing reference"); + giterr_set(GITERR_REFERENCE, + "Cannot push because a reference that you are trying to update on the remote contains commits that are not present locally."); error = GIT_ENONFASTFORWARD; goto on_error; } @@ -571,22 +545,20 @@ static int calculate_work(git_push *push) /* Update local and remote oids*/ git_vector_foreach(&push->specs, i, spec) { - if (spec->lref) { + if (spec->refspec.src && spec->refspec.src[0]!= '\0') { /* This is a create or update. Local ref must exist. */ if (git_reference_name_to_id( - &spec->loid, push->repo, spec->lref) < 0) { - giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->lref); + &spec->loid, push->repo, spec->refspec.src) < 0) { + giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->refspec.src); return -1; } } - if (spec->rref) { - /* Remote ref may or may not (e.g. during create) already exist. */ - git_vector_foreach(&push->remote->refs, j, head) { - if (!strcmp(spec->rref, head->name)) { - git_oid_cpy(&spec->roid, &head->oid); - break; - } + /* Remote ref may or may not (e.g. during create) already exist. */ + git_vector_foreach(&push->remote->refs, j, head) { + if (!strcmp(spec->refspec.dst, head->name)) { + git_oid_cpy(&spec->roid, &head->oid); + break; } } } diff --git a/src/push.h b/src/push.h index 6c8bf7229..68fa868dd 100644 --- a/src/push.h +++ b/src/push.h @@ -8,15 +8,13 @@ #define INCLUDE_push_h__ #include "git2.h" +#include "refspec.h" typedef struct push_spec { - char *lref; - char *rref; + struct git_refspec refspec; git_oid loid; git_oid roid; - - bool force; } push_spec; typedef struct push_status { diff --git a/src/refspec.c b/src/refspec.c index 9f0df35a7..a56c44cc0 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -119,6 +119,12 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch) if (!git_reference__is_valid_name(refspec->dst, flags)) goto invalid; } + + /* if the RHS is empty, then it's a copy of the LHS */ + if (!refspec->dst) { + refspec->dst = git__strdup(refspec->src); + GITERR_CHECK_ALLOC(refspec->dst); + } } refspec->string = git__strdup(input); diff --git a/src/remote.c b/src/remote.c index cc9f85cd1..b1a84075e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -163,6 +163,10 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n if (fetch != NULL) { if (add_refspec(remote, fetch, true) < 0) goto on_error; + + /* Move the data over to where the matching functions can find them */ + if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0) + goto on_error; } if (!name) @@ -702,7 +706,7 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote assert(remote); if (!remote->transport) { - giterr_set(GITERR_NET, "No transport bound to this remote"); + giterr_set(GITERR_NET, "this remote has never connected"); return -1; } @@ -2111,3 +2115,63 @@ int git_remote_default_branch(git_buf *out, git_remote *remote) return git_buf_puts(out, guess->name); } + +int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_options *opts, + const git_signature *signature, const char *reflog_message) +{ + int error; + size_t i; + git_push *push = NULL; + git_remote_callbacks *cbs; + git_refspec *spec; + + assert(remote && refspecs); + + if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0) + return error; + + if ((error = git_push_new(&push, remote)) < 0) + goto cleanup; + + if (opts && (error = git_push_set_options(push, opts)) < 0) + goto cleanup; + + if (refspecs && refspecs->count > 0) { + for (i = 0; i < refspecs->count; i++) { + if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0) + goto cleanup; + } + } else { + git_vector_foreach(&remote->refspecs, i, spec) { + if (!spec->push) + continue; + if ((error = git_push_add_refspec(push, spec->string)) < 0) + goto cleanup; + } + } + + cbs = &remote->callbacks; + if ((error = git_push_set_callbacks(push, + cbs->pack_progress, cbs->payload, + cbs->push_transfer_progress, cbs->payload)) < 0) + goto cleanup; + + if ((error = git_push_finish(push)) < 0) + goto cleanup; + + if (!git_push_unpack_ok(push)) { + error = -1; + giterr_set(GITERR_NET, "error in the remote while trying to unpack"); + goto cleanup; + } + + if ((error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0) + goto cleanup; + + error = git_push_update_tips(push, signature, reflog_message); + +cleanup: + git_remote_disconnect(remote); + git_push_free(push); + return error; +} diff --git a/src/transports/http.c b/src/transports/http.c index 4070b683a..234ee229f 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -1009,6 +1009,7 @@ static int http_close(git_smart_subtransport *subtransport) git_vector_clear(&t->auth_contexts); gitno_connection_data_free_ptrs(&t->connection_data); + memset(&t->connection_data, 0x0, sizeof(gitno_connection_data)); return 0; } diff --git a/src/transports/local.c b/src/transports/local.c index f859f0b70..05302a13f 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -405,7 +405,7 @@ static int local_push( git_vector_foreach(&push->specs, j, spec) { push_status *status; const git_error *last; - char *ref = spec->rref ? spec->rref : spec->lref; + char *ref = spec->refspec.dst; status = git__calloc(sizeof(push_status), 1); if (!status) @@ -417,7 +417,7 @@ static int local_push( goto on_error; } - error = local_push_update_remote_ref(remote_repo, spec->lref, spec->rref, + error = local_push_update_remote_ref(remote_repo, spec->refspec.src, spec->refspec.dst, &spec->loid, &spec->roid); switch (error) { diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 7c20382dc..e110da07e 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -645,7 +645,7 @@ static int gen_pktline(git_buf *buf, git_push *push) old_id[GIT_OID_HEXSZ] = '\0'; new_id[GIT_OID_HEXSZ] = '\0'; git_vector_foreach(&push->specs, i, spec) { - len = 2*GIT_OID_HEXSZ + 7 + strlen(spec->rref); + len = 2*GIT_OID_HEXSZ + 7 + strlen(spec->refspec.dst); if (i == 0) { ++len; /* '\0' */ @@ -657,7 +657,7 @@ static int gen_pktline(git_buf *buf, git_push *push) git_oid_fmt(old_id, &spec->roid); git_oid_fmt(new_id, &spec->loid); - git_buf_printf(buf, "%04"PRIxZ"%s %s %s", len, old_id, new_id, spec->rref); + git_buf_printf(buf, "%04"PRIxZ"%s %s %s", len, old_id, new_id, spec->refspec.dst); if (i == 0) { git_buf_putc(buf, '\0'); @@ -816,7 +816,7 @@ static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec) added->type = GIT_PKT_REF; git_oid_cpy(&added->head.oid, &push_spec->loid); - added->head.name = git__strdup(push_spec->rref); + added->head.name = git__strdup(push_spec->refspec.dst); if (!added->head.name || git_vector_insert(refs, added) < 0) { @@ -855,7 +855,7 @@ static int update_refs_from_report( /* For each push spec we sent to the server, we should have * gotten back a status packet in the push report which matches */ - if (strcmp(push_spec->rref, push_status->ref)) { + if (strcmp(push_spec->refspec.dst, push_status->ref)) { giterr_set(GITERR_NET, "report-status: protocol error"); return -1; } @@ -872,7 +872,7 @@ static int update_refs_from_report( push_status = git_vector_get(push_report, i); ref = git_vector_get(refs, j); - cmp = strcmp(push_spec->rref, ref->head.name); + cmp = strcmp(push_spec->refspec.dst, ref->head.name); /* Iterate appropriately */ if (cmp <= 0) i++; @@ -985,7 +985,7 @@ int git_smart__push(git_transport *transport, git_push *push) * cases except when we only send delete commands */ git_vector_foreach(&push->specs, i, spec) { - if (spec->lref) { + if (spec->refspec.src && spec->refspec.src[0] != '\0') { need_pack = 1; break; } |
