diff options
-rw-r--r-- | include/git2/repository.h | 6 | ||||
-rw-r--r-- | src/refs.h | 6 | ||||
-rw-r--r-- | src/repository.c | 21 | ||||
-rw-r--r-- | tests-clar/repo/state.c | 79 | ||||
-rw-r--r-- | tests-clar/reset/soft.c | 1 |
5 files changed, 98 insertions, 15 deletions
diff --git a/include/git2/repository.h b/include/git2/repository.h index d72431538..4d122265c 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -574,6 +574,12 @@ typedef enum { GIT_REPOSITORY_STATE_MERGE, GIT_REPOSITORY_STATE_REVERT, GIT_REPOSITORY_STATE_CHERRY_PICK, + GIT_REPOSITORY_STATE_BISECT, + GIT_REPOSITORY_STATE_REBASE, + GIT_REPOSITORY_STATE_REBASE_INTERACTIVE, + GIT_REPOSITORY_STATE_REBASE_MERGE, + GIT_REPOSITORY_STATE_APPLY_MAILBOX, + GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE, } git_repository_state_t; /** diff --git a/src/refs.h b/src/refs.h index 58e2fd558..3a1f8cf33 100644 --- a/src/refs.h +++ b/src/refs.h @@ -33,6 +33,12 @@ #define GIT_MERGE_HEAD_FILE "MERGE_HEAD" #define GIT_REVERT_HEAD_FILE "REVERT_HEAD" #define GIT_CHERRY_PICK_HEAD_FILE "CHERRY_PICK_HEAD" +#define GIT_BISECT_LOG_FILE "BISECT_LOG" +#define GIT_REBASE_MERGE_DIR "rebase-merge/" +#define GIT_REBASE_MERGE_INTERACTIVE_FILE GIT_REBASE_MERGE_DIR "interactive" +#define GIT_REBASE_APPLY_DIR "rebase-apply/" +#define GIT_REBASE_APPLY_REBASING_FILE GIT_REBASE_APPLY_DIR "rebasing" +#define GIT_REBASE_APPLY_APPLYING_FILE GIT_REBASE_APPLY_DIR "applying" #define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master" #define GIT_REFNAME_MAX 1024 diff --git a/src/repository.c b/src/repository.c index fa4604bee..0e416e0b8 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1541,6 +1541,10 @@ cleanup: return error; } +/** + * Loosely ported from git.git + * https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh#L198-289 + */ int git_repository_state(git_repository *repo) { git_buf repo_path = GIT_BUF_INIT; @@ -1548,15 +1552,30 @@ int git_repository_state(git_repository *repo) assert(repo); + if (!git_repository_head_detached(repo)) + return state; + if (git_buf_puts(&repo_path, repo->path_repository) < 0) return -1; - if (git_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE)) + if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE)) + state = GIT_REPOSITORY_STATE_REBASE_INTERACTIVE; + else if (git_path_contains_dir(&repo_path, GIT_REBASE_MERGE_DIR)) + state = GIT_REPOSITORY_STATE_REBASE_MERGE; + else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_REBASING_FILE)) + state = GIT_REPOSITORY_STATE_REBASE; + else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_APPLYING_FILE)) + state = GIT_REPOSITORY_STATE_APPLY_MAILBOX; + else if (git_path_contains_dir(&repo_path, GIT_REBASE_APPLY_DIR)) + state = GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE; + else if (git_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE)) state = GIT_REPOSITORY_STATE_MERGE; else if(git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE)) state = GIT_REPOSITORY_STATE_REVERT; else if(git_path_contains_file(&repo_path, GIT_CHERRY_PICK_HEAD_FILE)) state = GIT_REPOSITORY_STATE_CHERRY_PICK; + else if(git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE)) + state = GIT_REPOSITORY_STATE_BISECT; git_buf_free(&repo_path); return state; diff --git a/tests-clar/repo/state.c b/tests-clar/repo/state.c index 1ee84374c..c0aba1987 100644 --- a/tests-clar/repo/state.c +++ b/tests-clar/repo/state.c @@ -2,6 +2,7 @@ #include "buffer.h" #include "refs.h" #include "posix.h" +#include "fileops.h" static git_repository *_repo; static git_buf _path; @@ -17,31 +18,81 @@ void test_repo_state__cleanup(void) git_buf_free(&_path); } -void test_repo_state__none(void) +static void setup_simple_state(const char *filename) { - /* The repo should be at its default state */ - cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(_repo)); + cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), filename)); + git_futils_mkpath2file(git_buf_cstr(&_path), 0777); + cl_git_mkfile(git_buf_cstr(&_path), "dummy"); + + cl_git_pass(git_repository_detach_head(_repo)); } -void test_repo_state__merge(void) +static void assert_repo_state(git_repository_state_t state) { + cl_assert_equal_i(state, git_repository_state(_repo)); +} - /* Then it should recognise that .git/MERGE_HEAD and friends mean their respective states */ - cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), GIT_MERGE_HEAD_FILE)); - cl_git_mkfile(git_buf_cstr(&_path), "dummy"); - cl_assert_equal_i(GIT_REPOSITORY_STATE_MERGE, git_repository_state(_repo)); +void test_repo_state__none_with_HEAD_attached(void) +{ + assert_repo_state(GIT_REPOSITORY_STATE_NONE); +} + +void test_repo_state__none_with_HEAD_detached(void) +{ + cl_git_pass(git_repository_detach_head(_repo)); + assert_repo_state(GIT_REPOSITORY_STATE_NONE); +} + +void test_repo_state__merge(void) +{ + setup_simple_state(GIT_MERGE_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_MERGE); } void test_repo_state__revert(void) { - cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), GIT_REVERT_HEAD_FILE)); - cl_git_mkfile(git_buf_cstr(&_path), "dummy"); - cl_assert_equal_i(GIT_REPOSITORY_STATE_REVERT, git_repository_state(_repo)); + setup_simple_state(GIT_REVERT_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REVERT); } void test_repo_state__cherry_pick(void) { - cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), GIT_CHERRY_PICK_HEAD_FILE)); - cl_git_mkfile(git_buf_cstr(&_path), "dummy"); - cl_assert_equal_i(GIT_REPOSITORY_STATE_CHERRY_PICK, git_repository_state(_repo)); + setup_simple_state(GIT_CHERRY_PICK_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_CHERRY_PICK); +} + +void test_repo_state__bisect(void) +{ + setup_simple_state(GIT_BISECT_LOG_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_BISECT); +} + +void test_repo_state__rebase_interactive(void) +{ + setup_simple_state(GIT_REBASE_MERGE_INTERACTIVE_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE_INTERACTIVE); +} + +void test_repo_state__rebase_merge(void) +{ + setup_simple_state(GIT_REBASE_MERGE_DIR "whatever"); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE_MERGE); +} + +void test_repo_state__rebase(void) +{ + setup_simple_state(GIT_REBASE_APPLY_REBASING_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE); +} + +void test_repo_state__apply_mailbox(void) +{ + setup_simple_state(GIT_REBASE_APPLY_APPLYING_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX); +} + +void test_repo_state__apply_mailbox_or_rebase(void) +{ + setup_simple_state(GIT_REBASE_APPLY_DIR "whatever"); + assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE); } diff --git a/tests-clar/reset/soft.c b/tests-clar/reset/soft.c index 194137217..d51e3f1f1 100644 --- a/tests-clar/reset/soft.c +++ b/tests-clar/reset/soft.c @@ -117,6 +117,7 @@ void test_reset_soft__fails_when_merging(void) { git_buf merge_head_path = GIT_BUF_INIT; + cl_git_pass(git_repository_detach_head(repo)); cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n"); |