Commit 9566ce430fde97d5e610bb2796d27d47e1e81ab5

Carlos Martín Nieto 2015-05-18T14:42:35

remote: call the update_tips callback for opportunisitc updates These are updates, same as the rest, we should call this callback. As we are using the callback, let's make sure to skip unnecessary updates.

diff --git a/src/remote.c b/src/remote.c
index 99b5bac..43b3456 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);