X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=fsck-objects.c;h=90e638e573be005033cbf7faeff6ea8e97a1e758;hb=e99fcf96deab45ca81b22948328deb2d8586aa8d;hp=43d188a139eaf5ea3e5dab100fdd7a284fa722c7;hpb=215a7ad1ef790467a4cd3f0dcffbd6e5f04c38f7;p=git.git diff --git a/fsck-objects.c b/fsck-objects.c index 43d188a1..90e638e5 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -20,6 +20,35 @@ static int check_strict = 0; static int keep_cache_objects = 0; static unsigned char head_sha1[20]; + +static void objreport(struct object *obj, const char *severity, + const char *err, va_list params) +{ + fprintf(stderr, "%s in %s %s: ", + severity, obj->type, sha1_to_hex(obj->sha1)); + vfprintf(stderr, err, params); + fputs("\n", stderr); +} + +static int objerror(struct object *obj, const char *err, ...) +{ + va_list params; + va_start(params, err); + objreport(obj, "error", err, params); + va_end(params); + return -1; +} + +static int objwarning(struct object *obj, const char *err, ...) +{ + va_list params; + va_start(params, err); + objreport(obj, "warning", err, params); + va_end(params); + return -1; +} + + static void check_connectivity(void) { int i; @@ -27,7 +56,6 @@ static void check_connectivity(void) /* Look up all the requirements, warn about missing objects.. */ for (i = 0; i < nr_objs; i++) { struct object *obj = objs[i]; - struct object_list *refs; if (!obj->parsed) { if (!standalone && has_sha1_file(obj->sha1)) @@ -38,14 +66,19 @@ static void check_connectivity(void) continue; } - for (refs = obj->refs; refs; refs = refs->next) { - if (refs->item->parsed || - (!standalone && has_sha1_file(refs->item->sha1))) - continue; - printf("broken link from %7s %s\n", - obj->type, sha1_to_hex(obj->sha1)); - printf(" to %7s %s\n", - refs->item->type, sha1_to_hex(refs->item->sha1)); + if (obj->refs) { + const struct object_refs *refs = obj->refs; + unsigned j; + for (j = 0; j < refs->count; j++) { + struct object *ref = refs->ref[j]; + if (ref->parsed || + (!standalone && has_sha1_file(ref->sha1))) + continue; + printf("broken link from %7s %s\n", + obj->type, sha1_to_hex(obj->sha1)); + printf(" to %7s %s\n", + ref->type, sha1_to_hex(ref->sha1)); + } } if (show_unreachable && !(obj->flags & REACHABLE)) { @@ -155,38 +188,33 @@ static int fsck_tree(struct tree *item) default: break; } + free(last->name); + free(last); } last = entry; } + if (last) { + free(last->name); + free(last); + } + item->entries = NULL; retval = 0; if (has_full_path) { - fprintf(stderr, "warning: git-fsck-objects: tree %s " - "has full pathnames in it\n", - sha1_to_hex(item->object.sha1)); + objwarning(&item->object, "contains full pathnames"); } if (has_zero_pad) { - fprintf(stderr, "warning: git-fsck-objects: tree %s " - "has zero-padded file modes in it\n", - sha1_to_hex(item->object.sha1)); + objwarning(&item->object, "contains zero-padded file modes"); } if (has_bad_modes) { - fprintf(stderr, "warning: git-fsck-objects: tree %s " - "has bad file modes in it\n", - sha1_to_hex(item->object.sha1)); + objwarning(&item->object, "contains bad file modes"); } if (has_dup_entries) { - fprintf(stderr, "error: git-fsck-objects: tree %s " - "has duplicate file entries\n", - sha1_to_hex(item->object.sha1)); - retval = -1; + retval = objerror(&item->object, "contains duplicate file entries"); } if (not_properly_sorted) { - fprintf(stderr, "error: git-fsck-objects: tree %s " - "is not properly sorted\n", - sha1_to_hex(item->object.sha1)); - retval = -1; + retval = objerror(&item->object, "not properly sorted"); } return retval; } @@ -194,24 +222,24 @@ static int fsck_tree(struct tree *item) static int fsck_commit(struct commit *commit) { char *buffer = commit->buffer; - unsigned char sha1[20]; + unsigned char tree_sha1[20], sha1[20]; if (memcmp(buffer, "tree ", 5)) - return -1; - if (get_sha1_hex(buffer+5, sha1) || buffer[45] != '\n') - return -1; + return objerror(&commit->object, "invalid format - expected 'tree' line"); + if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n') + return objerror(&commit->object, "invalid 'tree' line format - bad sha1"); buffer += 46; while (!memcmp(buffer, "parent ", 7)) { if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n') - return -1; + return objerror(&commit->object, "invalid 'parent' line format - bad sha1"); buffer += 48; } if (memcmp(buffer, "author ", 7)) - return -1; + return objerror(&commit->object, "invalid format - expected 'author' line"); free(commit->buffer); commit->buffer = NULL; if (!commit->tree) - return -1; + return objerror(&commit->object, "could not load commit's tree %s", tree_sha1); if (!commit->parents && show_root) printf("root %s\n", sha1_to_hex(commit->object.sha1)); if (!commit->date) @@ -225,8 +253,7 @@ static int fsck_tag(struct tag *tag) struct object *tagged = tag->tagged; if (!tagged) { - printf("bad object in tag %s\n", sha1_to_hex(tag->object.sha1)); - return -1; + return objerror(&tag->object, "could not load tagged object"); } if (!show_tags) return 0; @@ -240,7 +267,7 @@ static int fsck_sha1(unsigned char *sha1) { struct object *obj = parse_object(sha1); if (!obj) - return -1; + return error("%s: object not found", sha1_to_hex(sha1)); if (obj->type == blob_type) return 0; if (obj->type == tree_type) @@ -249,7 +276,8 @@ static int fsck_sha1(unsigned char *sha1) return fsck_commit((struct commit *) obj); if (obj->type == tag_type) return fsck_tag((struct tag *) obj); - return -1; + /* By now, parse_object() would've returned NULL instead. */ + return objerror(obj, "unknown type '%s' (internal fsck error)", obj->type); } /* @@ -285,8 +313,7 @@ static void fsck_sha1_list(void) unsigned char *sha1 = entry->sha1; sha1_list.entry[i] = NULL; - if (fsck_sha1(sha1) < 0) - fprintf(stderr, "bad sha1 entry '%s'\n", sha1_to_hex(sha1)); + fsck_sha1(sha1); free(entry); } sha1_list.nr = 0; @@ -313,9 +340,8 @@ static int fsck_dir(int i, char *path) DIR *dir = opendir(path); struct dirent *de; - if (!dir) { - return error("missing sha1 directory '%s'", path); - } + if (!dir) + return 0; while ((de = readdir(dir)) != NULL) { char name[100]; @@ -386,28 +412,17 @@ static void fsck_object_dir(const char *path) static int fsck_head_link(void) { - int fd, count; - char hex[40]; unsigned char sha1[20]; - static char path[PATH_MAX], link[PATH_MAX]; - const char *git_dir; - - git_dir = gitenv(GIT_DIR_ENVIRONMENT); - if (!git_dir) git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; - - snprintf(path, sizeof(path), "%s/HEAD", git_dir); - if (readlink(path, link, sizeof(link)) < 0) - return error("HEAD is not a symlink"); - if (strncmp("refs/heads/", link, 11)) - return error("HEAD points to something strange (%s)", link); - fd = open(path, O_RDONLY); - if (fd < 0) - return error("HEAD: %s", strerror(errno)); - count = read(fd, hex, sizeof(hex)); - close(fd); - if (count < 0) - return error("HEAD: %s", strerror(errno)); - if (count < 40 || get_sha1_hex(hex, sha1)) + const char *git_HEAD = strdup(git_path("HEAD")); + const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 1); + int pfxlen = strlen(git_HEAD) - 4; /* strip .../.git/ part */ + + if (!git_refs_heads_master) + return error("HEAD is not a symbolic ref"); + if (strncmp(git_refs_heads_master + pfxlen, "refs/heads/", 11)) + return error("HEAD points to something strange (%s)", + git_refs_heads_master + pfxlen); + if (!memcmp(null_sha1, sha1, 20)) return error("HEAD: not a valid git pointer"); return 0; } @@ -416,6 +431,8 @@ int main(int argc, char **argv) { int i, heads; + setup_git_directory(); + for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -479,9 +496,7 @@ int main(int argc, char **argv) for (i = 0; i < num; i++) { unsigned char sha1[20]; nth_packed_object_sha1(p, i, sha1); - if (fsck_sha1(sha1) < 0) - fprintf(stderr, "bad sha1 entry '%s'\n", sha1_to_hex(sha1)); - + fsck_sha1(sha1); } } } @@ -505,7 +520,7 @@ int main(int argc, char **argv) heads++; continue; } - error("expected sha1, got %s", arg); + error("invalid parameter: expected sha1, got '%s'", arg); } /*