Commit 99a9c86cb654eb37bc77b31b76619e843d89de09

Ben Straub 2013-07-17T20:08:15

Merge pull request #1722 from libgit2/ntk/fix/issue_1722 git_revparse_ext: should return a NULL reference when the revparse expression doesn't lead to a reference

diff --git a/src/revparse.c b/src/revparse.c
index bcfb084..d21f08b 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -685,6 +685,8 @@ int revparse__ext(
 	git_reference *reference = NULL;
 	git_object *base_rev = NULL;
 
+	bool should_return_reference = true;
+
 	assert(object_out && reference_out && repo && spec);
 
 	*object_out = NULL;
@@ -693,6 +695,8 @@ int revparse__ext(
 	while (spec[pos]) {
 		switch (spec[pos]) {
 		case '^':
+			should_return_reference = false;
+
 			if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0)
 				goto cleanup;
 
@@ -725,6 +729,8 @@ int revparse__ext(
 		{
 			git_object *temp_object = NULL;
 
+			should_return_reference = false;
+
 			if ((error = extract_how_many(&n, spec, &pos)) < 0)
 				goto cleanup;
 
@@ -743,6 +749,8 @@ int revparse__ext(
 		{
 			git_object *temp_object = NULL;
 
+			should_return_reference = false;
+
 			if ((error = extract_path(&buf, spec, &pos)) < 0)
 				goto cleanup;
 
@@ -807,6 +815,11 @@ int revparse__ext(
 	if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0)
 		goto cleanup;
 
+	if (!should_return_reference) {
+		git_reference_free(reference);
+		reference = NULL;
+	}
+
 	*object_out = base_rev;
 	*reference_out = reference;
 	*identifier_len_out = identifier_len;
diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c
index 69d9274..9657054 100644
--- a/tests-clar/refs/revparse.c
+++ b/tests-clar/refs/revparse.c
@@ -738,4 +738,45 @@ void test_refs_revparse__ext_can_expand_short_reference_names(void)
 		"master",
 		"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
 		"refs/heads/master");
+
+	test_object_and_ref(
+		"HEAD",
+		"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+		"refs/heads/master");
+
+    test_object_and_ref(
+		"tags/test",
+		"b25fa35b38051e4ae45d4222e795f9df2e43f1d1",
+        "refs/tags/test");
+}
+
+void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_revision(void)
+{
+    test_object_and_ref(
+        "HEAD~3",
+        "4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
+        NULL);
+
+    test_object_and_ref(
+        "HEAD~0",
+        "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+        NULL);
+
+    test_object_and_ref(
+        "HEAD^0",
+        "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+        NULL);
+
+    test_object_and_ref(
+		"@{-1}@{0}",
+		"a4a7dce85cf63874e984719f4fdd239f5145052f",
+		NULL);
+}
+
+void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_tree_content(void)
+{
+    test_object_and_ref(
+		"tags/test:readme.txt",
+		"0266163a49e280c4f5ed1e08facd36a2bd716bcf",
+        NULL);
 }