We inspect commit objects pretty much in detail in git-fsck, but we just
glanced over the tag objects. Let's be stricter.

This work was sponsored by GitHub Inc.

Signed-off-by: Johannes Schindelin <johannes.schinde...@gmx.de>
---
 fsck.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/fsck.c b/fsck.c
index db6aaa4..d30946b 100644
--- a/fsck.c
+++ b/fsck.c
@@ -6,6 +6,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "fsck.h"
+#include "refs.h"
 
 static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data)
 {
@@ -355,6 +356,90 @@ static int fsck_commit(struct commit *commit, const char 
*data,
        return ret;
 }
 
+static int fsck_tag_buffer(struct tag *tag, const char *data,
+       unsigned long size, fsck_error error_func)
+{
+       unsigned char commit_sha1[20];
+       int ret = 0;
+       const char *buffer;
+       char *tmp = NULL, *eol;
+
+       if (data)
+               buffer = data;
+       else {
+               enum object_type type;
+
+               buffer = tmp = read_sha1_file(tag->object.sha1, &type, &size);
+               if (!buffer)
+                       return error_func(&tag->object, FSCK_ERROR,
+                               "cannot read tag object");
+
+               if (type != OBJ_TAG) {
+                       ret = error_func(&tag->object, FSCK_ERROR,
+                               "expected tag got %s",
+                           typename(type));
+                       goto done;
+               }
+       }
+
+       if (must_have_empty_line(buffer, size, &tag->object, error_func))
+               goto done;
+
+       if (!skip_prefix(buffer, "object ", &buffer)) {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid format - 
expected 'object' line");
+               goto done;
+       }
+       if (get_sha1_hex(buffer, commit_sha1) || buffer[40] != '\n') {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid 'object' 
line format - bad sha1");
+               goto done;
+       }
+       buffer += 41;
+
+       if (!skip_prefix(buffer, "type ", &buffer)) {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid format - 
expected 'type' line");
+               goto done;
+       }
+       eol = strchr(buffer, '\n');
+       if (!eol) {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid format - 
unexpected end after 'type' line");
+               goto done;
+       }
+       *eol = '\0';
+       if (type_from_string_gently(buffer) < 0)
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid 'type' 
value");
+       *eol = '\n';
+       if (ret)
+               goto done;
+       buffer = eol + 1;
+
+       if (!skip_prefix(buffer, "tag ", &buffer)) {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid format - 
expected 'tag' line");
+               goto done;
+       }
+       eol = strchr(buffer, '\n');
+       if (!eol) {
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid format - 
unexpected end after 'type' line");
+               goto done;
+       }
+       *eol = '\0';
+       if (check_refname_format(buffer, REFNAME_ALLOW_ONELEVEL))
+               ret = error_func(&tag->object, FSCK_ERROR, "invalid 'tag' name: 
%s", buffer);
+       *eol = '\n';
+       if (ret)
+               goto done;
+       buffer = eol + 1;
+
+       if (!skip_prefix(buffer, "tagger ", &buffer)) {
+               /* early tags do not contain 'tagger' lines; warn only */
+               error_func(&tag->object, FSCK_WARN, "invalid format - expected 
'tagger' line");
+       }
+       ret = fsck_ident(&buffer, &tag->object, error_func);
+
+done:
+       free(tmp);
+       return ret;
+}
+
 static int fsck_tag(struct tag *tag, const char *data,
        unsigned long size, fsck_error error_func)
 {
@@ -362,7 +447,8 @@ static int fsck_tag(struct tag *tag, const char *data,
 
        if (!tagged)
                return error_func(&tag->object, FSCK_ERROR, "could not load 
tagged object");
-       return 0;
+
+       return fsck_tag_buffer(tag, data, size, error_func);
 }
 
 int fsck_object(struct object *obj, void *data, unsigned long size,
-- 
2.0.0.rc3.9669.g840d1f9

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to