#include "fsck.h"
#include "parse-options.h"
#include "dir.h"
+#include "progress.h"
+#include "streaming.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
static int errors_found;
static int write_lost_and_found;
static int verbose;
+static int show_progress = -1;
+static int show_dangling = 1;
#define ERROR_OBJECT 01
#define ERROR_REACHABLE 02
#define ERROR_PACK 04
static int traverse_reachable(void)
{
+ struct progress *progress = NULL;
+ unsigned int nr = 0;
int result = 0;
+ if (show_progress)
+ progress = start_progress_delay("Checking connectivity", 0, 0, 2);
while (pending.nr) {
struct object_array_entry *entry;
struct object *obj;
entry = pending.objects + --pending.nr;
obj = entry->item;
result |= traverse_one_object(obj);
+ display_progress(progress, ++nr);
}
+ stop_progress(&progress);
return !!result;
}
* start looking at, for example.
*/
if (!obj->used) {
- printf("dangling %s %s\n", typename(obj->type),
- sha1_to_hex(obj->sha1));
+ if (show_dangling)
+ printf("dangling %s %s\n", typename(obj->type),
+ sha1_to_hex(obj->sha1));
if (write_lost_and_found) {
char *filename = git_path("lost-found/%s/%s",
obj->type == OBJ_COMMIT ? "commit" : "other",
if (!(f = fopen(filename, "w")))
die_errno("Could not open '%s'", filename);
if (obj->type == OBJ_BLOB) {
- enum object_type type;
- unsigned long size;
- char *buf = read_sha1_file(obj->sha1,
- &type, &size);
- if (buf && fwrite(buf, 1, size, f) != size)
+ if (stream_blob_to_fd(fileno(f), obj->sha1, NULL, 1))
die_errno("Could not write '%s'", filename);
- free(buf);
} else
fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
if (fclose(f))
static void fsck_object_dir(const char *path)
{
int i;
+ struct progress *progress = NULL;
if (verbose)
fprintf(stderr, "Checking object directory\n");
+ if (show_progress)
+ progress = start_progress("Checking object directories", 256);
for (i = 0; i < 256; i++) {
static char dir[4096];
sprintf(dir, "%s/%02x", path, i);
fsck_dir(i, dir);
+ display_progress(progress, i+1);
}
+ stop_progress(&progress);
fsck_sha1_list();
}
if (verbose)
fprintf(stderr, "Checking HEAD link\n");
- head_points_at = resolve_ref("HEAD", head_sha1, 0, &flag);
+ head_points_at = resolve_ref_unsafe("HEAD", head_sha1, 0, &flag);
if (!head_points_at)
return error("Invalid HEAD");
if (!strcmp(head_points_at, "HEAD"))
static struct option fsck_opts[] = {
OPT__VERBOSE(&verbose, "be verbose"),
OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"),
+ OPT_BOOL(0, "dangling", &show_dangling, "show dangling objects"),
OPT_BOOLEAN(0, "tags", &show_tags, "report tags"),
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
"write dangling objects in .git/lost-found"),
+ OPT_BOOL(0, "progress", &show_progress, "show progress"),
OPT_END(),
};
read_replace_refs = 0;
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
+
+ if (show_progress == -1)
+ show_progress = isatty(2);
+ if (verbose)
+ show_progress = 0;
+
if (write_lost_and_found) {
check_full = 1;
include_reflogs = 0;
if (check_full) {
struct packed_git *p;
+ uint32_t total = 0, count = 0;
+ struct progress *progress = NULL;
prepare_packed_git();
- for (p = packed_git; p; p = p->next)
+
+ if (show_progress) {
+ for (p = packed_git; p; p = p->next) {
+ if (open_pack_index(p))
+ continue;
+ total += p->num_objects;
+ }
+
+ progress = start_progress("Checking objects", total);
+ }
+ for (p = packed_git; p; p = p->next) {
/* verify gives error messages itself */
- if (verify_pack(p, fsck_obj_buffer))
+ if (verify_pack(p, fsck_obj_buffer,
+ progress, count))
errors_found |= ERROR_PACK;
+ count += p->num_objects;
+ }
+ stop_progress(&progress);
}
heads = 0;