{"thread":{"id":"28822","subject":"long fsck time","startedAt":"2011-11-02T12:06:42Z","lastAt":"2011-11-06T06:05:54Z","messageCount":21,"participants":["Nguyen Thai Ngoc Duy","Jeff King","Nguyễn Thái Ngọc Duy","Junio C Hamano","Stephen Boyd"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"178684","messageId":"CACsJy8D04Hw0_OoV01g2xtNK2d6fmZD_+YNEOR3A8aMUTpG5Lw@mail.gmail.com","threadId":"28822","inReplyTo":null,"subject":"long fsck time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-02T12:06:42Z","receivedAt":"2011-11-02T12:06:42Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On git.git\n\n$ /usr/bin/time git fsck\n333.25user 4.28system 5:37.59elapsed 99%CPU (0avgtext+0avgdata\n420080maxresident)k\n0inputs+0outputs (0major+726560minor)pagefaults 0swaps\n\nThat's really long time, perhaps we should print progress so users\nknow it's still running?\n-- \nDuy\n"},{"id":"178685","messageId":"CACsJy8B=5mEWoOBkrTfmJ+p7HxqJM97zdG-k71oW81-3XxuO_Q@mail.gmail.com","threadId":"28822","inReplyTo":"CACsJy8D04Hw0_OoV01g2xtNK2d6fmZD_+YNEOR3A8aMUTpG5Lw@mail.gmail.com","subject":"Re: long fsck time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-02T12:10:26Z","receivedAt":"2011-11-02T12:10:26Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Nov 2, 2011 at 7:06 PM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n> On git.git\n>\n> $ /usr/bin/time git fsck\n> 333.25user 4.28system 5:37.59elapsed 99%CPU (0avgtext+0avgdata\n> 420080maxresident)k\n> 0inputs+0outputs (0major+726560minor)pagefaults 0swaps\n>\n> That's really long time, perhaps we should print progress so users\n> know it's still running?\n\n\nAhh.. --verbose. Sorry for the noise. Still good to show the number of\nchecked objects though.\n-- \nDuy\n"},{"id":"178725","messageId":"20111102213332.GA14108@sigill.intra.peff.net","threadId":"28822","inReplyTo":"CACsJy8B=5mEWoOBkrTfmJ+p7HxqJM97zdG-k71oW81-3XxuO_Q@mail.gmail.com","subject":"Re: long fsck time","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-02T21:33:32Z","receivedAt":"2011-11-02T21:33:32Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Nov 02, 2011 at 07:10:26PM +0700, Nguyen Thai Ngoc Duy wrote:\n\n> On Wed, Nov 2, 2011 at 7:06 PM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n> > On git.git\n> >\n> > $ /usr/bin/time git fsck\n> > 333.25user 4.28system 5:37.59elapsed 99%CPU (0avgtext+0avgdata\n> > 420080maxresident)k\n> > 0inputs+0outputs (0major+726560minor)pagefaults 0swaps\n> >\n> > That's really long time, perhaps we should print progress so users\n> > know it's still running?\n> \n> Ahh.. --verbose. Sorry for the noise. Still good to show the number of\n> checked objects though.\n\nfsck --verbose is _really_ verbose. It could probably stand to have some\nprogress meters sprinkled throughout. The patch below produces this on\nmy git.git repo:\n\n  $ git fsck\n  Checking object directories: 100% (256/256), done.\n  Verifying packs: 100% (7/7), done.\n  Checking objects (pack 1/7): 100% (241/241), done.\n  Checking objects (pack 2/7): 100% (176/176), done.\n  Checking objects (pack 3/7): 100% (312/312), done.\n  Checking objects (pack 4/7): 100% (252/252), done.\n  Checking objects (pack 5/7): 100% (353/353), done.\n  Checking objects (pack 6/7): 100% (375/375), done.\n  Checking objects (pack 7/7): 100% (171079/171079), done.\n\nwhich gives reasonably smooth progress. The longest hang is that\n\"Verifying pack\" 7 is slow (I believe it's doing a sha1 over the whole\nthing). If you really wanted to get fancy, you could probably do a\nthroughput meter as we sha1 the whole contents.\n\nPatch is below. It would need --{no-,}progress support on the command\nline, and to check isatty(2) before it would be acceptable.\n\n---\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex df1a88b..481de4e 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -11,6 +11,7 @@\n #include \"fsck.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"progress.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\n@@ -512,15 +513,19 @@ static void get_default_heads(void)\n static void fsck_object_dir(const char *path)\n {\n \tint i;\n+\tstruct progress *progress;\n \n \tif (verbose)\n \t\tfprintf(stderr, \"Checking object directory\\n\");\n \n+\tprogress = start_progress(\"Checking object directories\", 256);\n \tfor (i = 0; i < 256; i++) {\n \t\tstatic char dir[4096];\n \t\tsprintf(dir, \"%s/%02x\", path, i);\n \t\tfsck_dir(i, dir);\n+\t\tdisplay_progress(progress, i+1);\n \t}\n+\tstop_progress(&progress);\n \tfsck_sha1_list();\n }\n \n@@ -622,19 +627,36 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \n \tif (check_full) {\n \t\tstruct packed_git *p;\n+\t\tint i, nr_packs = 0;\n+\t\tstruct progress *progress;\n \n \t\tprepare_packed_git();\n \t\tfor (p = packed_git; p; p = p->next)\n+\t\t\tnr_packs++;\n+\n+\t\tprogress = start_progress(\"Verifying packs\", nr_packs);\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n \t\t\t/* verify gives error messages itself */\n \t\t\tverify_pack(p);\n+\t\t\tdisplay_progress(progress, i);\n+\t\t}\n+\t\tstop_progress(&progress);\n \n-\t\tfor (p = packed_git; p; p = p->next) {\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n+\t\t\tchar buf[32];\n \t\t\tuint32_t j, num;\n \t\t\tif (open_pack_index(p))\n \t\t\t\tcontinue;\n \t\t\tnum = p->num_objects;\n-\t\t\tfor (j = 0; j < num; j++)\n+\n+\t\t\tsnprintf(buf, sizeof(buf), \"Checking objects (pack %d/%d)\",\n+\t\t\t\t i, nr_packs);\n+\t\t\tprogress = start_progress(buf, num);\n+\t\t\tfor (j = 0; j < num; j++) {\n \t\t\t\tfsck_sha1(nth_packed_object_sha1(p, j));\n+\t\t\t\tdisplay_progress(progress, j+1);\n+\t\t\t}\n+\t\t\tstop_progress(&progress);\n \t\t}\n \t}\n \n"},{"id":"178745","messageId":"CACsJy8DN74QWYA_NzBCGgp_VdQpV5PqGMgAFUKYbOecVqw6HYQ@mail.gmail.com","threadId":"28822","inReplyTo":"20111102213332.GA14108@sigill.intra.peff.net","subject":"Re: long fsck time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-03T01:36:16Z","receivedAt":"2011-11-03T01:36:16Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/11/3 Jeff King <peff@peff.net>:\n> On Wed, Nov 02, 2011 at 07:10:26PM +0700, Nguyen Thai Ngoc Duy wrote:\n>\n>> On Wed, Nov 2, 2011 at 7:06 PM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n>> > On git.git\n>> >\n>> > $ /usr/bin/time git fsck\n>> > 333.25user 4.28system 5:37.59elapsed 99%CPU (0avgtext+0avgdata\n>> > 420080maxresident)k\n>> > 0inputs+0outputs (0major+726560minor)pagefaults 0swaps\n>> >\n>> > That's really long time, perhaps we should print progress so users\n>> > know it's still running?\n>>\n>> Ahh.. --verbose. Sorry for the noise. Still good to show the number of\n>> checked objects though.\n>\n> fsck --verbose is _really_ verbose. It could probably stand to have some\n> progress meters sprinkled throughout. The patch below produces this on\n> my git.git repo:\n\n\nYes, I wanted something like this.\n\n>  $ git fsck\n>  Checking object directories: 100% (256/256), done.\n>  Verifying packs: 100% (7/7), done.\n>  Checking objects (pack 1/7): 100% (241/241), done.\n>  Checking objects (pack 2/7): 100% (176/176), done.\n>  Checking objects (pack 3/7): 100% (312/312), done.\n>  Checking objects (pack 4/7): 100% (252/252), done.\n>  Checking objects (pack 5/7): 100% (353/353), done.\n>  Checking objects (pack 6/7): 100% (375/375), done.\n>  Checking objects (pack 7/7): 100% (171079/171079), done.\n\nWould be better if we only output one \"Checking objects\" line.\n\n> which gives reasonably smooth progress. The longest hang is that\n> \"Verifying pack\" 7 is slow (I believe it's doing a sha1 over the whole\n> thing). If you really wanted to get fancy, you could probably do a\n> throughput meter as we sha1 the whole contents.\n\nI'll give it a try.\n\n> Patch is below. It would need --{no-,}progress support on the command\n> line, and to check isatty(2) before it would be acceptable.\n\nAgreed on isatty(), though I think this output should be default (with\nmaybe --quiet to silence it on tty). Other messages may be prepended\nwith severity to indicate they are not progress output.\n-- \nDuy\n"},{"id":"178753","messageId":"1320290513-8878-1-git-send-email-pclouds@gmail.com","threadId":"28822","inReplyTo":"CACsJy8DN74QWYA_NzBCGgp_VdQpV5PqGMgAFUKYbOecVqw6HYQ@mail.gmail.com","subject":"[PATCH] fsck: print progress","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-03T03:21:53Z","receivedAt":"2011-11-03T03:21:53Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"fsck is usually a long process and it would be nice if it prints\nprogress from time to time.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-fsck.txt |   12 ++++++++-\n builtin/fsck.c             |   57 +++++++++++++++++++++++++++++++++++++++++--\n pack-check.c               |   11 ++++++--\n pack.h                     |    4 ++-\n 4 files changed, 76 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex a2a508d..5245101 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -10,7 +10,8 @@ SYNOPSIS\n --------\n [verse]\n 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n-\t [--[no-]full] [--strict] [--verbose] [--lost-found] [<object>*]\n+\t [--[no-]full] [--strict] [--verbose] [--lost-found]\n+\t [--[no-]progress] [<object>*]\n \n DESCRIPTION\n -----------\n@@ -72,6 +73,15 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless\n \ta blob, the contents are written into the file, rather than\n \tits object name.\n \n+--progress::\n+--no-progress::\n+\tWhen fsck is run in a terminal, it will show the progress.\n+\tThese options can force progress to be shown or not\n+\tregardless terminal check.\n++\n+Progress is not shown when --verbose is used. --progress is ignored\n+in this case.\n+\n It tests SHA1 and general object sanity, and it does full tracking of\n the resulting reachability and everything else. It prints out any\n corruption it finds (missing or bad objects), and if you use the\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex df1a88b..dc6a6fc 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -11,6 +11,7 @@\n #include \"fsck.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"progress.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\n@@ -27,6 +28,8 @@ static const char *head_points_at;\n static int errors_found;\n static int write_lost_and_found;\n static int verbose;\n+static int show_progress = -1;\n+\n #define ERROR_OBJECT 01\n #define ERROR_REACHABLE 02\n \n@@ -512,15 +515,20 @@ static void get_default_heads(void)\n static void fsck_object_dir(const char *path)\n {\n \tint i;\n+\tstruct progress *progress;\n \n \tif (verbose)\n \t\tfprintf(stderr, \"Checking object directory\\n\");\n \n+\tif (show_progress)\n+\t\tprogress = start_progress(\"Checking object directories\", 256);\n \tfor (i = 0; i < 256; i++) {\n \t\tstatic char dir[4096];\n \t\tsprintf(dir, \"%s/%02x\", path, i);\n \t\tfsck_dir(i, dir);\n+\t\tdisplay_progress(progress, i+1);\n \t}\n+\tstop_progress(&progress);\n \tfsck_sha1_list();\n }\n \n@@ -591,6 +599,7 @@ static struct option fsck_opts[] = {\n \tOPT_BOOLEAN(0, \"strict\", &check_strict, \"enable more strict checking\"),\n \tOPT_BOOLEAN(0, \"lost-found\", &write_lost_and_found,\n \t\t\t\t\"write dangling objects in .git/lost-found\"),\n+\tOPT_BOOL   (0, \"progress\", &show_progress, \"show progress\"),\n \tOPT_END(),\n };\n \n@@ -603,6 +612,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \tread_replace_refs = 0;\n \n \targc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);\n+\n+\tif (show_progress == -1)\n+\t\tshow_progress = isatty(2);\n+\tif (verbose)\n+\t\tshow_progress = 0;\n+\n \tif (write_lost_and_found) {\n \t\tcheck_full = 1;\n \t\tinclude_reflogs = 0;\n@@ -622,20 +637,56 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \n \tif (check_full) {\n \t\tstruct packed_git *p;\n+\t\tint i, nr_packs = 0;\n+\t\tstruct progress *progress = NULL;\n \n \t\tprepare_packed_git();\n+\n \t\tfor (p = packed_git; p; p = p->next)\n+\t\t\tnr_packs++;\n+\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n+\t\t\tif (show_progress) {\n+\t\t\t\tchar buf[32];\n+\t\t\t\tsnprintf(buf, sizeof(buf), \"Verifying pack %d/%d\",\n+\t\t\t\t\t i, nr_packs);\n+\t\t\t\tif (open_pack_index(p))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprogress = start_progress(buf, p->num_objects);\n+\t\t\t}\n \t\t\t/* verify gives error messages itself */\n-\t\t\tverify_pack(p);\n+\t\t\tverify_pack(p, progress);\n+\n+\t\t\t/*\n+\t\t\t * we do not stop progress here, let the next\n+\t\t\t * progress line overwrite the current one for\n+\t\t\t * the next pack.\n+\t\t\t */\n+\t\t}\n+\t\tstop_progress(&progress);\n \n-\t\tfor (p = packed_git; p; p = p->next) {\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n+\t\t\tchar buf[64];\n \t\t\tuint32_t j, num;\n \t\t\tif (open_pack_index(p))\n \t\t\t\tcontinue;\n \t\t\tnum = p->num_objects;\n-\t\t\tfor (j = 0; j < num; j++)\n+\n+\t\t\tsnprintf(buf, sizeof(buf), \"Checking objects on pack %d/%d\",\n+\t\t\t\t i, nr_packs);\n+\t\t\tif (show_progress)\n+\t\t\t\tprogress = start_progress(buf, num);\n+\t\t\tfor (j = 0; j < num; j++) {\n \t\t\t\tfsck_sha1(nth_packed_object_sha1(p, j));\n+\t\t\t\tdisplay_progress(progress, j+1);\n+\t\t\t}\n+\t\t\t/*\n+\t\t\t * we do not stop progress here, let the next\n+\t\t\t * progress line overwrite the current one for\n+\t\t\t * the next pack.\n+\t\t\t */\n \t\t}\n+\t\tstop_progress(&progress);\n \t}\n \n \theads = 0;\ndiff --git a/pack-check.c b/pack-check.c\nindex 0c19b6e..e30c18c 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"pack.h\"\n #include \"pack-revindex.h\"\n+#include \"progress.h\"\n \n struct idx_entry {\n \toff_t                offset;\n@@ -42,7 +43,8 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n }\n \n static int verify_packfile(struct packed_git *p,\n-\t\tstruct pack_window **w_curs)\n+\t\t\t   struct pack_window **w_curs,\n+\t\t\t   struct progress *progress)\n {\n \toff_t index_size = p->index_size;\n \tconst unsigned char *index_base = p->index_data;\n@@ -126,7 +128,10 @@ static int verify_packfile(struct packed_git *p,\n \t\t\tbreak;\n \t\t}\n \t\tfree(data);\n+\t\tif ((i & 1023) == 0)\n+\t\t\tdisplay_progress(progress, i);\n \t}\n+\tdisplay_progress(progress, i);\n \tfree(entries);\n \n \treturn err;\n@@ -155,7 +160,7 @@ int verify_pack_index(struct packed_git *p)\n \treturn err;\n }\n \n-int verify_pack(struct packed_git *p)\n+int verify_pack(struct packed_git *p, struct progress *progress)\n {\n \tint err = 0;\n \tstruct pack_window *w_curs = NULL;\n@@ -164,7 +169,7 @@ int verify_pack(struct packed_git *p)\n \tif (!p->index_data)\n \t\treturn -1;\n \n-\terr |= verify_packfile(p, &w_curs);\n+\terr |= verify_packfile(p, &w_curs, progress);\n \tunuse_pack(&w_curs);\n \n \treturn err;\ndiff --git a/pack.h b/pack.h\nindex 722a54e..572794f 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -70,10 +70,12 @@ struct pack_idx_entry {\n \toff_t offset;\n };\n \n+struct progress;\n+\n extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, unsigned char *sha1);\n extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);\n extern int verify_pack_index(struct packed_git *);\n-extern int verify_pack(struct packed_git *);\n+extern int verify_pack(struct packed_git *, struct progress *);\n extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);\n extern char *index_pack_lockfile(int fd);\n extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);\n-- \n1.7.3.1.256.g2539c.dirty\n"},{"id":"178755","messageId":"20111103033325.GA10230@sigill.intra.peff.net","threadId":"28822","inReplyTo":"1320290513-8878-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-03T03:33:25Z","receivedAt":"2011-11-03T03:33:25Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 03, 2011 at 10:21:53AM +0700, Nguyen Thai Ngoc Duy wrote:\n\n> fsck is usually a long process and it would be nice if it prints\n> progress from time to time.\n\nThe output looks good to me. Code looks sane overall, with one comment:\n\n> +\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n> +\t\t\tif (show_progress) {\n> +\t\t\t\tchar buf[32];\n> +\t\t\t\tsnprintf(buf, sizeof(buf), \"Verifying pack %d/%d\",\n> +\t\t\t\t\t i, nr_packs);\n> +\t\t\t\tif (open_pack_index(p))\n> +\t\t\t\t\tcontinue;\n> +\t\t\t\tprogress = start_progress(buf, p->num_objects);\n> +\t\t\t}\n>  \t\t\t/* verify gives error messages itself */\n> -\t\t\tverify_pack(p);\n> +\t\t\tverify_pack(p, progress);\n> +\n> +\t\t\t/*\n> +\t\t\t * we do not stop progress here, let the next\n> +\t\t\t * progress line overwrite the current one for\n> +\t\t\t * the next pack.\n> +\t\t\t */\n> +\t\t}\n> +\t\tstop_progress(&progress);\n\nWe're actually leaking some memory here, since stop_progress will also\nfree() the progress object and any associated resources. It's not a lot,\nbut it's kind of ugly.\n\nPerhaps there should be a special version of stop_progress that handles\nthis better? Or perhaps we could even come up with a total object count\nbefore starting.  I guess it would involve mapping each pack index\nsimultaneously, though by my reading of the code, I think we do that\nanyway (the opened index is cached in the pack object).\n\n-Peff\n"},{"id":"178761","messageId":"1320310234-11243-1-git-send-email-pclouds@gmail.com","threadId":"28822","inReplyTo":"20111103033325.GA10230@sigill.intra.peff.net","subject":"[PATCH] fsck: print progress","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-03T08:50:34Z","receivedAt":"2011-11-03T08:50:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"fsck is usually a long process and it would be nice if it prints\nprogress from time to time.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n 2011/11/3 Jeff King <peff@peff.net>:\n > We're actually leaking some memory here, since stop_progress will also\n > free() the progress object and any associated resources. It's not a lot,\n > but it's kind of ugly.\n\n Fixed by always calling stop_progress_msg() but make sure no newline\n is printed (actually \"done\\n\" is not)\n\n Also fixed \"progress\" initialization in fsck_object_dir()\n\n > Or perhaps we could even come up with a total object count\n > before starting.  I guess it would involve mapping each pack index\n > simultaneously, though by my reading of the code, I think we do that\n > anyway (the opened index is cached in the pack object).\n\n I think this way is better because we can count two numbers at a\n time, nr. packs and nr. objects of current pack. Total object\n (I assume you mean of all packs) may be less informative.\n\n Documentation/git-fsck.txt |   12 +++++++++-\n builtin/fsck.c             |   52 +++++++++++++++++++++++++++++++++++++++++--\n pack-check.c               |   11 ++++++--\n pack.h                     |    4 ++-\n progress.c                 |    2 +-\n 5 files changed, 72 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex a2a508d..5245101 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -10,7 +10,8 @@ SYNOPSIS\n --------\n [verse]\n 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n-\t [--[no-]full] [--strict] [--verbose] [--lost-found] [<object>*]\n+\t [--[no-]full] [--strict] [--verbose] [--lost-found]\n+\t [--[no-]progress] [<object>*]\n \n DESCRIPTION\n -----------\n@@ -72,6 +73,15 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless\n \ta blob, the contents are written into the file, rather than\n \tits object name.\n \n+--progress::\n+--no-progress::\n+\tWhen fsck is run in a terminal, it will show the progress.\n+\tThese options can force progress to be shown or not\n+\tregardless terminal check.\n++\n+Progress is not shown when --verbose is used. --progress is ignored\n+in this case.\n+\n It tests SHA1 and general object sanity, and it does full tracking of\n the resulting reachability and everything else. It prints out any\n corruption it finds (missing or bad objects), and if you use the\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex df1a88b..e19b78c 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -11,6 +11,7 @@\n #include \"fsck.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"progress.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\n@@ -27,6 +28,8 @@ static const char *head_points_at;\n static int errors_found;\n static int write_lost_and_found;\n static int verbose;\n+static int show_progress = -1;\n+\n #define ERROR_OBJECT 01\n #define ERROR_REACHABLE 02\n \n@@ -512,15 +515,20 @@ static void get_default_heads(void)\n static void fsck_object_dir(const char *path)\n {\n \tint i;\n+\tstruct progress *progress = NULL;\n \n \tif (verbose)\n \t\tfprintf(stderr, \"Checking object directory\\n\");\n \n+\tif (show_progress)\n+\t\tprogress = start_progress(\"Checking object directories\", 256);\n \tfor (i = 0; i < 256; i++) {\n \t\tstatic char dir[4096];\n \t\tsprintf(dir, \"%s/%02x\", path, i);\n \t\tfsck_dir(i, dir);\n+\t\tdisplay_progress(progress, i+1);\n \t}\n+\tstop_progress(&progress);\n \tfsck_sha1_list();\n }\n \n@@ -591,6 +599,7 @@ static struct option fsck_opts[] = {\n \tOPT_BOOLEAN(0, \"strict\", &check_strict, \"enable more strict checking\"),\n \tOPT_BOOLEAN(0, \"lost-found\", &write_lost_and_found,\n \t\t\t\t\"write dangling objects in .git/lost-found\"),\n+\tOPT_BOOL   (0, \"progress\", &show_progress, \"show progress\"),\n \tOPT_END(),\n };\n \n@@ -603,6 +612,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \tread_replace_refs = 0;\n \n \targc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);\n+\n+\tif (show_progress == -1)\n+\t\tshow_progress = isatty(2);\n+\tif (verbose)\n+\t\tshow_progress = 0;\n+\n \tif (write_lost_and_found) {\n \t\tcheck_full = 1;\n \t\tinclude_reflogs = 0;\n@@ -622,20 +637,51 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \n \tif (check_full) {\n \t\tstruct packed_git *p;\n+\t\tint i, nr_packs = 0;\n+\t\tstruct progress *progress = NULL;\n \n \t\tprepare_packed_git();\n+\n \t\tfor (p = packed_git; p; p = p->next)\n+\t\t\tnr_packs++;\n+\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n+\t\t\tif (show_progress) {\n+\t\t\t\tchar buf[32];\n+\t\t\t\tsnprintf(buf, sizeof(buf), \"Verifying pack %d/%d\",\n+\t\t\t\t\t i, nr_packs);\n+\t\t\t\tif (open_pack_index(p))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprogress = start_progress(buf, p->num_objects);\n+\t\t\t}\n \t\t\t/* verify gives error messages itself */\n-\t\t\tverify_pack(p);\n+\t\t\tverify_pack(p, progress);\n \n-\t\tfor (p = packed_git; p; p = p->next) {\n+\t\t\tif (p->next)\n+\t\t\t\tstop_progress_msg(&progress, NULL);\n+\t\t}\n+\t\tstop_progress(&progress);\n+\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n+\t\t\tchar buf[64];\n \t\t\tuint32_t j, num;\n \t\t\tif (open_pack_index(p))\n \t\t\t\tcontinue;\n \t\t\tnum = p->num_objects;\n-\t\t\tfor (j = 0; j < num; j++)\n+\n+\t\t\tsnprintf(buf, sizeof(buf), \"Checking objects on pack %d/%d\",\n+\t\t\t\t i, nr_packs);\n+\t\t\tif (show_progress)\n+\t\t\t\tprogress = start_progress(buf, num);\n+\t\t\tfor (j = 0; j < num; j++) {\n \t\t\t\tfsck_sha1(nth_packed_object_sha1(p, j));\n+\t\t\t\tdisplay_progress(progress, j+1);\n+\t\t\t}\n+\n+\t\t\tif (p->next)\n+\t\t\t\tstop_progress_msg(&progress, NULL);\n \t\t}\n+\t\tstop_progress(&progress);\n \t}\n \n \theads = 0;\ndiff --git a/pack-check.c b/pack-check.c\nindex 0c19b6e..e30c18c 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"pack.h\"\n #include \"pack-revindex.h\"\n+#include \"progress.h\"\n \n struct idx_entry {\n \toff_t                offset;\n@@ -42,7 +43,8 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n }\n \n static int verify_packfile(struct packed_git *p,\n-\t\tstruct pack_window **w_curs)\n+\t\t\t   struct pack_window **w_curs,\n+\t\t\t   struct progress *progress)\n {\n \toff_t index_size = p->index_size;\n \tconst unsigned char *index_base = p->index_data;\n@@ -126,7 +128,10 @@ static int verify_packfile(struct packed_git *p,\n \t\t\tbreak;\n \t\t}\n \t\tfree(data);\n+\t\tif ((i & 1023) == 0)\n+\t\t\tdisplay_progress(progress, i);\n \t}\n+\tdisplay_progress(progress, i);\n \tfree(entries);\n \n \treturn err;\n@@ -155,7 +160,7 @@ int verify_pack_index(struct packed_git *p)\n \treturn err;\n }\n \n-int verify_pack(struct packed_git *p)\n+int verify_pack(struct packed_git *p, struct progress *progress)\n {\n \tint err = 0;\n \tstruct pack_window *w_curs = NULL;\n@@ -164,7 +169,7 @@ int verify_pack(struct packed_git *p)\n \tif (!p->index_data)\n \t\treturn -1;\n \n-\terr |= verify_packfile(p, &w_curs);\n+\terr |= verify_packfile(p, &w_curs, progress);\n \tunuse_pack(&w_curs);\n \n \treturn err;\ndiff --git a/pack.h b/pack.h\nindex 722a54e..572794f 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -70,10 +70,12 @@ struct pack_idx_entry {\n \toff_t offset;\n };\n \n+struct progress;\n+\n extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, unsigned char *sha1);\n extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);\n extern int verify_pack_index(struct packed_git *);\n-extern int verify_pack(struct packed_git *);\n+extern int verify_pack(struct packed_git *, struct progress *);\n extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);\n extern char *index_pack_lockfile(int fd);\n extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);\ndiff --git a/progress.c b/progress.c\nindex 3971f49..fc96a5f 100644\n--- a/progress.c\n+++ b/progress.c\n@@ -245,7 +245,7 @@ void stop_progress_msg(struct progress **p_progress, const char *msg)\n \tif (!progress)\n \t\treturn;\n \t*p_progress = NULL;\n-\tif (progress->last_value != -1) {\n+\tif (progress->last_value != -1 && msg) {\n \t\t/* Force the last update */\n \t\tchar buf[128], *bufp;\n \t\tsize_t len = strlen(msg) + 5;\n-- \n1.7.3.1.256.g2539c.dirty\n"},{"id":"178794","messageId":"20111103193826.GB19483@sigill.intra.peff.net","threadId":"28822","inReplyTo":"1320310234-11243-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-03T19:38:26Z","receivedAt":"2011-11-03T19:38:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 03, 2011 at 03:50:34PM +0700, Nguyen Thai Ngoc Duy wrote:\n\n>  2011/11/3 Jeff King <peff@peff.net>:\n>  > We're actually leaking some memory here, since stop_progress will also\n>  > free() the progress object and any associated resources. It's not a lot,\n>  > but it's kind of ugly.\n> \n>  Fixed by always calling stop_progress_msg() but make sure no newline\n>  is printed (actually \"done\\n\" is not)\n\nThanks, that sounds reasonable, and the output looks good.\n\n>  > Or perhaps we could even come up with a total object count\n>  > before starting.  I guess it would involve mapping each pack index\n>  > simultaneously, though by my reading of the code, I think we do that\n>  > anyway (the opened index is cached in the pack object).\n> \n>  I think this way is better because we can count two numbers at a\n>  time, nr. packs and nr. objects of current pack. Total object\n>  (I assume you mean of all packs) may be less informative.\n\nYeah, I meant all of the packs. It's a little more accurate as a\nprogress meter, because you don't otherwise know what's in each of the\npacks. For example, if I see that we are halfway through \"pack 1/2\",\ndoes that mean we are a quarter of the way done? Not really. Pack 2/2\nmay be much smaller or much bigger. Finishing pack 1 may make us 99%\ndone, or it may make us 10% done.\n\nShowing all of the objects in a flat list gives a more accurate\nrepresentation (though it's still not entirely accurate; even one\ngigantic blob may dwarf the earlier objects. But it's the best we can\ndo).\n\nIn practice, though, I think people tend to have one really big pack and\nsome small ones. And the packs are sorted in recency order, so we'll\nquickly go through the early little ones, and then spend all of our time\non the big old one. Unless they have .keep files.\n\nSo I don't really care that much. But it would also make the newline\nstuff go away.\n\n> +\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n> +\t\t\tif (show_progress) {\n> +\t\t\t\tchar buf[32];\n> +\t\t\t\tsnprintf(buf, sizeof(buf), \"Verifying pack %d/%d\",\n> +\t\t\t\t\t i, nr_packs);\n> +\t\t\t\tif (open_pack_index(p))\n> +\t\t\t\t\tcontinue;\n> +\t\t\t\tprogress = start_progress(buf, p->num_objects);\n> +\t\t\t}\n>  \t\t\t/* verify gives error messages itself */\n> +\t\t\tverify_pack(p, progress);\n>  \n> +\t\t\tif (p->next)\n> +\t\t\t\tstop_progress_msg(&progress, NULL);\n> +\t\t}\n> +\t\tstop_progress(&progress);\n\nYou start the progress in the loop, but stop the final one outside the\nloop. Which means that if there are no packs, we'll call stop_progress\neven though we didn't start one. I think the progress code will handle\nthe NULL fine, but it took me a minute to convince myself it's right.\n\nI would find this:\n\n  if (p->next)\n          stop_progress_msg(&progress, NULL);\n  else\n          stop_progress(&progress);\n\na little more readable, or even:\n\n  stop_progress_msg(&progress, p->next ? NULL : \"done\\n\");\n\nBut I almost wonder if it is worth factoring out the concept of a\n\"progress group\", where you would call it like:\n\n  progress = progress_group_start(\"Checking objects in pack\", nr_packs);\n  for (p = packed_git; p; p = p->next) {\n          progress_group_next(progress, p->num_objects);\n          for (j = 0; j < num; j++) {\n                  fsck_sha1(p, j);\n                  display_progress(progress, j+1);\n          }\n  }\n  stop_progress(&progress);\n\nand progress_set_next would take care of formatting the %d/%d counter,\nand would not output a newline before writing the new description line.\n\n> +           snprintf(buf, sizeof(buf), \"Checking objects on pack %d/%d\",\n> +                    i, nr_packs);\n\ns/on/in/\n\n-Peff\n"},{"id":"178795","messageId":"7vd3d9f0u8.fsf@alter.siamese.dyndns.org","threadId":"28822","inReplyTo":"20111103193826.GB19483@sigill.intra.peff.net","subject":"Re: [PATCH] fsck: print progress","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-03T19:43:59Z","receivedAt":"2011-11-03T19:43:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> a little more readable, or even:\n>\n>   stop_progress_msg(&progress, p->next ? NULL : \"done\\n\");\n\nYeah, this one looks neat.\n\n> But I almost wonder if it is worth factoring out the concept of a\n> \"progress group\", where you would call it like:\n>\n>   progress = progress_group_start(\"Checking objects in pack\", nr_packs);\n>   for (p = packed_git; p; p = p->next) {\n>           progress_group_next(progress, p->num_objects);\n>           for (j = 0; j < num; j++) {\n>                   fsck_sha1(p, j);\n>                   display_progress(progress, j+1);\n>           }\n>   }\n>   stop_progress(&progress);\n\nHmm, once you do this kind of thing I would expect two (or more) progress\nbars to be shown, something like:\n\n\t$ git fsck --progress\n\tchecking packs: 3 of 7 (42% done)\n        checking objects in pack: 12405 of 332340 (4% done)\n"},{"id":"178796","messageId":"20111103195147.GA21318@sigill.intra.peff.net","threadId":"28822","inReplyTo":"7vd3d9f0u8.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] fsck: print progress","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-03T19:51:47Z","receivedAt":"2011-11-03T19:51:47Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 03, 2011 at 12:43:59PM -0700, Junio C Hamano wrote:\n\n> > But I almost wonder if it is worth factoring out the concept of a\n> > \"progress group\", where you would call it like:\n> >\n> >   progress = progress_group_start(\"Checking objects in pack\", nr_packs);\n> >   for (p = packed_git; p; p = p->next) {\n> >           progress_group_next(progress, p->num_objects);\n> >           for (j = 0; j < num; j++) {\n> >                   fsck_sha1(p, j);\n> >                   display_progress(progress, j+1);\n> >           }\n> >   }\n> >   stop_progress(&progress);\n> \n> Hmm, once you do this kind of thing I would expect two (or more) progress\n> bars to be shown, something like:\n> \n> \t$ git fsck --progress\n> \tchecking packs: 3 of 7 (42% done)\n>         checking objects in pack: 12405 of 332340 (4% done)\n\nI don't think we can do multiple lines portably, though, because the\nprogress code just uses \"\\r\" to return to the beginning of the line.\n\nHowever, I do think it's a nice design even if the output is the same\nright now, because the calling code is specifying more clearly to the\nprogress code what it actually means. Which means it is easier to\ntweak the progress code later to make a prettier representation of that\nmeaning.\n\nOne downside (as with all abstractions :) ), is that it's hard to\ndeviate from the defaults. With the above, how would you specify if it\nwas a group of throughput measurements, not counts? Or that you wanted\nto use start_progress_delay instead of start_progress on each one?\n\nOr hey, if you really want to get crazy, why can't we check each pack in\nparallel on a different CPU, and have all of the progress meters\ndisplayed and moving simultaneously? :)\n\nThe last one is obviously a bit tongue in cheek. But it does raise an\ninteresting point: is seeing the per-pack meter actually useful (whether\nparallel or not)? The user just wants to know that progress is being\nmade, and when it is done. And maybe that argues for just summing the\nsize of each pack and showing a single progress meter per task.\n\n-Peff\n"},{"id":"178797","messageId":"7v8vnxeyrp.fsf@alter.siamese.dyndns.org","threadId":"28822","inReplyTo":"20111103195147.GA21318@sigill.intra.peff.net","subject":"Re: [PATCH] fsck: print progress","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-03T20:28:42Z","receivedAt":"2011-11-03T20:28:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n>> Hmm, once you do this kind of thing I would expect two (or more) progress\n>> bars to be shown, something like:\n>> \n>> \t$ git fsck --progress\n>> \tchecking packs: 3 of 7 (42% done)\n>>      checking objects in pack: 12405 of 332340 (4% done)\n>\n> I don't think we can do multiple lines portably, though, because the\n> progress code just uses \"\\r\" to return to the beginning of the line.\n\nIt was meant to be a tongue-in-cheek comment. I personally hate those\n\"Installing n of N packages / Installation of package n p% done\" progress\nmeters when we know the weight of each of these N packages varies.\n\nI also agree with your \"how would you know which one is throughput and\nwhich one is counts\" comment, which would mean the particular abstraction\nyou mentioned is too premature even though it looks nice on the surface.\n"},{"id":"178798","messageId":"20111103202954.GC19483@sigill.intra.peff.net","threadId":"28822","inReplyTo":"7v8vnxeyrp.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] fsck: print progress","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-03T20:29:54Z","receivedAt":"2011-11-03T20:29:54Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 03, 2011 at 01:28:42PM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> >> Hmm, once you do this kind of thing I would expect two (or more) progress\n> >> bars to be shown, something like:\n> >> \n> >> \t$ git fsck --progress\n> >> \tchecking packs: 3 of 7 (42% done)\n> >>      checking objects in pack: 12405 of 332340 (4% done)\n> >\n> > I don't think we can do multiple lines portably, though, because the\n> > progress code just uses \"\\r\" to return to the beginning of the line.\n> \n> It was meant to be a tongue-in-cheek comment. I personally hate those\n> \"Installing n of N packages / Installation of package n p% done\" progress\n> meters when we know the weight of each of these N packages varies.\n\nOK, I missed your sarcasm. You're too understated. ;)\n\nSo you would agree that we are better summing the objects for all packs\nand showing one big progress bar?\n\n-Peff\n"},{"id":"178799","messageId":"7vwrbhdixe.fsf@alter.siamese.dyndns.org","threadId":"28822","inReplyTo":"20111103202954.GC19483@sigill.intra.peff.net","subject":"Re: [PATCH] fsck: print progress","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-03T20:56:13Z","receivedAt":"2011-11-03T20:56:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> So you would agree that we are better summing the objects for all packs\n> and showing one big progress bar?\n\nIf it can be done without sacrificing the clarity of the code, compared to\nthe \"we will do new and smaller ones first so in practice it does not\nmatter\" approach taken by the patch in question, I would not mind it, but\nto be honest, I do not deeply care either way.\n"},{"id":"178800","messageId":"20111103211819.GA17341@sigill.intra.peff.net","threadId":"28822","inReplyTo":"7vwrbhdixe.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] fsck: print progress","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-03T21:18:19Z","receivedAt":"2011-11-03T21:18:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 03, 2011 at 01:56:13PM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > So you would agree that we are better summing the objects for all packs\n> > and showing one big progress bar?\n> \n> If it can be done without sacrificing the clarity of the code, compared to\n> the \"we will do new and smaller ones first so in practice it does not\n> matter\" approach taken by the patch in question, I would not mind it, but\n> to be honest, I do not deeply care either way.\n\nI looked briefly at doing this. It's a little annoying with the\nverify_packs code, because you have to pass around the \"how far are we\ninto the progress\" counter separately. But I confess I don't care that\nmuch either way, either. With the two minor fixups I sent in my original\nreview, I think Duy's patch would be OK by me.\n\n-Peff\n"},{"id":"178808","messageId":"1320376242-27851-1-git-send-email-pclouds@gmail.com","threadId":"28822","inReplyTo":"20111103211819.GA17341@sigill.intra.peff.net","subject":"[PATCH] fsck: print progress","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-04T03:10:42Z","receivedAt":"2011-11-04T03:10:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"fsck is usually a long process and it would be nice if it prints\nprogress from time to time.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n OK let's go with total object count for more accurate progress. One\n thing I did not realize that the title is not copied to struct\n progress and we can update title (e.g. current pack) while displaying\n progress.\n\n Updating once every 1024 objects may feel sluggish on large blobs,\n but we have more important things to worry about when it comes to\n large blobs than this progress bar.\n\n multithread fsck sounds interesting, I'll look into it.\n\n Documentation/git-fsck.txt |   12 +++++++++-\n builtin/fsck.c             |   49 ++++++++++++++++++++++++++++++++++++++++---\n pack-check.c               |   11 +++++++--\n pack.h                     |    4 ++-\n 4 files changed, 67 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex a2a508d..5245101 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -10,7 +10,8 @@ SYNOPSIS\n --------\n [verse]\n 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n-\t [--[no-]full] [--strict] [--verbose] [--lost-found] [<object>*]\n+\t [--[no-]full] [--strict] [--verbose] [--lost-found]\n+\t [--[no-]progress] [<object>*]\n \n DESCRIPTION\n -----------\n@@ -72,6 +73,15 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless\n \ta blob, the contents are written into the file, rather than\n \tits object name.\n \n+--progress::\n+--no-progress::\n+\tWhen fsck is run in a terminal, it will show the progress.\n+\tThese options can force progress to be shown or not\n+\tregardless terminal check.\n++\n+Progress is not shown when --verbose is used. --progress is ignored\n+in this case.\n+\n It tests SHA1 and general object sanity, and it does full tracking of\n the resulting reachability and everything else. It prints out any\n corruption it finds (missing or bad objects), and if you use the\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex df1a88b..e0cc4de 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -11,6 +11,7 @@\n #include \"fsck.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"progress.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\n@@ -27,6 +28,8 @@ static const char *head_points_at;\n static int errors_found;\n static int write_lost_and_found;\n static int verbose;\n+static int show_progress = -1;\n+\n #define ERROR_OBJECT 01\n #define ERROR_REACHABLE 02\n \n@@ -512,15 +515,20 @@ static void get_default_heads(void)\n static void fsck_object_dir(const char *path)\n {\n \tint i;\n+\tstruct progress *progress = NULL;\n \n \tif (verbose)\n \t\tfprintf(stderr, \"Checking object directory\\n\");\n \n+\tif (show_progress)\n+\t\tprogress = start_progress(\"Checking object directories\", 256);\n \tfor (i = 0; i < 256; i++) {\n \t\tstatic char dir[4096];\n \t\tsprintf(dir, \"%s/%02x\", path, i);\n \t\tfsck_dir(i, dir);\n+\t\tdisplay_progress(progress, i+1);\n \t}\n+\tstop_progress(&progress);\n \tfsck_sha1_list();\n }\n \n@@ -591,6 +599,7 @@ static struct option fsck_opts[] = {\n \tOPT_BOOLEAN(0, \"strict\", &check_strict, \"enable more strict checking\"),\n \tOPT_BOOLEAN(0, \"lost-found\", &write_lost_and_found,\n \t\t\t\t\"write dangling objects in .git/lost-found\"),\n+\tOPT_BOOL   (0, \"progress\", &show_progress, \"show progress\"),\n \tOPT_END(),\n };\n \n@@ -603,6 +612,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \tread_replace_refs = 0;\n \n \targc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);\n+\n+\tif (show_progress == -1)\n+\t\tshow_progress = isatty(2);\n+\tif (verbose)\n+\t\tshow_progress = 0;\n+\n \tif (write_lost_and_found) {\n \t\tcheck_full = 1;\n \t\tinclude_reflogs = 0;\n@@ -622,20 +637,46 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \n \tif (check_full) {\n \t\tstruct packed_git *p;\n+\t\tint i, nr_objects = 0, object_count;\n+\t\tstruct progress *progress = NULL;\n \n \t\tprepare_packed_git();\n-\t\tfor (p = packed_git; p; p = p->next)\n+\n+\t\tif (show_progress) {\n+\t\t\tfor (p = packed_git; p; p = p->next) {\n+\t\t\t\tif (open_pack_index(p))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tnr_objects += p->num_objects;\n+\t\t\t}\n+\n+\t\t\tobject_count = 0;\n+\t\t\tprogress = start_progress(\"Verifying packs\", nr_objects);\n+\t\t}\n+\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n \t\t\t/* verify gives error messages itself */\n-\t\t\tverify_pack(p);\n+\t\t\tverify_pack(p, progress, object_count);\n+\t\t\tobject_count += p->num_objects;\n+\t\t}\n+\t\tstop_progress(&progress);\n \n-\t\tfor (p = packed_git; p; p = p->next) {\n+\t\tif (show_progress) {\n+\t\t\tobject_count = 0;\n+\t\t\tprogress = start_progress(\"Checking objects\", nr_objects);\n+\t\t}\n+\n+\t\tfor (i = 1, p = packed_git; p; p = p->next, i++) {\n \t\t\tuint32_t j, num;\n \t\t\tif (open_pack_index(p))\n \t\t\t\tcontinue;\n \t\t\tnum = p->num_objects;\n-\t\t\tfor (j = 0; j < num; j++)\n+\t\t\tfor (j = 0; j < num; j++) {\n \t\t\t\tfsck_sha1(nth_packed_object_sha1(p, j));\n+\t\t\t\tdisplay_progress(progress, object_count + j+1);\n+\t\t\t}\n+\t\t\tobject_count += p->num_objects;\n \t\t}\n+\t\tstop_progress(&progress);\n \t}\n \n \theads = 0;\ndiff --git a/pack-check.c b/pack-check.c\nindex 0c19b6e..80de302 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"pack.h\"\n #include \"pack-revindex.h\"\n+#include \"progress.h\"\n \n struct idx_entry {\n \toff_t                offset;\n@@ -42,7 +43,8 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n }\n \n static int verify_packfile(struct packed_git *p,\n-\t\tstruct pack_window **w_curs)\n+\t\t\t   struct pack_window **w_curs,\n+\t\t\t   struct progress *progress, uint32_t base_count)\n {\n \toff_t index_size = p->index_size;\n \tconst unsigned char *index_base = p->index_data;\n@@ -126,7 +128,10 @@ static int verify_packfile(struct packed_git *p,\n \t\t\tbreak;\n \t\t}\n \t\tfree(data);\n+\t\tif (((base_count + i) & 1023) == 0)\n+\t\t\tdisplay_progress(progress, base_count + i);\n \t}\n+\tdisplay_progress(progress, base_count + i);\n \tfree(entries);\n \n \treturn err;\n@@ -155,7 +160,7 @@ int verify_pack_index(struct packed_git *p)\n \treturn err;\n }\n \n-int verify_pack(struct packed_git *p)\n+int verify_pack(struct packed_git *p, struct progress *progress, uint32_t base_count)\n {\n \tint err = 0;\n \tstruct pack_window *w_curs = NULL;\n@@ -164,7 +169,7 @@ int verify_pack(struct packed_git *p)\n \tif (!p->index_data)\n \t\treturn -1;\n \n-\terr |= verify_packfile(p, &w_curs);\n+\terr |= verify_packfile(p, &w_curs, progress, base_count);\n \tunuse_pack(&w_curs);\n \n \treturn err;\ndiff --git a/pack.h b/pack.h\nindex 722a54e..3a63bf6 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -70,10 +70,12 @@ struct pack_idx_entry {\n \toff_t offset;\n };\n \n+struct progress;\n+\n extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, unsigned char *sha1);\n extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);\n extern int verify_pack_index(struct packed_git *);\n-extern int verify_pack(struct packed_git *);\n+extern int verify_pack(struct packed_git *, struct progress *, uint32_t);\n extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);\n extern char *index_pack_lockfile(int fd);\n extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);\n-- \n1.7.3.1.256.g2539c.dirty\n"},{"id":"178886","messageId":"4EB4EB70.40801@gmail.com","threadId":"28822","inReplyTo":"1320376242-27851-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2011-11-05T07:53:20Z","receivedAt":"2011-11-05T07:53:20Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"On 11/03/2011 08:10 PM, Nguyễn Thái Ngọc Duy wrote:\n> diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\n[...]\n> +--progress::\n> +--no-progress::\n> +\tWhen fsck is run in a terminal, it will show the progress.\n> +\tThese options can force progress to be shown or not\n> +\tregardless terminal check.\n\nCan we reuse the --progress description in fetch-options.txt (minus the q)?\n\n--[no]-progress::\n        Progress status is reported on the standard error stream\n        by default when it is attached to a terminal. This flag\n\tforces progress status even if the standard error stream\n\tis not directed to a terminal.\n\n\n> ++\n> +Progress is not shown when --verbose is used. --progress is ignored\n> +in this case.\n\nWhat progress isn't shown? How about\n\n\tIf --verbose is used with --progress the progress status\n\twill not be shown.\n"},{"id":"178890","messageId":"CACsJy8CEh6x1O0AHpiErZ_+T2hGwjRZofygmsgVX8_WXV7uDTA@mail.gmail.com","threadId":"28822","inReplyTo":"4EB4EB70.40801@gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-05T09:02:01Z","receivedAt":"2011-11-05T09:02:01Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/11/5 Stephen Boyd <bebarino@gmail.com>:\n> On 11/03/2011 08:10 PM, Nguyễn Thái Ngọc Duy wrote:\n>> diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\n> [...]\n>> +--progress::\n>> +--no-progress::\n>> +     When fsck is run in a terminal, it will show the progress.\n>> +     These options can force progress to be shown or not\n>> +     regardless terminal check.\n>\n> Can we reuse the --progress description in fetch-options.txt (minus the q)?\n>\n> --[no]-progress::\n>        Progress status is reported on the standard error stream\n>        by default when it is attached to a terminal. This flag\n>        forces progress status even if the standard error stream\n>        is not directed to a terminal.\n>\n>\n>> ++\n>> +Progress is not shown when --verbose is used. --progress is ignored\n>> +in this case.\n>\n> What progress isn't shown? How about\n>\n>        If --verbose is used with --progress the progress status\n>        will not be shown.\n\n\"-q\" in fetch-options.txt can be converted to \"--no-progress or\n--verbose\". How about this?\n\n--progress::\n--no-progress::\n\tProgress status is reported on the standard error stream by\n\tdefault when it is attached to a terminal, unless\n\t--no-progress or --verbose is specified. --progress forces\n\tprogress status even if the standard error stream is not\n\tdirected to a terminal.\n-- \nDuy\n"},{"id":"178924","messageId":"4EB58B64.3070304@gmail.com","threadId":"28822","inReplyTo":"CACsJy8CEh6x1O0AHpiErZ_+T2hGwjRZofygmsgVX8_WXV7uDTA@mail.gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2011-11-05T19:15:48Z","receivedAt":"2011-11-05T19:15:48Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"On 11/05/2011 02:02 AM, Nguyen Thai Ngoc Duy wrote:\n> \n> \"-q\" in fetch-options.txt can be converted to \"--no-progress or\n> --verbose\". How about this?\n> \n> --progress::\n> --no-progress::\n> \tProgress status is reported on the standard error stream by\n> \tdefault when it is attached to a terminal, unless\n> \t--no-progress or --verbose is specified. --progress forces\n> \tprogress status even if the standard error stream is not\n> \tdirected to a terminal.\n\nLooks good.\n"},{"id":"178933","messageId":"7vk47e86j5.fsf@alter.siamese.dyndns.org","threadId":"28822","inReplyTo":"4EB4EB70.40801@gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-05T23:59:42Z","receivedAt":"2011-11-05T23:59:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> What progress isn't shown? How about\n>\n> \tIf --verbose is used with --progress the progress status\n> \twill not be shown.\n\nWhen I ask for verbose output, I do not get progress eye-candy?\n\nWhy?\n"},{"id":"178944","messageId":"CACsJy8DDKLrtmA3rGdW6xghwSs_e+zi1o2LzPDbmryH+XufpvQ@mail.gmail.com","threadId":"28822","inReplyTo":"7vk47e86j5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] fsck: print progress","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-06T02:37:55Z","receivedAt":"2011-11-06T02:37:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/11/6 Junio C Hamano <gitster@pobox.com>:\n> Stephen Boyd <bebarino@gmail.com> writes:\n>\n>> What progress isn't shown? How about\n>>\n>>       If --verbose is used with --progress the progress status\n>>       will not be shown.\n>\n> When I ask for verbose output, I do not get progress eye-candy?\n>\n> Why?\n\nBecause in verbose mode, the screen is filled with \"checking ...\"\nlines for evevry object, there'll be no wonder why it stops for so\nlong. It'd be good to show how many percent complete, but with current\nprogress.c support, the progress line would be lost in \"checking...\"\nflood.\n-- \nDuy\n"},{"id":"178953","messageId":"7vpqh57pkt.fsf@alter.siamese.dyndns.org","threadId":"28822","inReplyTo":"CACsJy8DDKLrtmA3rGdW6xghwSs_e+zi1o2LzPDbmryH+XufpvQ@mail.gmail.com","subject":"Re: [PATCH] fsck: print progress","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-06T06:05:54Z","receivedAt":"2011-11-06T06:05:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:\n\n> Because in verbose mode, the screen is filled with \"checking ...\"\n> lines for evevry object, there'll be no wonder why it stops for so\n> long.\n\nAh, OK. It makes sense then, but the fact that you needed to explain it\nwould suggest that explanation deserves to be in the proposed commit log\nmessage.\n\nI was wondering if it was a typo of either \"If --quiet is used, progress\nis not shown\", or \"If --verbose=no is used, ...\"\n"}]}