Commit f1587b97a11e3a7283b32f5af46b7d057b8be4c5

Ben Straub 2012-07-30T14:37:40

Checkout: use git_index_read_tree_with_stats. New variant of git_index_read_tree that fills in the 'total' field of a git_indexer_stats struct as it's walking the tree.

diff --git a/include/git2/index.h b/include/git2/index.h
index f863a60..85f8cfc 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -8,6 +8,7 @@
 #define INCLUDE_git_index_h__
 
 #include "common.h"
+#include "indexer.h"
 #include "types.h"
 #include "oid.h"
 
@@ -345,6 +346,20 @@ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry);
  */
 GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree);
 
+
+/**
+ * Read a tree into the index file with stats
+ *
+ * The current index contents will be replaced by the specified tree. The total
+ * node count is collected in stats.
+ *
+ * @param index an existing index object
+ * @param tree tree to read
+ * @param stats structure that receives the total node count
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_index_read_tree_with_stats(git_index *index, git_tree *tree, git_indexer_stats *stats);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/checkout.c b/src/checkout.c
index 81389a7..3eed002 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -191,8 +191,7 @@ int git_checkout_head(git_repository *repo, git_checkout_opts *opts, git_indexer
 	if (!git_repository_head_tree(&tree, repo)) {
 		git_index *idx;
 		if (!(retcode = git_repository_index(&idx, repo))) {
-			/* TODO: Make git_index_read_tree fill in stats->total */
-			if (!(retcode = git_index_read_tree(idx, tree))) {
+			if (!(retcode = git_index_read_tree_with_stats(idx, tree, stats))) {
 				retcode = git_tree_walk(tree, checkout_walker, GIT_TREEWALK_POST, &payload);
 			}
 			git_index_free(idx);
diff --git a/src/index.c b/src/index.c
index 89d4798..434c1f1 100644
--- a/src/index.c
+++ b/src/index.c
@@ -985,12 +985,19 @@ int git_index_entry_stage(const git_index_entry *entry)
 	return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT;
 }
 
+typedef struct read_tree_data {
+	git_index *index;
+	git_indexer_stats *stats;
+} read_tree_data;
+
 static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *data)
 {
-	git_index *index = data;
+	read_tree_data *rtd = data;
 	git_index_entry *entry = NULL;
 	git_buf path = GIT_BUF_INIT;
 
+	rtd->stats->total++;
+
 	if (git_tree_entry__is_tree(tentry))
 		return 0;
 
@@ -1005,7 +1012,7 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
 	entry->path = git_buf_detach(&path);
 	git_buf_free(&path);
 
-	if (index_insert(index, entry, 0) < 0) {
+	if (index_insert(rtd->index, entry, 0) < 0) {
 		index_entry_free(entry);
 		return -1;
 	}
@@ -1013,9 +1020,21 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
 	return 0;
 }
 
-int git_index_read_tree(git_index *index, git_tree *tree)
+int git_index_read_tree_with_stats(git_index *index, git_tree *tree, git_indexer_stats *stats)
 {
+	git_indexer_stats dummy_stats;
+	read_tree_data rtd = {index, NULL};
+
+	if (!stats) stats = &dummy_stats;
+	stats->total = 0;
+	rtd.stats = stats;
+
 	git_index_clear(index);
 
-	return git_tree_walk(tree, read_tree_cb, GIT_TREEWALK_POST, index);
+	return git_tree_walk(tree, read_tree_cb, GIT_TREEWALK_POST, &rtd);
+}
+
+int git_index_read_tree(git_index *index, git_tree *tree)
+{
+	return git_index_read_tree_with_stats(index, tree, NULL);
 }