summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/remote.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/remote.c b/src/remote.c
index 99b5bacc0..43b34561d 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -1453,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
@@ -1473,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(
@@ -1532,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);