Commit 306475eb0173d7943a27afee6054af8d0f76bedd

Carlos Martín Nieto 2014-05-20T09:55:26

remote: expose the remote's symref mappings Add a symref_target field to git_remote_head to expose the symref mappings to the user.

diff --git a/include/git2/net.h b/include/git2/net.h
index e70ba1f..a727696 100644
--- a/include/git2/net.h
+++ b/include/git2/net.h
@@ -41,6 +41,11 @@ struct git_remote_head {
 	git_oid oid;
 	git_oid loid;
 	char *name;
+	/**
+	 * If the server send a symref mapping for this ref, this will
+	 * point to the target.
+	 */
+	char *symref_target;
 };
 
 /**
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 2f3e777..47ef503 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -75,6 +75,25 @@ int git_smart__update_heads(transport_smart *t, git_vector *symrefs)
 		if (pkt->type != GIT_PKT_REF)
 			continue;
 
+		if (symrefs) {
+			git_refspec *spec;
+			git_buf buf = GIT_BUF_INIT;
+			size_t j;
+			int error;
+
+			git_vector_foreach(symrefs, j, spec) {
+				git_buf_clear(&buf);
+				if (git_refspec_src_matches(spec, ref->head.name) &&
+				    !(error = git_refspec_transform(&buf, spec, ref->head.name)))
+					ref->head.symref_target = git_buf_detach(&buf);
+			}
+
+			git_buf_free(&buf);
+
+			if (error < 0)
+				return error;
+		}
+
 		if (git_vector_insert(&t->heads, &ref->head) < 0)
 			return -1;
 	}
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index e9376ae..b5f9d6d 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -433,6 +433,7 @@ void git_pkt_free(git_pkt *pkt)
 	if (pkt->type == GIT_PKT_REF) {
 		git_pkt_ref *p = (git_pkt_ref *) pkt;
 		git__free(p->head.name);
+		git__free(p->head.symref_target);
 	}
 
 	if (pkt->type == GIT_PKT_OK) {
diff --git a/tests/online/fetch.c b/tests/online/fetch.c
index c54ec56..f03a6fa 100644
--- a/tests/online/fetch.c
+++ b/tests/online/fetch.c
@@ -184,3 +184,21 @@ void test_online_fetch__ls_disconnected(void)
 
 	git_remote_free(remote);
 }
+
+void test_online_fetch__remote_symrefs(void)
+{
+	const git_remote_head **refs;
+	size_t refs_len;
+	git_remote *remote;
+
+	cl_git_pass(git_remote_create(&remote, _repo, "test",
+				"http://github.com/libgit2/TestGitRepository.git"));
+	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
+	git_remote_disconnect(remote);
+	cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
+
+	cl_assert_equal_s("HEAD", refs[0]->name);
+	cl_assert_equal_s("refs/heads/master", refs[0]->symref_target);
+
+	git_remote_free(remote);
+}