repository: add a getter and remove function for git's prepared message The 'git revert/cherry-pick/merge -n' commands leave .git/MERGE_MSG behind so that git-commit can find it. As we don't yet support these operations, users who are shelling out to let git perform these operations haven't had a convenient way to get this message. These functions allow the user to retrieve the message and remove it when she's created the commit.
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
diff --git a/include/git2/repository.h b/include/git2/repository.h
index ef2f541..e727ff3 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -315,6 +315,28 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
*/
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
+/**
+ * Retrive git's prepared message
+ *
+ * Operations such as git revert/cherry-pick/merge with the -n option
+ * stop just short of creating a commit with the changes and save
+ * their prepared message in .git/MERGE_MSG so the next git-commit
+ * execution can present it to the user for them to amend if they
+ * wish.
+ *
+ * Use this function to get the contents of this file. Don't forget to
+ * remove the file after you create the commit.
+ */
+GIT_EXTERN(int) git_repository_message(char *buffer, size_t len, git_repository *repo);
+
+/**
+ * Remove git's prepared message.
+ *
+ * Remove the message that `git_repository_message` retrieves.
+ */
+GIT_EXTERN(int) git_repository_message_remove(git_repository *repo);
+
+
/** @} */
GIT_END_DECL
#endif
diff --git a/src/repository.c b/src/repository.c
index e0104f3..ba29203 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1071,3 +1071,59 @@ int git_repository_head_tree(git_tree **tree, git_repository *repo)
*tree = (git_tree *)obj;
return 0;
}
+
+#define MERGE_MSG_FILE "MERGE_MSG"
+
+int git_repository_message(char *buffer, size_t len, git_repository *repo)
+{
+ git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+ struct stat st;
+ ssize_t size;
+ int error;
+
+ if (git_buf_joinpath(&path, repo->path_repository, MERGE_MSG_FILE) < 0)
+ return -1;
+
+ error = p_stat(git_buf_cstr(&path), &st);
+ if (error < 0) {
+ if (errno == ENOENT)
+ error = GIT_ENOTFOUND;
+
+ git_buf_free(&path);
+ return error;
+ }
+
+ if (buffer == NULL) {
+ git_buf_free(&path);
+ return st.st_size;
+ }
+
+ if (git_futils_readbuffer(&buf, git_buf_cstr(&path)) < 0)
+ goto on_error;
+
+ memcpy(buffer, git_buf_cstr(&buf), len);
+ size = git_buf_len(&buf);
+
+ git_buf_free(&path);
+ git_buf_free(&buf);
+ return size;
+
+on_error:
+ git_buf_free(&path);
+ return -1;
+
+}
+
+int git_repository_message_remove(git_repository *repo)
+{
+ git_buf path = GIT_BUF_INIT;
+ int error;
+
+ if (git_buf_joinpath(&path, repo->path_repository, MERGE_MSG_FILE) < 0)
+ return -1;
+
+ error = p_unlink(git_buf_cstr(&path));
+ git_buf_free(&path);
+
+ return error;
+}
diff --git a/tests-clar/repo/message.c b/tests-clar/repo/message.c
new file mode 100644
index 0000000..4a6f13b
--- /dev/null
+++ b/tests-clar/repo/message.c
@@ -0,0 +1,47 @@
+#include "clar_libgit2.h"
+#include "buffer.h"
+#include "refs.h"
+#include "posix.h"
+
+static git_repository *_repo;
+static git_buf _path;
+static char *_actual;
+
+void test_repo_message__initialize(void)
+{
+ _repo = cl_git_sandbox_init("testrepo.git");
+}
+
+void test_repo_message__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+ git_buf_free(&_path);
+ git__free(_actual);
+ _actual = NULL;
+}
+
+void test_repo_message__none(void)
+{
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo));
+}
+
+void test_repo_message__message(void)
+{
+ const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n";
+ ssize_t len;
+
+ cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG"));
+ cl_git_mkfile(git_buf_cstr(&_path), expected);
+
+ len = git_repository_message(NULL, 0, _repo);
+ cl_assert(len > 0);
+ _actual = git__malloc(len + 1);
+ cl_assert(_actual != NULL);
+
+ cl_assert(git_repository_message(_actual, len, _repo) > 0);
+ _actual[len] = '\0';
+ cl_assert_equal_s(expected, _actual);
+
+ cl_git_pass(p_unlink(git_buf_cstr(&_path)));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo));
+}