summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-10-18 12:14:19 +0200
committerPatrick Steinhardt <ps@pks.im>2019-10-18 12:26:56 +0200
commit8532ed11848092d816aecc2d34d1bb432a525df9 (patch)
tree52f488f1ce7e5113f3ad83b3ee549b3173fac0ba
parentd8233feb78d10ade39fd64b85044fea84f2fc293 (diff)
downloadlibgit2-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.c10
-rw-r--r--src/parse.h1
-rw-r--r--src/refdb_fs.c75
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;