summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ident.c4
-rw-r--r--src/indexer.c15
-rw-r--r--src/openssl_stream.c21
-rw-r--r--src/pack.c7
-rw-r--r--src/remote.c82
5 files changed, 77 insertions, 52 deletions
diff --git a/src/ident.c b/src/ident.c
index 6bc80abc7..4718ed664 100644
--- a/src/ident.c
+++ b/src/ident.c
@@ -56,7 +56,7 @@ static int ident_insert_id(
return GIT_PASSTHROUGH;
need_size = (size_t)(id_start - from->ptr) +
- 5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ +
+ 5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
(size_t)(from_end - id_end);
if (git_buf_grow(to, need_size) < 0)
@@ -65,7 +65,7 @@ static int ident_insert_id(
git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
git_buf_put(to, "$Id: ", 5);
git_buf_put(to, oid, GIT_OID_HEXSZ);
- git_buf_putc(to, '$');
+ git_buf_put(to, " $", 2);
git_buf_put(to, id_end, (size_t)(from_end - id_end));
return git_buf_oom(to) ? -1 : 0;
diff --git a/src/indexer.c b/src/indexer.c
index 665d50fcd..e39345c71 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -325,6 +325,13 @@ on_error:
return -1;
}
+GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id)
+{
+ khiter_t k;
+ k = kh_get(oid, idx->pack->idx_cache, id);
+ return (k != kh_end(idx->pack->idx_cache));
+}
+
static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start)
{
int i, error;
@@ -339,8 +346,11 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent
pentry->offset = entry_start;
k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
- if (!error)
+
+ if (error <= 0) {
+ giterr_set(GITERR_INDEXER, "cannot insert object into pack");
return -1;
+ }
kh_value(idx->pack->idx_cache, k) = pentry;
@@ -791,6 +801,9 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
git_oid_fromraw(&base, base_info);
git_mwindow_close(&w);
+ if (has_entry(idx, &base))
+ return 0;
+
if (inject_object(idx, &base) < 0)
return -1;
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index a975bb0c1..9b2d5951c 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -291,19 +291,14 @@ ssize_t openssl_write(git_stream *stream, const char *data, size_t len, int flag
{
openssl_stream *st = (openssl_stream *) stream;
int ret;
- size_t off = 0;
GIT_UNUSED(flags);
- while (off < len) {
- ret = SSL_write(st->ssl, data + off, len - off);
- if (ret <= 0 && ret != SSL_ERROR_WANT_WRITE)
- return ssl_set_error(st->ssl, ret);
-
- off += ret;
- }
+ if ((ret = SSL_write(st->ssl, data, len)) <= 0) {
+ return ssl_set_error(st->ssl, ret);
+ }
- return off;
+ return ret;
}
ssize_t openssl_read(git_stream *stream, void *data, size_t len)
@@ -311,14 +306,8 @@ ssize_t openssl_read(git_stream *stream, void *data, size_t len)
openssl_stream *st = (openssl_stream *) stream;
int ret;
- do {
- ret = SSL_read(st->ssl, data, len);
- } while (SSL_get_error(st->ssl, ret) == SSL_ERROR_WANT_READ);
-
- if (ret < 0) {
+ if ((ret = SSL_read(st->ssl, data, len)) <= 0)
ssl_set_error(st->ssl, ret);
- return -1;
- }
return ret;
}
diff --git a/src/pack.c b/src/pack.c
index 5d0a27b91..105d67510 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -959,8 +959,15 @@ git_off_t get_delta_base(
if (k != kh_end(p->idx_cache)) {
*curpos += 20;
return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset;
+ } else {
+ /* If we're building an index, don't try to find the pack
+ * entry; we just haven't seen it yet. We'll make
+ * progress again in the next loop.
+ */
+ return GIT_PASSTHROUGH;
}
}
+
/* The base entry _must_ be in the same pack */
if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < 0)
return packfile_error("base entry delta is not in the same pack");
diff --git a/src/remote.c b/src/remote.c
index 44885bd17..43b34561d 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -97,6 +97,7 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
{
git_config *cfg;
git_buf var = GIT_BUF_INIT;
+ git_refspec spec;
const char *fmt;
int error;
@@ -108,6 +109,15 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
if ((error = ensure_remote_name_is_valid(name)) < 0)
return error;
+ if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0) {
+ if (giterr_last()->klass != GITERR_NOMEMORY)
+ error = GIT_EINVALIDSPEC;
+
+ return error;
+ }
+
+ git_refspec__free(&spec);
+
if ((error = git_buf_printf(&var, fmt, name)) < 0)
return error;
@@ -311,15 +321,16 @@ on_error:
return -1;
}
-int git_remote_create_anonymous(git_remote **out, git_repository *repo, const char *url, const char *fetch)
+int git_remote_create_anonymous(git_remote **out, git_repository *repo, const char *url)
{
- return create_internal(out, repo, NULL, url, fetch);
+ return create_internal(out, repo, NULL, url, NULL);
}
int git_remote_dup(git_remote **dest, git_remote *source)
{
+ size_t i;
int error = 0;
- git_strarray refspecs = { 0 };
+ git_refspec *spec;
git_remote *remote = git__calloc(1, sizeof(git_remote));
GITERR_CHECK_ALLOC(remote);
@@ -349,22 +360,15 @@ int git_remote_dup(git_remote **dest, git_remote *source)
goto cleanup;
}
- if ((error = git_remote_get_fetch_refspecs(&refspecs, source)) < 0 ||
- (error = git_remote_set_fetch_refspecs(remote, &refspecs)) < 0)
- goto cleanup;
-
- git_strarray_free(&refspecs);
-
- if ((error = git_remote_get_push_refspecs(&refspecs, source)) < 0 ||
- (error = git_remote_set_push_refspecs(remote, &refspecs)) < 0)
- goto cleanup;
+ git_vector_foreach(&source->refspecs, i, spec) {
+ if ((error = add_refspec(remote, spec->string, !spec->push)) < 0)
+ goto cleanup;
+ }
*dest = remote;
cleanup:
- git_strarray_free(&refspecs);
-
if (error < 0)
git__free(remote);
@@ -1449,18 +1453,20 @@ static int next_head(const git_remote *remote, git_vector *refs,
return GIT_ITEROVER;
}
-static int opportunistic_updates(const git_remote *remote, git_vector *refs, const char *msg)
+static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
+ git_vector *refs, const char *msg)
{
size_t i, j, k;
git_refspec *spec;
git_remote_head *head;
git_reference *ref;
git_buf refname = GIT_BUF_INIT;
- int error;
+ int error = 0;
i = j = k = 0;
while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
+ git_oid old = {{ 0 }};
/*
* If we got here, there is a refspec which was used
* for fetching which matches the source of one of the
@@ -1469,18 +1475,38 @@ static int opportunistic_updates(const git_remote *remote, git_vector *refs, con
* FETCH_HEAD
*/
+ git_buf_clear(&refname);
if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
- return error;
+ goto cleanup;
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
- git_buf_free(&refname);
- git_reference_free(ref);
+ error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
+ if (error < 0 && error != GIT_ENOTFOUND)
+ goto cleanup;
+ if (!git_oid_cmp(&old, &head->oid))
+ continue;
+
+ /* If we did find a current reference, make sure we haven't lost a race */
+ if (error)
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
+ else
+ error = git_reference_create_matching(&ref, remote->repo, refname.ptr, &head->oid, true, &old, msg);
+ git_reference_free(ref);
if (error < 0)
- return error;
+ goto cleanup;
+
+ if (callbacks && callbacks->update_tips != NULL) {
+ if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
+ goto cleanup;
+ }
}
- return 0;
+ if (error == GIT_ITEROVER)
+ error = 0;
+
+cleanup:
+ git_buf_free(&refname);
+ return error;
}
int git_remote_update_tips(
@@ -1528,7 +1554,7 @@ int git_remote_update_tips(
/* only try to do opportunisitic updates if the refpec lists differ */
if (remote->passed_refspecs)
- error = opportunistic_updates(remote, &refs, reflog_message);
+ error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
out:
git_vector_free(&refs);
@@ -2046,16 +2072,6 @@ static int set_refspecs(git_remote *remote, git_strarray *array, int push)
return 0;
}
-int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array)
-{
- return set_refspecs(remote, array, false);
-}
-
-int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array)
-{
- return set_refspecs(remote, array, true);
-}
-
static int copy_refspecs(git_strarray *array, const git_remote *remote, unsigned int push)
{
size_t i;