Commit 05e286fb by Patrick Steinhardt

grafts: move parsing into grafts module

Parsing of grafts files is currently contained in the repository code.
To make grafts-related logic more self-contained, move it into
"grafts.c" instead.
parent 14a309ab
......@@ -108,7 +108,8 @@ typedef enum {
GIT_ERROR_WORKTREE,
GIT_ERROR_SHA1,
GIT_ERROR_HTTP,
GIT_ERROR_INTERNAL
GIT_ERROR_INTERNAL,
GIT_ERROR_GRAFTS
} git_error_t;
/**
......
......@@ -7,6 +7,8 @@
#include "grafts.h"
#include "parse.h"
struct git_grafts {
/* Map of `git_commit_graft`s */
git_oidmap *commits;
......@@ -51,6 +53,50 @@ void git_grafts_clear(git_grafts *grafts)
git_oidmap_clear(grafts->commits);
}
int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen)
{
git_array_oid_t parents = GIT_ARRAY_INIT;
git_parse_ctx parser;
int error;
git_grafts_clear(grafts);
if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0)
goto error;
for (; parser.remain_len; git_parse_advance_line(&parser)) {
const char *line_start = parser.line, *line_end = parser.line + parser.line_len;
git_oid graft_oid;
if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num);
goto error;
}
line_start += GIT_OID_HEXSZ;
while (line_start < line_end && *line_start == ' ') {
git_oid *id = git_array_alloc(parents);
GIT_ERROR_CHECK_ALLOC(id);
if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num);
goto error;
}
line_start += GIT_OID_HEXSZ;
}
if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0)
goto error;
git_array_clear(parents);
}
error:
git_array_clear(parents);
return error;
}
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents)
{
git_commit_graft *graft;
......
......@@ -23,6 +23,7 @@ int git_grafts_new(git_grafts **out);
void git_grafts_free(git_grafts *grafts);
void git_grafts_clear(git_grafts *grafts);
int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen);
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents);
int git_grafts_remove(git_grafts *grafts, const git_oid *oid);
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid);
......
......@@ -31,7 +31,6 @@
#include "annotated_commit.h"
#include "submodule.h"
#include "worktree.h"
#include "parse.h"
#include "strmap.h"
......@@ -582,10 +581,8 @@ out:
static int load_grafts(git_repository *repo)
{
git_array_oid_t parents = GIT_ARRAY_INIT;
git_buf graft_path = GIT_BUF_INIT;
git_buf contents = GIT_BUF_INIT;
git_parse_ctx parser;
int error, updated;
if ((error = git_repository_item_path(&graft_path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
......@@ -604,42 +601,10 @@ static int load_grafts(git_repository *repo)
goto cleanup;
}
git_grafts_clear(repo->grafts);
if ((error = git_parse_ctx_init(&parser, contents.ptr, contents.size)) < 0)
goto cleanup;
for (; parser.remain_len; git_parse_advance_line(&parser)) {
const char *line_start = parser.line, *line_end = parser.line + parser.line_len;
git_oid graft_oid;
if (git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ) < 0)
goto invalid_oid;
line_start += GIT_OID_HEXSZ;
while (line_start < line_end && *line_start == ' ') {
git_oid *id = git_array_alloc(parents);
GIT_ERROR_CHECK_ALLOC(id);
if (git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ) < 0)
goto invalid_oid;
line_start += GIT_OID_HEXSZ;
}
if ((error = git_grafts_add(repo->grafts, &graft_oid, parents)) < 0)
goto cleanup;
git_array_clear(parents);
continue;
invalid_oid:
git_error_set(GIT_ERROR_REPOSITORY, "invalid OID at line %" PRIuZ, parser.line_num);
error = -1;
if ((error = git_grafts_parse(repo->grafts, contents.ptr, contents.size)) < 0)
goto cleanup;
}
cleanup:
git_array_clear(parents);
git_buf_dispose(&contents);
git_buf_dispose(&graft_path);
......
#include "clar_libgit2.h"
#include "grafts.h"
#define OID0 "c0368f9f9743e950e6cfe1f45a649f8a9dfcd97e"
#define OID1 "cfc50a0db87ce908fb8a8c5b8f7b4ab96eee8643"
#define OID2 "6914d97cd08b9edf5e855fca211c750fa82fd80a"
#define OID3 "516521937d0e9ce9d0d836149a0702671f326b4a"
#define OID4 "e2c29d67ef2f217650196f94c796f0532b8caad6"
#define OID5 "79bcb936596cb50353fe7be28b7444e66e4a2842"
#define OID6 "b9c54107d57c17dbcaf646c4d52f66eb9e69d23d"
#define OID7 "9f8a746e9ad7b58cc840016bc3944d5ad262acb5"
#define OID8 "392f4beef7d0d15b2bc5b1abe1a754eba0ec36da"
#define OID_TRUNCATED "392f4beef7d0d15b2bc5b1abe1a754eba0ec36d"
#define OID_NONHEX "9f8a746e9ax7b58cc840016bc3944d5ad262acb5"
static git_grafts *grafts;
void test_grafts_parse__initialize(void)
{
cl_git_pass(git_grafts_new(&grafts));
}
void test_grafts_parse__cleanup(void)
{
git_grafts_free(grafts);
grafts = NULL;
}
static void assert_parse_succeeds(git_grafts *grafts, const char *string, size_t n)
{
cl_git_pass(git_grafts_parse(grafts, string, strlen(string)));
cl_assert_equal_i(git_grafts_size(grafts), n);
}
static void assert_parse_fails(git_grafts *grafts, const char *string)
{
cl_git_fail(git_grafts_parse(grafts, string, strlen(string)));
}
static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t n, ...)
{
git_commit_graft *commit;
git_oid oid;
va_list ap;
size_t i = 0;
cl_git_pass(git_oid_fromstr(&oid, graft));
cl_git_pass(git_grafts_get(&commit, grafts, &oid));
cl_assert_equal_oid(&commit->oid, &oid);
cl_assert_equal_i(commit->parents.size, n);
va_start(ap, n);
while (i < n) {
cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *)));
cl_assert_equal_oid(&commit->parents.ptr[i], &oid);
i++;
}
va_end(ap);
}
void test_grafts_parse__single_oid(void)
{
assert_parse_succeeds(grafts, OID1, 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__single_oid_with_newline(void)
{
assert_parse_succeeds(grafts, OID1 "\n", 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__multiple_oids(void)
{
assert_parse_succeeds(grafts, OID1 "\n" OID2 "\n" OID3, 3);
assert_graft_contains(grafts, OID1, 0);
assert_graft_contains(grafts, OID2, 0);
assert_graft_contains(grafts, OID3, 0);
}
void test_grafts_parse__same_oid(void)
{
assert_parse_succeeds(grafts, OID1 "\n" OID1, 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__oid_with_parent(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2, 1);
assert_graft_contains(grafts, OID1, 1, OID2);
}
void test_grafts_parse__oid_with_parent_and_newline(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2 "\n", 1);
assert_graft_contains(grafts, OID1, 1, OID2);
}
void test_grafts_parse__oid_with_multiple_parents(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2 " " OID3 " " OID4 " " OID5, 1);
assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5);
}
void test_grafts_parse__multiple_oids_with_multiple_parents(void)
{
assert_parse_succeeds(grafts,
OID1 " " OID2 " " OID3 " " OID4 " " OID5 "\n"
OID6 " " OID7 " " OID8 "\n" , 2);
assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5);
assert_graft_contains(grafts, OID6, 2, OID7, OID8);
}
void test_grafts_parse__multiple_spaces_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID2);
}
void test_grafts_parse__trailing_space_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID2 " ");
}
void test_grafts_parse__invalid_character_inbetween_fails(void)
{
assert_parse_fails(grafts, OID1 " x " OID2);
}
void test_grafts_parse__truncated_oid_fails(void)
{
assert_parse_fails(grafts, OID_TRUNCATED);
}
void test_grafts_parse__truncated_parent_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID_TRUNCATED);
}
void test_grafts_parse__invalid_oid_fails(void)
{
assert_parse_fails(grafts, OID_NONHEX);
}
void test_grafts_parse__invalid_parent_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID_NONHEX);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment