{"thread":{"id":"7753","subject":"[PATCH] git-add -u: match the index with working tree.","startedAt":"2007-04-20T08:42:18Z","lastAt":"2007-04-20T14:46:56Z","messageCount":13,"participants":["Junio C Hamano","Johannes Sixt","Karl Hasselström","Nikolai Weibull","Andy Parkins","Matthieu Moy","Nicolas Pitre","J. Bruce Fields","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"39951","messageId":"11770585393395-git-send-email-junkio@cox.net","threadId":"7753","inReplyTo":null,"subject":"[PATCH] git-add -u: match the index with working tree.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-20T08:42:18Z","receivedAt":"2007-04-20T08:42:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is a shorthand of what \"git commit -a\" does in preparation\nfor making a commit, which is:\n\n    git diff-files --name-only -z | git update-index --remove -z --stdin\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n builtin-add.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 57 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 9ec2925..5e6748f 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -8,10 +8,15 @@\n #include \"dir.h\"\n #include \"exec_cmd.h\"\n #include \"cache-tree.h\"\n+#include \"diff.h\"\n+#include \"diffcore.h\"\n+#include \"commit.h\"\n+#include \"revision.h\"\n \n static const char builtin_add_usage[] =\n-\"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...\";\n+\"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n \n+static int take_all_worktree_changes;\n static const char *excludes_file;\n \n static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)\n@@ -92,6 +97,44 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec)\n \t\tprune_directory(dir, pathspec, baselen);\n }\n \n+static void update_callback(struct diff_queue_struct *q,\n+\t\t\t    struct diff_options *opt, void *cbdata)\n+{\n+\tint i, verbose;\n+\n+\tverbose = *((int *)cbdata);\n+\tfor (i = 0; i < q->nr; i++) {\n+\t\tstruct diff_filepair *p = q->queue[i];\n+\t\tconst char *path = p->one->path;\n+\t\tswitch (p->status) {\n+\t\tdefault:\n+\t\t\tdie(\"unexpacted diff status %c\", p->status);\n+\t\tcase DIFF_STATUS_UNMERGED:\n+\t\tcase DIFF_STATUS_MODIFIED:\n+\t\t\tadd_file_to_cache(path, verbose);\n+\t\t\tbreak;\n+\t\tcase DIFF_STATUS_DELETED:\n+\t\t\tremove_file_from_cache(path);\n+\t\t\tif (verbose)\n+\t\t\t\tprintf(\"remove '%s'\\n\", path);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+static void update_all(int verbose)\n+{\n+\tstruct rev_info rev;\n+\tinit_revisions(&rev, \"\");\n+\tsetup_revisions(0, NULL, &rev, NULL);\n+\trev.diffopt.output_format = DIFF_FORMAT_CALLBACK;\n+\trev.diffopt.format_callback = update_callback;\n+\trev.diffopt.format_callback_data = &verbose;\n+\tif (read_cache() < 0)\n+\t\tdie(\"index file corrupt\");\n+\trun_diff_files(&rev, 0);\n+}\n+\n static int git_add_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"core.excludesfile\")) {\n@@ -156,8 +199,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\t\tverbose = 1;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"-u\")) {\n+\t\t\ttake_all_worktree_changes = 1;\n+\t\t\tcontinue;\n+\t\t}\n \t\tusage(builtin_add_usage);\n \t}\n+\n+\tif (take_all_worktree_changes) {\n+\t\tif (i < argc)\n+\t\t\tdie(\"-u and explicit paths are incompatible\");\n+\t\tupdate_all(verbose);\n+\t\tgoto finish;\n+\t}\n+\n \tif (argc <= i) {\n \t\tfprintf(stderr, \"Nothing specified, nothing added.\\n\");\n \t\tfprintf(stderr, \"Maybe you wanted to say 'git add .'?\\n\");\n@@ -207,6 +262,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tfor (i = 0; i < dir.nr; i++)\n \t\tadd_file_to_cache(dir.entries[i]->name, verbose);\n \n+ finish:\n \tif (active_cache_changed) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n \t\t    close(newfd) || commit_locked_index(&lock_file))\n-- \n1.5.1.1.942.g0a20\n"},{"id":"39952","messageId":"1177058540390-git-send-email-junkio@cox.net","threadId":"7753","inReplyTo":"11770585393395-git-send-email-junkio@cox.net","subject":"[PATCH] Do not show progress meter while checking files out.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-20T08:42:19Z","receivedAt":"2007-04-20T08:42:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Originally I thought it would take too long to check out many\nfiles and to prevent people from getting bored, I added progress\nmeter.  But it feels a bit too noisy; let's disable it.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n unpack-trees.c |   62 --------------------------------------------------------\n 1 files changed, 0 insertions(+), 62 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 5139481..1419653 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -288,73 +288,15 @@ static void unlink_entry(char *name)\n \t}\n }\n \n-static volatile sig_atomic_t progress_update;\n-\n-static void progress_interval(int signum)\n-{\n-\tprogress_update = 1;\n-}\n-\n-static void setup_progress_signal(void)\n-{\n-\tstruct sigaction sa;\n-\tstruct itimerval v;\n-\n-\tmemset(&sa, 0, sizeof(sa));\n-\tsa.sa_handler = progress_interval;\n-\tsigemptyset(&sa.sa_mask);\n-\tsa.sa_flags = SA_RESTART;\n-\tsigaction(SIGALRM, &sa, NULL);\n-\n-\tv.it_interval.tv_sec = 1;\n-\tv.it_interval.tv_usec = 0;\n-\tv.it_value = v.it_interval;\n-\tsetitimer(ITIMER_REAL, &v, NULL);\n-}\n-\n static struct checkout state;\n static void check_updates(struct cache_entry **src, int nr,\n \t\tstruct unpack_trees_options *o)\n {\n \tunsigned short mask = htons(CE_UPDATE);\n-\tunsigned last_percent = 200, cnt = 0, total = 0;\n-\n-\tif (o->update && o->verbose_update) {\n-\t\tfor (total = cnt = 0; cnt < nr; cnt++) {\n-\t\t\tstruct cache_entry *ce = src[cnt];\n-\t\t\tif (!ce->ce_mode || ce->ce_flags & mask)\n-\t\t\t\ttotal++;\n-\t\t}\n-\n-\t\t/* Don't bother doing this for very small updates */\n-\t\tif (total < 250)\n-\t\t\ttotal = 0;\n-\n-\t\tif (total) {\n-\t\t\tfprintf(stderr, \"Checking files out...\\n\");\n-\t\t\tsetup_progress_signal();\n-\t\t\tprogress_update = 1;\n-\t\t}\n-\t\tcnt = 0;\n-\t}\n \n \twhile (nr--) {\n \t\tstruct cache_entry *ce = *src++;\n \n-\t\tif (total) {\n-\t\t\tif (!ce->ce_mode || ce->ce_flags & mask) {\n-\t\t\t\tunsigned percent;\n-\t\t\t\tcnt++;\n-\t\t\t\tpercent = (cnt * 100) / total;\n-\t\t\t\tif (percent != last_percent ||\n-\t\t\t\t    progress_update) {\n-\t\t\t\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\",\n-\t\t\t\t\t\tpercent, cnt, total);\n-\t\t\t\t\tlast_percent = percent;\n-\t\t\t\t\tprogress_update = 0;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n \t\tif (!ce->ce_mode) {\n \t\t\tif (o->update)\n \t\t\t\tunlink_entry(ce->name);\n@@ -366,10 +308,6 @@ static void check_updates(struct cache_entry **src, int nr,\n \t\t\t\tcheckout_entry(ce, &state, NULL);\n \t\t}\n \t}\n-\tif (total) {\n-\t\tsignal(SIGALRM, SIG_IGN);\n-\t\tfputc('\\n', stderr);\n-\t}\n }\n \n int unpack_trees(struct object_list *trees, struct unpack_trees_options *o)\n-- \n1.5.1.1.942.g0a20\n"},{"id":"39955","messageId":"462889DC.44F4569@eudaptics.com","threadId":"7753","inReplyTo":"1177058540390-git-send-email-junkio@cox.net","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"Johannes Sixt","fromEmail":"j.sixt@eudaptics.com","sentAt":"2007-04-20T09:37:32Z","receivedAt":"2007-04-20T09:37:32Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Junio C Hamano wrote:\n> \n> Originally I thought it would take too long to check out many\n> files and to prevent people from getting bored, I added progress\n> meter.  But it feels a bit too noisy; let's disable it.\n\nHm. The only place where I've seen this particular progress meter is\nafter a clone. Which is quite noisy anyway.\n\nHere on my windows box, this progress meter *is* entertaining. My\nproject has ~2400 files, and it takes its time. If you really want to\nget rid of it, then please leave the message \"Checking out files...\",\nwhich together with a thrashing disk should give \"progress\" enough for\npeople who do their first clone.\n\n-- Hannes\n"},{"id":"39960","messageId":"20070420104930.GB13560@diana.vm.bytemark.co.uk","threadId":"7753","inReplyTo":"11770585393395-git-send-email-junkio@cox.net","subject":"Re: [PATCH] git-add -u: match the index with working tree.","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-04-20T10:49:30Z","receivedAt":"2007-04-20T10:49:30Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2007-04-20 01:42:18 -0700, Junio C Hamano wrote:\n\n> This is a shorthand of what \"git commit -a\" does in preparation\n> for making a commit,\n[snip]\n> -\"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...\";\n> +\"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n\nAny particular reason for choosing a different letter than the\n-a/--all that git commit uses?\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"39964","messageId":"7virbrz47b.fsf@assigned-by-dhcp.cox.net","threadId":"7753","inReplyTo":"20070420104930.GB13560@diana.vm.bytemark.co.uk","subject":"Re: [PATCH] git-add -u: match the index with working tree.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-20T11:16:08Z","receivedAt":"2007-04-20T11:16:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karl Hasselström <kha@treskal.com> writes:\n\n> On 2007-04-20 01:42:18 -0700, Junio C Hamano wrote:\n>\n>> This is a shorthand of what \"git commit -a\" does in preparation\n>> for making a commit,\n> [snip]\n>> -\"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...\";\n>> +\"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n>\n> Any particular reason for choosing a different letter than the\n> -a/--all that git commit uses?\n\nHaven't I explain that elsewhere already?\n"},{"id":"39965","messageId":"7vejmfz44g.fsf@assigned-by-dhcp.cox.net","threadId":"7753","inReplyTo":"20070420104930.GB13560@diana.vm.bytemark.co.uk","subject":"Re: [PATCH] git-add -u: match the index with working tree.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-20T11:17:51Z","receivedAt":"2007-04-20T11:17:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karl Hasselström <kha@treskal.com> writes:\n\n> On 2007-04-20 01:42:18 -0700, Junio C Hamano wrote:\n>\n>> This is a shorthand of what \"git commit -a\" does in preparation\n>> for making a commit,\n> [snip]\n>> -\"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...\";\n>> +\"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n>\n> Any particular reason for choosing a different letter than the\n> -a/--all that git commit uses?\n\nI picked \"-u\" instead of \"-a\" because I wanted to stress that\nthis is about \"updating\" (which has connotation that it is\nrelative to something, and in this case it is relative to the\ncurrent \"index\"), and not about \"all\", which \"-a\" would imply.\n"},{"id":"39966","messageId":"dbfc82860704200418o4d27b5a6pc3ea2f5abe25be8e@mail.gmail.com","threadId":"7753","inReplyTo":"7virbrz47b.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-add -u: match the index with working tree.","fromName":"Nikolai Weibull","fromEmail":"now@bitwi.se","sentAt":"2007-04-20T11:18:25Z","receivedAt":"2007-04-20T11:18:25Z","isPatch":true,"sender":{"key":"now@bitwi.se","avatar":"https://gravatar.com/avatar/d9242f067845cf9a72be23e4213c3b6e53492178e5df97372088a441af846133?d=mp&s=160"},"body":"On 4/20/07, Junio C Hamano <junkio@cox.net> wrote:\n> Karl Hasselström <kha@treskal.com> writes:\n>\n> > On 2007-04-20 01:42:18 -0700, Junio C Hamano wrote:\n> >\n> >> This is a shorthand of what \"git commit -a\" does in preparation\n> >> for making a commit,\n> > [snip]\n> >> -\"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...\";\n> >> +\"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n> >\n> > Any particular reason for choosing a different letter than the\n> > -a/--all that git commit uses?\n>\n> Haven't I explain that elsewhere already?\n\nYes, in <7vzm531ly3.fsf@assigned-by-dhcp.cox.net>.\n\nSpecifically:\n\n> I picked \"-u\" instead of \"-a\" because I wanted to stress that\n> this is about \"updating\" (which has connotation that it is\n> relative to something, and in this case it is relative to the\n> current \"index\"), and not about \"all\", which \"-a\" would imply.\n\n  nikolai\n"},{"id":"39969","messageId":"20070420113912.GA15378@diana.vm.bytemark.co.uk","threadId":"7753","inReplyTo":"dbfc82860704200418o4d27b5a6pc3ea2f5abe25be8e@mail.gmail.com","subject":"Re: [PATCH] git-add -u: match the index with working tree.","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-04-20T11:39:12Z","receivedAt":"2007-04-20T11:39:12Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2007-04-20 13:18:25 +0200, Nikolai Weibull wrote:\n\n> On 4/20/07, Junio C Hamano <junkio@cox.net> wrote:\n>\n> > Karl Hasselström <kha@treskal.com> writes:\n>\n> > > Any particular reason for choosing a different letter than the\n> > > -a/--all that git commit uses?\n> >\n> > Haven't I explain that elsewhere already?\n>\n> Yes, in <7vzm531ly3.fsf@assigned-by-dhcp.cox.net>.\n\nAh, I missed that. Sorry.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"39974","messageId":"200704201337.30836.andyparkins@gmail.com","threadId":"7753","inReplyTo":"1177058540390-git-send-email-junkio@cox.net","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-04-20T12:37:18Z","receivedAt":"2007-04-20T12:37:18Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007 April 20 09:42, Junio C Hamano wrote:\n> Originally I thought it would take too long to check out many\n> files and to prevent people from getting bored, I added progress\n> meter.  But it feels a bit too noisy; let's disable it.\n\nDon't do that.  I like it.\n\nI think you need output like this not to prevent boredom but to reassure that \nnothing has crashed or gone wild.  A checkout of a big project really can \ntake time, so it's nice to have the feedback.\n\nIncidentally, the other place that needs some sort of feedback is the \nbeginning of git-fetch/git-push.  I think they are off listing remote \nbranches, but they don't output anything before they do it, so I have no idea \nwhere the delay is (actually I know that the delay is from forming the ssh \nconnection - which seems to be unable to understand that I'm connecting over \na VPN and my IP has no reverse DNS so don't check for it - grr - but the \npoint is that nothing is (apparently) happening and I have no feedback to \nknow why).\n\nI'll submit a patch...\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"39975","messageId":"vpqabx3nrh6.fsf@bauges.imag.fr","threadId":"7753","inReplyTo":"1177058540390-git-send-email-junkio@cox.net","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2007-04-20T12:46:29Z","receivedAt":"2007-04-20T12:46:29Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Originally I thought it would take too long to check out many\n> files and to prevent people from getting bored, I added progress\n> meter.  But it feels a bit too noisy; let's disable it.\n\n[...]\n\n> -\t\t/* Don't bother doing this for very small updates */\n> -\t\tif (total < 250)\n> -\t\t\ttotal = 0;\n\n[...]\n\nAndy Parkins <andyparkins@gmail.com> writes:\n\n> Don't do that.  I like it.\n\nIf it's just to make it less noisy, perhaps adjusting the magic value\nabove would do it.\n\n-- \nMatthieu\n"},{"id":"39978","messageId":"alpine.LFD.0.98.0704200900460.4504@xanadu.home","threadId":"7753","inReplyTo":"1177058540390-git-send-email-junkio@cox.net","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-04-20T13:04:39Z","receivedAt":"2007-04-20T13:04:39Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Fri, 20 Apr 2007, Junio C Hamano wrote:\n\n> Originally I thought it would take too long to check out many\n> files and to prevent people from getting bored, I added progress\n> meter.  But it feels a bit too noisy; let's disable it.\n\nFor large checkouts, say after a big clone, that might be quite long to \ncheck out large amount of files.\n\nWhat about looking at the number of files checked out after say 2 \nseconds, and if it is still below 50% of the total then turn on the \nprogress display?\n\n\nNicolas\n"},{"id":"39979","messageId":"20070420131217.GA16077@fieldses.org","threadId":"7753","inReplyTo":"1177058540390-git-send-email-junkio@cox.net","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-04-20T13:12:17Z","receivedAt":"2007-04-20T13:12:17Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Fri, Apr 20, 2007 at 01:42:19AM -0700, Junio C Hamano wrote:\n> Originally I thought it would take too long to check out many\n> files and to prevent people from getting bored, I added progress\n> meter.  But it feels a bit too noisy; let's disable it.\n\nI was just doing a kernel-tree clone on an NFS filesystem yesterday, and\ncreating 20000 new files over NFS does take some time, so the progress\nmeter was appreciated.\n\n--b.\n"},{"id":"39986","messageId":"20070420144656.GA17480@spearce.org","threadId":"7753","inReplyTo":"alpine.LFD.0.98.0704200900460.4504@xanadu.home","subject":"Re: [PATCH] Do not show progress meter while checking files out.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-04-20T14:46:56Z","receivedAt":"2007-04-20T14:46:56Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Nicolas Pitre <nico@cam.org> wrote:\n> On Fri, 20 Apr 2007, Junio C Hamano wrote:\n> \n> > Originally I thought it would take too long to check out many\n> > files and to prevent people from getting bored, I added progress\n> > meter.  But it feels a bit too noisy; let's disable it.\n...\n> What about looking at the number of files checked out after say 2 \n> seconds, and if it is still below 50% of the total then turn on the \n> progress display?\n\nI agree completely with Nico, and everyone else.\n\nNico's approach is the right way to handle that particular progress\nmeter.  It should also be enabled the same way in git-checkout.sh\nand git-merge.sh (for the fast-forward case).\n\nOn Windows, with a cheap+slow 5400 RPM IDE drive, a slow processor\nand a virus scanner that has higher priority than the mouse driver,\na simple branch switch that updates only 500 files (out of almost\n10,000) can take 30 seconds.  Ok, sure, maybe I shouldn't switch\nbranches on such horrid hardware[*1*], but a progress meter would\nbe very nice for when I do.\n\nOn the other hand, the one I removed from merge-recursive was\nbraindamaged.  It only knew the amount of work remaining once it\nhad finished it.  That meant the meter was completely useless.\nThough maybe something based on a 2 second timer like Nico is\nproposing for read-tree might still be useful in merge-recursive.\n\n\n*1*: Of course my Solaris 9 system does that switch so fast it makes\n     my head spin.  Ahh, what a good system modern UNIXes are...\n\n-- \nShawn.\n"}]}