Commit b0d376695e7d3f71fed97d9d08b60661faad7a5a

Russell Belfer 2012-08-03T17:24:59

Add new iteration behavior to git_tree_walk Missed this one, ironically enough.

diff --git a/src/tree.c b/src/tree.c
index 422e62b..2e6153b 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -787,9 +787,10 @@ static int tree_walk(
 	for (i = 0; i < tree->entries.length; ++i) {
 		git_tree_entry *entry = tree->entries.contents[i];
 
-		if (preorder &&
-			(error = callback(path->ptr, entry, payload)) != 0)
+		if (preorder && callback(path->ptr, entry, payload)) {
+			error = GIT_EUSER;
 			break;
+		}
 
 		if (git_tree_entry__is_tree(entry)) {
 			git_tree *subtree;
@@ -814,9 +815,10 @@ static int tree_walk(
 			git_tree_free(subtree);
 		}
 
-		if (!preorder &&
-			(error = callback(path->ptr, entry, payload)) != 0)
+		if (!preorder && callback(path->ptr, entry, payload)) {
+			error = GIT_EUSER;
 			break;
+		}
 	}
 
 	return error;
diff --git a/tests-clar/object/tree/walk.c b/tests-clar/object/tree/walk.c
new file mode 100644
index 0000000..a0ea64c
--- /dev/null
+++ b/tests-clar/object/tree/walk.c
@@ -0,0 +1,103 @@
+#include "clar_libgit2.h"
+#include "tree.h"
+
+static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
+static git_repository *g_repo;
+
+void test_object_tree_walk__initialize(void)
+{
+   g_repo = cl_git_sandbox_init("testrepo");
+}
+
+void test_object_tree_walk__cleanup(void)
+{
+   cl_git_sandbox_cleanup();
+}
+
+static int treewalk_count_cb(
+	const char *root, const git_tree_entry *entry, void *payload)
+{
+	int *count = payload;
+
+	GIT_UNUSED(root);
+	GIT_UNUSED(entry);
+
+	(*count) += 1;
+
+	return 0;
+}
+
+void test_object_tree_walk__0(void)
+{
+	git_oid id;
+	git_tree *tree;
+	int ct;
+
+	git_oid_fromstr(&id, tree_oid);
+
+	cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
+
+	ct = 0;
+	cl_git_pass(git_tree_walk(tree, treewalk_count_cb, GIT_TREEWALK_PRE, &ct));
+	cl_assert_equal_i(3, ct);
+
+	ct = 0;
+	cl_git_pass(git_tree_walk(tree, treewalk_count_cb, GIT_TREEWALK_POST, &ct));
+	cl_assert_equal_i(3, ct);
+
+	git_tree_free(tree);
+}
+
+
+static int treewalk_stop_cb(
+	const char *root, const git_tree_entry *entry, void *payload)
+{
+	int *count = payload;
+
+	GIT_UNUSED(root);
+	GIT_UNUSED(entry);
+
+	(*count) += 1;
+
+	return (*count == 2);
+}
+
+static int treewalk_stop_immediately_cb(
+	const char *root, const git_tree_entry *entry, void *payload)
+{
+	GIT_UNUSED(root);
+	GIT_UNUSED(entry);
+	GIT_UNUSED(payload);
+	return -100;
+}
+
+void test_object_tree_walk__1(void)
+{
+	git_oid id;
+	git_tree *tree;
+	int ct;
+
+	git_oid_fromstr(&id, tree_oid);
+
+	cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
+
+	ct = 0;
+	cl_assert_equal_i(
+		GIT_EUSER, git_tree_walk(tree, treewalk_stop_cb, GIT_TREEWALK_PRE, &ct));
+	cl_assert_equal_i(2, ct);
+
+	ct = 0;
+	cl_assert_equal_i(
+		GIT_EUSER, git_tree_walk(tree, treewalk_stop_cb, GIT_TREEWALK_POST, &ct));
+	cl_assert_equal_i(2, ct);
+
+	cl_assert_equal_i(
+		GIT_EUSER, git_tree_walk(
+			tree, treewalk_stop_immediately_cb, GIT_TREEWALK_PRE, NULL));
+
+	cl_assert_equal_i(
+		GIT_EUSER, git_tree_walk(
+			tree, treewalk_stop_immediately_cb, GIT_TREEWALK_POST, NULL));
+
+	git_tree_free(tree);
+}