diff options
Diffstat (limited to 'src/remote.c')
-rw-r--r-- | src/remote.c | 40 |
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); |