diff options
author | Patrick Steinhardt <ps@pks.im> | 2019-10-18 12:14:19 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2019-10-18 12:26:56 +0200 |
commit | 8532ed11848092d816aecc2d34d1bb432a525df9 (patch) | |
tree | 52f488f1ce7e5113f3ad83b3ee549b3173fac0ba | |
parent | d8233feb78d10ade39fd64b85044fea84f2fc293 (diff) | |
download | libgit2-8532ed11848092d816aecc2d34d1bb432a525df9.tar.gz |
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.
-rw-r--r-- | src/parse.c | 10 | ||||
-rw-r--r-- | src/parse.h | 1 | ||||
-rw-r--r-- | src/refdb_fs.c | 75 |
3 files changed, 42 insertions, 44 deletions
diff --git a/src/parse.c b/src/parse.c index b04fda36b..0a10758bf 100644 --- a/src/parse.c +++ b/src/parse.c @@ -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; diff --git a/src/parse.h b/src/parse.h index 188ac281c..0ecb7c103 100644 --- a/src/parse.h +++ b/src/parse.h @@ -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) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 449dedfba..1bf300c79 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -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; |