status: Add a baseline field to git_status_options for comparing to trees other than HEAD
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 94 95 96 97
diff --git a/include/git2/status.h b/include/git2/status.h
index 6711139..4b86818 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -173,12 +173,16 @@ typedef enum {
* The `pathspec` is an array of path patterns to match (using
* fnmatch-style matching), or just an array of paths to match exactly if
* `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags.
+ *
+ * The `baseline` is the tree to be used for comparison to the working directory
+ * and index; defaults to HEAD.
*/
typedef struct {
unsigned int version;
git_status_show_t show;
unsigned int flags;
git_strarray pathspec;
+ git_tree *baseline;
} git_status_options;
#define GIT_STATUS_OPTIONS_VERSION 1
diff --git a/src/status.c b/src/status.c
index 03682bc..f547bd4 100644
--- a/src/status.c
+++ b/src/status.c
@@ -280,12 +280,16 @@ int git_status_list_new(
if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 ||
(error = git_repository_index(&index, repo)) < 0)
return error;
-
- /* if there is no HEAD, that's okay - we'll make an empty iterator */
- if ((error = git_repository_head_tree(&head, repo)) < 0) {
- if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH)
- goto done;
- giterr_clear();
+
+ if (opts != NULL && opts->baseline != NULL) {
+ head = opts->baseline;
+ } else {
+ /* if there is no HEAD, that's okay - we'll make an empty iterator */
+ if ((error = git_repository_head_tree(&head, repo)) < 0) {
+ if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH)
+ goto done;
+ giterr_clear();
+ }
}
/* refresh index from disk unless prevented */
@@ -377,7 +381,8 @@ done:
*out = status;
- git_tree_free(head);
+ if (opts == NULL || opts->baseline != head)
+ git_tree_free(head);
git_index_free(index);
return error;
diff --git a/tests/status/worktree.c b/tests/status/worktree.c
index 1345dbf..44ed324 100644
--- a/tests/status/worktree.c
+++ b/tests/status/worktree.c
@@ -1280,3 +1280,34 @@ void test_status_worktree__with_directory_in_pathlist(void)
git_status_list_free(statuslist);
}
+void test_status_worktree__at_head_parent(void)
+{
+ git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+ git_status_list *statuslist;
+ git_tree *parent_tree;
+ const git_status_entry *status;
+
+ cl_git_mkfile("empty_standard_repo/file1", "ping");
+ stage_and_commit(repo, "file1");
+
+ cl_git_pass(git_repository_head_tree(&parent_tree, repo));
+
+ cl_git_mkfile("empty_standard_repo/file2", "pong");
+ stage_and_commit(repo, "file2");
+
+ cl_git_rewritefile("empty_standard_repo/file2", "pyng");
+
+ opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
+ opts.baseline = parent_tree;
+ cl_git_pass(git_status_list_new(&statuslist, repo, &opts));
+
+ cl_assert_equal_sz(1, git_status_list_entrycount(statuslist));
+ status = git_status_byindex(statuslist, 0);
+ cl_assert(status != NULL);
+ cl_assert_equal_s("file2", status->index_to_workdir->old_file.path);
+ cl_assert_equal_i(GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, status->status);
+
+ git_tree_free(parent_tree);
+ git_status_list_free(statuslist);
+}