status: handle subdirs for git_status_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
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)
{