Commit bb89cf9478bd6c1c5df1fbda2d82cc86a3ba5aed

nulltoken 2012-07-12T10:57:31

revparse: simplify handling of the colon syntax

diff --git a/src/revparse.c b/src/revparse.c
index 2b03c86..e35c01a 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -520,88 +520,37 @@ static int handle_linear_syntax(git_object **out, git_object *obj, const char *m
 	return git_commit_nth_gen_ancestor((git_commit **)out, (git_commit*)obj, n);
 }
 
-static int oid_for_tree_path(git_oid *out, git_tree *tree, git_repository *repo, const char *path)
-{
-	char *str, *tok;
-	void *alloc;
-	git_tree *tree2 = tree;
-	const git_tree_entry *entry = NULL;
-	git_otype type;
-
-	if (*path == '\0') {
-		git_oid_cpy(out, git_object_id((git_object *)tree));
-		return 0;
-	}
-
-	alloc = str = git__strdup(path);
-
-	while ((tok = git__strtok(&str, "/\\")) != NULL) {
-		entry = git_tree_entry_byname(tree2, tok);
-		if (tree2 != tree) git_tree_free(tree2);
-
-		if (entry == NULL)
-			break;
-
-		type = git_tree_entry_type(entry);
-
-		switch (type) {
-		case GIT_OBJ_TREE:
-			if (*str == '\0')
-				break;
-			if (git_tree_lookup(&tree2, repo, &entry->oid) < 0) {
-				git__free(alloc);
-				return GIT_ERROR;
-			}
-			break;
-		case GIT_OBJ_BLOB:
-			if (*str != '\0') {
-				entry = NULL;
-				goto out;
-			}
-			break;
-		default:
-			/* TODO: support submodules? */
-			giterr_set(GITERR_INVALID, "Unimplemented");
-			git__free(alloc);
-			return GIT_ERROR;
-		}
-	}
-
-out:
-	if (!entry) {
-		giterr_set(GITERR_INVALID, "Invalid tree path '%s'", path);
-		git__free(alloc);
-		return GIT_ENOTFOUND;
-	}
-
-	git_oid_cpy(out, git_tree_entry_id(entry));
-	git__free(alloc);
-	return 0;
-}
-
 static int handle_colon_syntax(git_object **out,
 	git_repository *repo,
 	git_object *obj,
 	const char *path)
 {
-	git_tree *tree;
-	git_oid oid;
-	int error;
+	git_object *tree = obj;
+	int error = -1;
+	git_tree_entry *entry = NULL;
 
 	/* Dereference until we reach a tree. */
-	if (dereference_to_type(&obj, obj, GIT_OBJ_TREE) < 0) {
+	if (dereference_to_type(&tree, obj, GIT_OBJ_TREE) < 0)
 		return GIT_ERROR;
-	}
-	tree = (git_tree*)obj;
 
-	/* Find the blob or tree at the given path. */
-	error = oid_for_tree_path(&oid, tree, repo, path);
-	git_tree_free(tree);
+	if (*path == '\0')
+		return git_object_lookup(out, repo, git_object_id(tree), GIT_OBJ_TREE);
 
-	if (error < 0)
-		return error;
+	/*
+	 * TODO: Handle the relative path syntax
+	 * (:./relative/path and :../relative/path)
+	 */
+	if ((error = git_tree_entry_bypath(&entry, (git_tree *)tree, path)) < 0)
+		goto cleanup;
+
+	error = git_tree_entry_to_object(out, repo, entry);
 
-	return git_object_lookup(out, repo, &oid, GIT_OBJ_ANY);
+cleanup:
+	git_tree_entry_free(entry);
+	if (tree != obj)
+		git_object_free(tree);
+
+	return error;
 }
 
 static int revparse_global_grep(git_object **out, git_repository *repo, const char *pattern)
diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c
index dbc002d..aba105b 100644
--- a/tests-clar/refs/revparse.c
+++ b/tests-clar/refs/revparse.c
@@ -325,12 +325,26 @@ void test_refs_revparse__colon(void)
 	test_object("subtrees:nope", NULL);
 	test_object("test/master^1:branch_file.txt", NULL);
 
-	/* Trees */
+	/* From tags */
+	test_object("test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
+	test_object("tags/test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
+	test_object("e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
+	test_object("tags/e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
+
+	/* From commits */
+	test_object("a65f:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
+
+	/* From trees */
+	test_object("a65f^{tree}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
+	test_object("944c:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
+
+	/* Retrieving trees */
 	test_object("master:", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
 	test_object("subtrees:", "ae90f12eea699729ed24555e40b9fd669da12a12");
 	test_object("subtrees:ab", "f1425cef211cc08caa31e7b545ffb232acb098c3");
+	test_object("subtrees:ab/", "f1425cef211cc08caa31e7b545ffb232acb098c3");
 
-	/* Blobs */
+	/* Retrieving blobs */
 	test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f");
 	test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b");
 	test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6");