mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 10:03:43 +00:00
Rev-parse: add "tag:README" syntax.
This commit is contained in:
parent
dd9e4abc1b
commit
244d2f6b80
@ -10,6 +10,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
#include "git2.h"
|
#include "git2.h"
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ typedef enum {
|
|||||||
REVPARSE_STATE_INIT,
|
REVPARSE_STATE_INIT,
|
||||||
REVPARSE_STATE_CARET,
|
REVPARSE_STATE_CARET,
|
||||||
REVPARSE_STATE_LINEAR,
|
REVPARSE_STATE_LINEAR,
|
||||||
|
REVPARSE_STATE_COLON,
|
||||||
REVPARSE_STATE_DONE,
|
REVPARSE_STATE_DONE,
|
||||||
} revparse_state;
|
} revparse_state;
|
||||||
|
|
||||||
@ -535,6 +537,45 @@ static int handle_linear_syntax(git_object **out, git_object *obj, const char *m
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const git_tree_entry* git_tree_entry_bypath(git_tree *tree, git_repository *repo, const char *path)
|
||||||
|
{
|
||||||
|
char *str = git__strdup(path);
|
||||||
|
char *tok;
|
||||||
|
git_tree *tree2 = tree;
|
||||||
|
const git_tree_entry *entry;
|
||||||
|
|
||||||
|
while ((tok = git__strtok(&str, "/\\")) != NULL) {
|
||||||
|
entry = git_tree_entry_byname(tree2, tok);
|
||||||
|
if (tree2 != tree) git_tree_free(tree2);
|
||||||
|
if (entry_is_tree(entry)) {
|
||||||
|
if (git_tree_lookup(&tree2, repo, &entry->oid) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_colon_syntax(git_object **out,
|
||||||
|
git_repository *repo,
|
||||||
|
git_object *obj,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
git_tree *tree;
|
||||||
|
const git_tree_entry *entry;
|
||||||
|
|
||||||
|
/* Dereference until we reach a tree. */
|
||||||
|
if (dereference_to_type(&obj, obj, GIT_OBJ_TREE) < 0) {
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
tree = (git_tree*)obj;
|
||||||
|
|
||||||
|
/* Find the blob at the given path. */
|
||||||
|
entry = git_tree_entry_bypath(tree, repo, path);
|
||||||
|
return git_tree_entry_2object(out, repo, entry);
|
||||||
|
}
|
||||||
|
|
||||||
int git_revparse_single(git_object **out, git_repository *repo, const char *spec)
|
int git_revparse_single(git_object **out, git_repository *repo, const char *spec)
|
||||||
{
|
{
|
||||||
revparse_state current_state = REVPARSE_STATE_INIT, next_state = REVPARSE_STATE_INIT;
|
revparse_state current_state = REVPARSE_STATE_INIT, next_state = REVPARSE_STATE_INIT;
|
||||||
@ -545,6 +586,13 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
|
|
||||||
assert(out && repo && spec);
|
assert(out && repo && spec);
|
||||||
|
|
||||||
|
if (spec[0] == ':') {
|
||||||
|
/* Either a global grep (":/foo") or a merge-stage path lookup (":2:Makefile").
|
||||||
|
Neither of these are handled just yet. */
|
||||||
|
giterr_set(GITERR_INVALID, "Unimplemented");
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
while (current_state != REVPARSE_STATE_DONE) {
|
while (current_state != REVPARSE_STATE_DONE) {
|
||||||
switch (current_state) {
|
switch (current_state) {
|
||||||
case REVPARSE_STATE_INIT:
|
case REVPARSE_STATE_INIT:
|
||||||
@ -561,6 +609,8 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
next_state = REVPARSE_STATE_CARET;
|
next_state = REVPARSE_STATE_CARET;
|
||||||
} else if (*spec_cur == '~') {
|
} else if (*spec_cur == '~') {
|
||||||
next_state = REVPARSE_STATE_LINEAR;
|
next_state = REVPARSE_STATE_LINEAR;
|
||||||
|
} else if (*spec_cur == ':') {
|
||||||
|
next_state = REVPARSE_STATE_COLON;
|
||||||
} else {
|
} else {
|
||||||
git_buf_putc(&specbuffer, *spec_cur);
|
git_buf_putc(&specbuffer, *spec_cur);
|
||||||
}
|
}
|
||||||
@ -617,6 +667,16 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
spec_cur++;
|
spec_cur++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case REVPARSE_STATE_COLON:
|
||||||
|
if (*spec_cur) {
|
||||||
|
git_buf_putc(&stepbuffer, *spec_cur);
|
||||||
|
} else {
|
||||||
|
retcode = handle_colon_syntax(out, repo, cur_obj, git_buf_cstr(&stepbuffer));
|
||||||
|
next_state = REVPARSE_STATE_DONE;
|
||||||
|
}
|
||||||
|
spec_cur++;
|
||||||
|
break;
|
||||||
|
|
||||||
case REVPARSE_STATE_DONE:
|
case REVPARSE_STATE_DONE:
|
||||||
if (cur_obj && *out != cur_obj) git_object_free(cur_obj);
|
if (cur_obj && *out != cur_obj) git_object_free(cur_obj);
|
||||||
if (next_obj && *out != next_obj) git_object_free(next_obj);
|
if (next_obj && *out != next_obj) git_object_free(next_obj);
|
||||||
|
@ -153,3 +153,13 @@ void test_refs_revparse__date(void)
|
|||||||
/* Core git gives a65fedf, because they don't take time zones into account. */
|
/* Core git gives a65fedf, because they don't take time zones into account. */
|
||||||
test_object("master@{1335806640}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
test_object("master@{1335806640}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_refs_revparse__colon(void)
|
||||||
|
{
|
||||||
|
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":/foo"));
|
||||||
|
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README"));
|
||||||
|
|
||||||
|
test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f");
|
||||||
|
test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
|
||||||
|
test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user