textconv: make the API public
[gitweb.git] / fsck.c
diff --git a/fsck.c b/fsck.c
index ab64c18a2baf5e88de8e98d9d8526ba3a7dfed14..ae9ae1abee8e406e838fc32802aeb2c50ba4ca7d 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -148,20 +148,17 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
        struct tree_desc desc;
        unsigned o_mode;
        const char *o_name;
-       const unsigned char *o_sha1;
 
        init_tree_desc(&desc, item->buffer, item->size);
 
        o_mode = 0;
        o_name = NULL;
-       o_sha1 = NULL;
 
        while (desc.size) {
                unsigned mode;
                const char *name;
-               const unsigned char *sha1;
 
-               sha1 = tree_entry_extract(&desc, &name, &mode);
+               tree_entry_extract(&desc, &name, &mode);
 
                if (strchr(name, '/'))
                        has_full_path = 1;
@@ -207,7 +204,6 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
 
                o_mode = mode;
                o_name = name;
-               o_sha1 = sha1;
        }
 
        retval = 0;
@@ -226,14 +222,49 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
        return retval;
 }
 
+static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
+{
+       if (**ident == '<' || **ident == '\n')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
+       *ident += strcspn(*ident, "<\n");
+       if ((*ident)[-1] != ' ')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
+       if (**ident != '<')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing email");
+       (*ident)++;
+       *ident += strcspn(*ident, "<>\n");
+       if (**ident != '>')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad email");
+       (*ident)++;
+       if (**ident != ' ')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before date");
+       (*ident)++;
+       if (**ident == '0' && (*ident)[1] != ' ')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
+       *ident += strspn(*ident, "0123456789");
+       if (**ident != ' ')
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");
+       (*ident)++;
+       if ((**ident != '+' && **ident != '-') ||
+           !isdigit((*ident)[1]) ||
+           !isdigit((*ident)[2]) ||
+           !isdigit((*ident)[3]) ||
+           !isdigit((*ident)[4]) ||
+           ((*ident)[5] != '\n'))
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad time zone");
+       (*ident) += 6;
+       return 0;
+}
+
 static int fsck_commit(struct commit *commit, fsck_error error_func)
 {
        char *buffer = commit->buffer;
        unsigned char tree_sha1[20], sha1[20];
        struct commit_graft *graft;
        int parents = 0;
+       int err;
 
-       if (!commit->date)
+       if (commit->date == ULONG_MAX)
                return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
 
        if (memcmp(buffer, "tree ", 5))
@@ -270,6 +301,18 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
        }
        if (memcmp(buffer, "author ", 7))
                return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'author' line");
+       buffer += 7;
+       err = fsck_ident(&buffer, &commit->object, error_func);
+       if (err)
+               return err;
+       if (memcmp(buffer, "committer ", strlen("committer ")))
+               return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'committer' line");
+       buffer += strlen("committer ");
+       err = fsck_ident(&buffer, &commit->object, error_func);
+       if (err)
+               return err;
+       if (*buffer != '\n')
+               return error_func(&commit->object, FSCK_ERROR, "invalid format - expected blank line");
        if (!commit->tree)
                return error_func(&commit->object, FSCK_ERROR, "could not load commit's tree %s", sha1_to_hex(tree_sha1));
 
@@ -307,9 +350,8 @@ int fsck_error_function(struct object *obj, int type, const char *fmt, ...)
 {
        va_list ap;
        int len;
-       struct strbuf sb;
+       struct strbuf sb = STRBUF_INIT;
 
-       strbuf_init(&sb, 0);
        strbuf_addf(&sb, "object %s:", obj->sha1?sha1_to_hex(obj->sha1):"(null)");
 
        va_start(ap, fmt);