Commit 34dfea2774c10257eb13aae515d79ea2c224b911

Jason Penny 2011-06-24T20:36:53

status: handle subdirs for git_status_file

diff --git a/src/status.c b/src/status.c
index 60310c5..e421842 100644
--- a/src/status.c
+++ b/src/status.c
@@ -152,6 +152,35 @@ static void recurse_tree_entries(git_tree *tree, git_vector *entries, char *path
 	git_tree_close(tree);
 }
 
+static void recurse_tree_entry(git_tree *tree, struct status_entry *e, const char *path)
+{
+	char *dir_sep;
+	char buffer[GIT_PATH_MAX];
+	const git_tree_entry *tree_entry;
+	git_tree *subtree;
+
+	strcpy(buffer, path);
+
+	dir_sep = strchr(buffer, '/');
+	if (dir_sep) {
+		*dir_sep = '\0';
+
+		tree_entry = git_tree_entry_byname(tree, buffer);
+		if (tree_entry != NULL) {
+			if (git_tree_lookup(&subtree, tree->object.repo, &tree_entry->oid) == GIT_SUCCESS) {
+				recurse_tree_entry(subtree, e, dir_sep+1);
+				return;
+			}
+		}
+	}
+
+	tree_entry = git_tree_entry_byname(tree, path);
+	if (tree_entry != NULL) {
+		git_oid_cpy(&e->head_oid, &tree_entry->oid);
+	}
+	git_tree_close(tree);
+}
+
 static int workdir_path_len;
 static int dirent_cb(void *state, char *full_path)
 {
@@ -320,7 +349,6 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
 	git_tree *tree;
 	git_reference *head_ref, *resolved_head_ref;
 	git_commit *head_commit;
-	const git_tree_entry *tree_entry;
 
 	assert(status_flags);
 
@@ -342,12 +370,7 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
 	git_commit_lookup(&head_commit, repo, git_reference_oid(resolved_head_ref));
 
 	git_commit_tree(&tree, head_commit);
-	// TODO: handle subdirectories by walking into subtrees
-	tree_entry = git_tree_entry_byname(tree, path);
-	if (tree_entry != NULL) {
-		git_oid_cpy(&e->head_oid, &tree_entry->oid);
-	}
-	git_tree_close(tree);
+	recurse_tree_entry(tree, e, path);
 
 	// Find file in Workdir
 	workdir_path_len = strlen(repo->path_workdir);
diff --git a/tests/t18-status.c b/tests/t18-status.c
index f5899d4..3c8a296 100644
--- a/tests/t18-status.c
+++ b/tests/t18-status.c
@@ -68,6 +68,11 @@ static const char *entry_paths[] = {
 	"staged_new_file",
 	"staged_new_file_deleted_file",
 	"staged_new_file_modified_file",
+
+	"subdir/current_file",
+	"subdir/deleted_file",
+	"subdir/modified_file",
+	"subdir/new_file",
 };
 static const unsigned int entry_statuses[] = {
 	GIT_STATUS_CURRENT,
@@ -82,8 +87,13 @@ static const unsigned int entry_statuses[] = {
 	GIT_STATUS_INDEX_NEW,
 	GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_DELETED,
 	GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED,
+
+	GIT_STATUS_CURRENT,
+	GIT_STATUS_WT_DELETED,
+	GIT_STATUS_WT_MODIFIED,
+	GIT_STATUS_WT_NEW,
 };
-#define ENTRY_COUNT 12
+#define ENTRY_COUNT 16
 
 static unsigned int get_expected_entry_status(const char *path)
 {