diff options
author | Russell Belfer <rb@github.com> | 2012-05-09 02:03:59 +0400 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2012-05-09 02:03:59 +0400 |
commit | 7e000ab2ece977a028e3f1327de37342bef9f687 (patch) | |
tree | 5955c21f0174237dfa0f2b99b9de8016862aeb54 | |
parent | 364f51bdca8cd5bb11bb322f8cac1b0d7dfcf686 (diff) |
Add support for diffing index with no HEAD
When a repo is first created, there is no HEAD yet and attempting
to diff files in the index was showing nothing because a tree
iterator could not be constructed. This adds an "empty" iterator
and falls back on that when the head cannot be looked up.
-rw-r--r-- | src/diff.c | 2 | ||||
-rw-r--r-- | src/iterator.c | 49 | ||||
-rw-r--r-- | src/iterator.h | 3 | ||||
-rw-r--r-- | src/status.c | 2 | ||||
-rw-r--r-- | tests-clar/status/worktree.c | 45 |
5 files changed, 98 insertions, 3 deletions
diff --git a/src/diff.c b/src/diff.c index 524cc9f59..fed22f403 100644 --- a/src/diff.c +++ b/src/diff.c @@ -631,7 +631,7 @@ int git_diff_index_to_tree( { git_iterator *a = NULL, *b = NULL; - assert(repo && old_tree && diff); + assert(repo && diff); if (git_iterator_for_tree(repo, old_tree, &a) < 0 || git_iterator_for_index(repo, &b) < 0) diff --git a/src/iterator.c b/src/iterator.c index 3a3be1755..646990d3f 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -11,6 +11,48 @@ #include "buffer.h" #include "git2/submodule.h" +static int empty_iterator__no_item( + git_iterator *iter, const git_index_entry **entry) +{ + GIT_UNUSED(iter); + *entry = NULL; + return 0; +} + +static int empty_iterator__at_end(git_iterator *iter) +{ + GIT_UNUSED(iter); + return 1; +} + +static int empty_iterator__noop(git_iterator *iter) +{ + GIT_UNUSED(iter); + return 0; +} + +static void empty_iterator__free(git_iterator *iter) +{ + GIT_UNUSED(iter); +} + +int git_iterator_for_nothing(git_iterator **iter) +{ + git_iterator *i = git__calloc(1, sizeof(git_iterator)); + GITERR_CHECK_ALLOC(i); + + i->type = GIT_ITERATOR_EMPTY; + i->current = empty_iterator__no_item; + i->at_end = empty_iterator__at_end; + i->advance = empty_iterator__no_item; + i->reset = empty_iterator__noop; + i->free = empty_iterator__free; + + *iter = i; + + return 0; +} + typedef struct tree_iterator_frame tree_iterator_frame; struct tree_iterator_frame { tree_iterator_frame *next; @@ -155,7 +197,12 @@ int git_iterator_for_tree( git_repository *repo, git_tree *tree, git_iterator **iter) { int error; - tree_iterator *ti = git__calloc(1, sizeof(tree_iterator)); + tree_iterator *ti; + + if (tree == NULL) + return git_iterator_for_nothing(iter); + + ti = git__calloc(1, sizeof(tree_iterator)); GITERR_CHECK_ALLOC(ti); ti->base.type = GIT_ITERATOR_TREE; diff --git a/src/iterator.h b/src/iterator.h index aa78c9f29..12eb96bb0 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -13,6 +13,7 @@ typedef struct git_iterator git_iterator; typedef enum { + GIT_ITERATOR_EMPTY = 0, GIT_ITERATOR_TREE = 1, GIT_ITERATOR_INDEX = 2, GIT_ITERATOR_WORKDIR = 3 @@ -27,6 +28,8 @@ struct git_iterator { void (*free)(git_iterator *); }; +int git_iterator_for_nothing(git_iterator **iter); + int git_iterator_for_tree( git_repository *repo, git_tree *tree, git_iterator **iter); diff --git a/src/status.c b/src/status.c index 546dc863d..d07b0c41c 100644 --- a/src/status.c +++ b/src/status.c @@ -101,7 +101,7 @@ int git_status_foreach_ext( diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS; /* TODO: support EXCLUDE_SUBMODULES flag */ - if (show != GIT_STATUS_SHOW_WORKDIR_ONLY && head != NULL && + if (show != GIT_STATUS_SHOW_WORKDIR_ONLY && (err = git_diff_index_to_tree(repo, &diffopt, head, &idx2head)) < 0) goto cleanup; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index c4c935c0d..4ac556aa6 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -401,3 +401,48 @@ void test_status_worktree__cannot_retrieve_the_status_of_a_bare_repository(void) git_repository_free(repo); } + +typedef struct { + int count; + unsigned int status; +} status_entry_single; + +static int +cb_status__single(const char *p, unsigned int s, void *payload) +{ + status_entry_single *data = (status_entry_single *)payload; + + GIT_UNUSED(p); + + data->count++; + data->status = s; + + return 0; +} + +void test_status_worktree__first_commit_in_progress(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + + cl_git_pass(git_repository_init(&repo, "getting_started", 0)); + cl_git_mkfile("getting_started/testfile.txt", "content\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert(result.count == 1); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add(index, "testfile.txt", 0)); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert(result.count == 1); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + git_index_free(index); + git_repository_free(repo); +} |