Commit 8532ed11 by Patrick Steinhardt

refdb_fs: convert reflog parsing to use parser

The refdb_fs code to parse the reflog currently uses a hand-rolled
parser. Convert it to use our `git_parse_ctx` structure instead.
parent d8233feb
......@@ -101,6 +101,16 @@ int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base)
return 0;
}
int git_parse_advance_oid(git_oid *out, git_parse_ctx *ctx)
{
if (ctx->line_len < GIT_OID_HEXSZ)
return -1;
if ((git_oid_fromstrn(out, ctx->line, GIT_OID_HEXSZ)) < 0)
return -1;
git_parse_advance_chars(ctx, GIT_OID_HEXSZ);
return 0;
}
int git_parse_peek(char *out, git_parse_ctx *ctx, int flags)
{
size_t remain = ctx->line_len;
......
......@@ -50,6 +50,7 @@ int git_parse_advance_expected(
int git_parse_advance_ws(git_parse_ctx *ctx);
int git_parse_advance_nl(git_parse_ctx *ctx);
int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base);
int git_parse_advance_oid(git_oid *out, git_parse_ctx *ctx);
enum GIT_PARSE_PEEK_FLAGS {
GIT_PARSE_PEEK_SKIP_WHITESPACE = (1 << 0)
......
......@@ -13,6 +13,7 @@
#include "futils.h"
#include "filebuf.h"
#include "pack.h"
#include "parse.h"
#include "reflog.h"
#include "refdb.h"
#include "iterator.h"
......@@ -1651,67 +1652,53 @@ static int reflog_alloc(git_reflog **reflog, const char *name)
static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size)
{
const char *ptr;
git_reflog_entry *entry;
git_parse_ctx parser = GIT_PARSE_CTX_INIT;
git_reflog_entry *entry = NULL;
#define seek_forward(_increase) do { \
if (_increase >= buf_size) { \
git_error_set(GIT_ERROR_INVALID, "ran out of data while parsing reflog"); \
goto fail; \
} \
buf += _increase; \
buf_size -= _increase; \
} while (0)
while (buf_size > GIT_REFLOG_SIZE_MIN) {
entry = git__calloc(1, sizeof(git_reflog_entry));
GIT_ERROR_CHECK_ALLOC(entry);
if ((git_parse_ctx_init(&parser, buf, buf_size)) < 0)
return -1;
entry->committer = git__calloc(1, sizeof(git_signature));
GIT_ERROR_CHECK_ALLOC(entry->committer);
for (; parser.remain_len; git_parse_advance_line(&parser)) {
const char *sig;
char c;
if (git_oid_fromstrn(&entry->oid_old, buf, GIT_OID_HEXSZ) < 0)
goto fail;
seek_forward(GIT_OID_HEXSZ + 1);
entry = git__calloc(1, sizeof(*entry));
GIT_ERROR_CHECK_ALLOC(entry);
if (git_oid_fromstrn(&entry->oid_cur, buf, GIT_OID_HEXSZ) < 0)
goto fail;
seek_forward(GIT_OID_HEXSZ + 1);
entry->committer = git__calloc(1, sizeof(*entry->committer));
GIT_ERROR_CHECK_ALLOC(entry->committer);
ptr = buf;
if (git_parse_advance_oid(&entry->oid_old, &parser) < 0 ||
git_parse_advance_expected(&parser, " ", 1) < 0 ||
git_parse_advance_oid(&entry->oid_cur, &parser) < 0)
goto error;
/* Seek forward to the end of the signature. */
while (*buf && *buf != '\t' && *buf != '\n')
seek_forward(1);
sig = parser.line;
while (git_parse_peek(&c, &parser, 0) == 0 && c != '\t' && c != '\n')
git_parse_advance_chars(&parser, 1);
if (git_signature__parse(entry->committer, &ptr, buf + 1, NULL, *buf) < 0)
goto fail;
if (git_signature__parse(entry->committer, &sig, parser.line, NULL, 0) < 0)
goto error;
if (*buf == '\t') {
/* We got a message. Read everything till we reach LF. */
seek_forward(1);
ptr = buf;
if (c == '\t') {
size_t len;
git_parse_advance_chars(&parser, 1);
while (*buf && *buf != '\n')
seek_forward(1);
len = parser.line_len;
if (parser.line[len - 1] == '\n')
len--;
entry->msg = git__strndup(ptr, buf - ptr);
entry->msg = git__strndup(parser.line, len);
GIT_ERROR_CHECK_ALLOC(entry->msg);
} else
entry->msg = NULL;
while (*buf && *buf == '\n' && buf_size > 1)
seek_forward(1);
}
if (git_vector_insert(&log->entries, entry) < 0)
goto fail;
goto error;
}
return 0;
#undef seek_forward
fail:
error:
git_reflog_entry__free(entry);
return -1;
......
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