static int check_strict;
static int keep_cache_objects;
static unsigned char head_sha1[20];
+static int errors_found;
+#define ERROR_OBJECT 01
+#define ERROR_REACHABLE 02
#ifdef NO_D_INO_IN_DIRENT
#define SORT_DIRENT 0
{
va_list params;
va_start(params, err);
+ errors_found |= ERROR_OBJECT;
objreport(obj, "error", err, params);
va_end(params);
return -1;
* do a full fsck
*/
if (!obj->parsed) {
- if (has_sha1_file(obj->sha1))
+ if (has_sha1_pack(obj->sha1, NULL))
return; /* it is in pack - forget about it */
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
+ errors_found |= ERROR_REACHABLE;
return;
}
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
typename(ref->type), sha1_to_hex(ref->sha1));
+ errors_found |= ERROR_REACHABLE;
}
}
}
{
int retval;
int has_full_path = 0;
+ int has_empty_name = 0;
int has_zero_pad = 0;
int has_bad_modes = 0;
int has_dup_entries = 0;
const char *o_name;
const unsigned char *o_sha1;
- desc.buf = item->buffer;
- desc.size = item->size;
+ init_tree_desc(&desc, item->buffer, item->size);
o_mode = 0;
o_name = NULL;
if (strchr(name, '/'))
has_full_path = 1;
- has_zero_pad |= *(char *)desc.buf == '0';
+ if (!*name)
+ has_empty_name = 1;
+ has_zero_pad |= *(char *)desc.buffer == '0';
update_tree_entry(&desc);
switch (mode) {
if (has_full_path) {
objwarning(&item->object, "contains full pathnames");
}
+ if (has_empty_name) {
+ objwarning(&item->object, "contains empty pathname");
+ }
if (has_zero_pad) {
objwarning(&item->object, "contains zero-padded file modes");
}
static int fsck_sha1(unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
- if (!obj)
- return error("%s: object corrupt or missing", sha1_to_hex(sha1));
+ if (!obj) {
+ errors_found |= ERROR_OBJECT;
+ return error("%s: object corrupt or missing",
+ sha1_to_hex(sha1));
+ }
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
return fsck_commit((struct commit *) obj);
if (obj->type == OBJ_TAG)
return fsck_tag((struct tag *) obj);
+
/* By now, parse_object() would've returned NULL instead. */
- return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
+ return objerror(obj, "unknown type '%d' (internal fsck error)",
+ obj->type);
}
/*
return 0;
}
+static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, int flag, void *cb_data)
+{
+ for_each_reflog_ent(logname, fsck_handle_reflog_ent, NULL);
+ return 0;
+}
+
static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
struct object *obj;
obj->used = 1;
mark_reachable(obj, REACHABLE);
- for_each_reflog_ent(refname, fsck_handle_reflog_ent, NULL);
-
return 0;
}
static void get_default_heads(void)
{
for_each_ref(fsck_handle_ref, NULL);
+ for_each_reflog(fsck_handle_reflog, NULL);
/*
* Not having any default heads isn't really fatal, but
* "show_unreachable" flag.
*/
if (!default_refs) {
- error("No default references");
+ fprintf(stderr, "notice: No default references\n");
show_unreachable = 0;
}
}
{
unsigned char sha1[20];
int flag;
- const char *head_points_at = resolve_ref("HEAD", sha1, 1, &flag);
-
- if (!head_points_at || !(flag & REF_ISSYMREF))
- return error("HEAD is not a symbolic ref");
- if (strncmp(head_points_at, "refs/heads/", 11))
+ int null_is_error = 0;
+ const char *head_points_at = resolve_ref("HEAD", sha1, 0, &flag);
+
+ if (!head_points_at)
+ return error("Invalid HEAD");
+ if (!strcmp(head_points_at, "HEAD"))
+ /* detached HEAD */
+ null_is_error = 1;
+ else if (prefixcmp(head_points_at, "refs/heads/"))
return error("HEAD points to something strange (%s)",
head_points_at);
- if (is_null_sha1(sha1))
- return error("HEAD: not a valid git pointer");
+ if (is_null_sha1(sha1)) {
+ if (null_is_error)
+ return error("HEAD: detached HEAD points at nothing");
+ fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n",
+ head_points_at + 11);
+ }
return 0;
}
return err;
}
+static const char fsck_usage[] =
+"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
+"[--strict] <head-sha1>*]";
+
int cmd_fsck(int argc, char **argv, const char *prefix)
{
int i, heads;
track_object_refs = 1;
+ errors_found = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
continue;
}
if (*arg == '-')
- usage("git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
+ usage(fsck_usage);
}
fsck_head_link();
verify_pack(p, 0);
for (p = packed_git; p; p = p->next) {
- int num = num_packed_objects(p);
+ uint32_t i, num = num_packed_objects(p);
for (i = 0; i < num; i++) {
unsigned char sha1[20];
nth_packed_object_sha1(p, i, sha1);
}
check_connectivity();
- return 0;
+ return errors_found;
}