mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 18:03:54 +00:00
Rev-parse: "ref^{/regex}" syntax.
This commit is contained in:
parent
bae780e084
commit
886f183ac3
@ -20,6 +20,7 @@
|
|||||||
#include "git2/refs.h"
|
#include "git2/refs.h"
|
||||||
#include "git2/repository.h"
|
#include "git2/repository.h"
|
||||||
#include "git2/config.h"
|
#include "git2/config.h"
|
||||||
|
#include "git2/revwalk.h"
|
||||||
|
|
||||||
GIT_BEGIN_DECL
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
@ -294,7 +295,7 @@ static git_otype parse_obj_type(const char *str)
|
|||||||
return GIT_OBJ_BAD;
|
return GIT_OBJ_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_caret_syntax(git_object **out, git_object *obj, const char *movement)
|
static int handle_caret_syntax(git_object **out, git_repository *repo, git_object *obj, const char *movement)
|
||||||
{
|
{
|
||||||
git_commit *commit;
|
git_commit *commit;
|
||||||
size_t movementlen = strlen(movement);
|
size_t movementlen = strlen(movement);
|
||||||
@ -325,8 +326,48 @@ static int handle_caret_syntax(git_object **out, git_object *obj, const char *mo
|
|||||||
|
|
||||||
/* {/...} -> Walk all commits until we see a commit msg that matches the phrase. */
|
/* {/...} -> Walk all commits until we see a commit msg that matches the phrase. */
|
||||||
if (movement[1] == '/') {
|
if (movement[1] == '/') {
|
||||||
/* TODO */
|
int retcode = GIT_ERROR;
|
||||||
return GIT_ERROR;
|
git_revwalk *walk;
|
||||||
|
if (!git_revwalk_new(&walk, repo)) {
|
||||||
|
git_oid oid;
|
||||||
|
regex_t preg;
|
||||||
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
|
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
||||||
|
git_revwalk_push(walk, git_object_id(obj));
|
||||||
|
|
||||||
|
/* Extract the regex from the movement string */
|
||||||
|
git_buf_put(&buf, movement+2, strlen(movement)-3);
|
||||||
|
|
||||||
|
if (!regcomp(&preg, git_buf_cstr(&buf), REG_EXTENDED)) {
|
||||||
|
while(!git_revwalk_next(&oid, walk)) {
|
||||||
|
git_object *walkobj;
|
||||||
|
char str[41];
|
||||||
|
git_oid_fmt(str, &oid);
|
||||||
|
str[40] = 0;
|
||||||
|
|
||||||
|
/* Fetch the commit object, and check for matches in the message */
|
||||||
|
if (!git_object_lookup(&walkobj, repo, &oid, GIT_OBJ_COMMIT)) {
|
||||||
|
if (!regexec(&preg, git_commit_message((git_commit*)walkobj), 0, NULL, 0)) {
|
||||||
|
/* Found it! */
|
||||||
|
retcode = 0;
|
||||||
|
*out = walkobj;
|
||||||
|
if (obj == walkobj) {
|
||||||
|
/* Avoid leaking an object */
|
||||||
|
git_object_free(walkobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
git_object_free(walkobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
regfree(&preg);
|
||||||
|
}
|
||||||
|
|
||||||
|
git_buf_free(&buf);
|
||||||
|
git_revwalk_free(walk);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {...} -> Dereference until we reach an object of a certain type. */
|
/* {...} -> Dereference until we reach an object of a certain type. */
|
||||||
@ -444,14 +485,14 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
case REVPARSE_STATE_CARET:
|
case REVPARSE_STATE_CARET:
|
||||||
/* Gather characters until NULL, '~', or '^' */
|
/* Gather characters until NULL, '~', or '^' */
|
||||||
if (!*spec_cur) {
|
if (!*spec_cur) {
|
||||||
retcode = handle_caret_syntax(out, cur_obj, git_buf_cstr(&stepbuffer));
|
retcode = handle_caret_syntax(out, repo, cur_obj, git_buf_cstr(&stepbuffer));
|
||||||
next_state = REVPARSE_STATE_DONE;
|
next_state = REVPARSE_STATE_DONE;
|
||||||
} else if (*spec_cur == '~') {
|
} else if (*spec_cur == '~') {
|
||||||
retcode = handle_caret_syntax(&next_obj, cur_obj, git_buf_cstr(&stepbuffer));
|
retcode = handle_caret_syntax(&next_obj, repo, cur_obj, git_buf_cstr(&stepbuffer));
|
||||||
git_buf_clear(&stepbuffer);
|
git_buf_clear(&stepbuffer);
|
||||||
next_state = !retcode ? REVPARSE_STATE_LINEAR : REVPARSE_STATE_DONE;
|
next_state = !retcode ? REVPARSE_STATE_LINEAR : REVPARSE_STATE_DONE;
|
||||||
} else if (*spec_cur == '^') {
|
} else if (*spec_cur == '^') {
|
||||||
retcode = handle_caret_syntax(&next_obj, cur_obj, git_buf_cstr(&stepbuffer));
|
retcode = handle_caret_syntax(&next_obj, repo, cur_obj, git_buf_cstr(&stepbuffer));
|
||||||
git_buf_clear(&stepbuffer);
|
git_buf_clear(&stepbuffer);
|
||||||
if (retcode < 0) {
|
if (retcode < 0) {
|
||||||
next_state = REVPARSE_STATE_DONE;
|
next_state = REVPARSE_STATE_DONE;
|
||||||
|
@ -122,6 +122,21 @@ void test_refs_revparse__reflog(void)
|
|||||||
test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_revparse__revwalk(void)
|
||||||
|
{
|
||||||
|
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/not found in any commit}"));
|
||||||
|
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/merge}"));
|
||||||
|
|
||||||
|
test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||||
|
test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
|
test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||||
|
test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_revparse__date(void)
|
||||||
|
{
|
||||||
/* Not ready yet
|
/* Not ready yet
|
||||||
test_object("HEAD@{100 years ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
test_object("HEAD@{100 years ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||||
test_object("master@{2012-4-30 10:23:20}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
test_object("master@{2012-4-30 10:23:20}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
|
Loading…
Reference in New Issue
Block a user