{"thread":{"id":"9792","subject":"[PATCH 5/9] Introduce strbuf_read_fd().","startedAt":"2007-09-06T00:23:30Z","lastAt":"2007-09-18T00:11:25Z","messageCount":25,"participants":["Kristian Høgsberg","Junio C Hamano","Pierre Habouzit","Johannes Schindelin","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":9},"messages":[{"id":"52657","messageId":"11890382183913-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":null,"subject":"[PATCH 1/9] Enable wt-status output to a given FILE pointer.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:30Z","receivedAt":"2007-09-06T00:23:30Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Still defaults to stdout, but you can now override wt_status.fp after\ncalling wt_status_prepare().\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n color.c     |   18 ++++++------\n color.h     |    4 +-\n wt-status.c |   85 ++++++++++++++++++++++++++++++----------------------------\n wt-status.h |    3 ++\n 4 files changed, 58 insertions(+), 52 deletions(-)\n\ndiff --git a/color.c b/color.c\nindex 09d82ee..124ba33 100644\n--- a/color.c\n+++ b/color.c\n@@ -135,39 +135,39 @@ int git_config_colorbool(const char *var, const char *value)\n \treturn git_config_bool(var, value);\n }\n \n-static int color_vprintf(const char *color, const char *fmt,\n+static int color_vfprintf(FILE *fp, const char *color, const char *fmt,\n \t\tva_list args, const char *trail)\n {\n \tint r = 0;\n \n \tif (*color)\n-\t\tr += printf(\"%s\", color);\n-\tr += vprintf(fmt, args);\n+\t\tr += fprintf(fp, \"%s\", color);\n+\tr += vfprintf(fp, fmt, args);\n \tif (*color)\n-\t\tr += printf(\"%s\", COLOR_RESET);\n+\t\tr += fprintf(fp, \"%s\", COLOR_RESET);\n \tif (trail)\n-\t\tr += printf(\"%s\", trail);\n+\t\tr += fprintf(fp, \"%s\", trail);\n \treturn r;\n }\n \n \n \n-int color_printf(const char *color, const char *fmt, ...)\n+int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)\n {\n \tva_list args;\n \tint r;\n \tva_start(args, fmt);\n-\tr = color_vprintf(color, fmt, args, NULL);\n+\tr = color_vfprintf(fp, color, fmt, args, NULL);\n \tva_end(args);\n \treturn r;\n }\n \n-int color_printf_ln(const char *color, const char *fmt, ...)\n+int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)\n {\n \tva_list args;\n \tint r;\n \tva_start(args, fmt);\n-\tr = color_vprintf(color, fmt, args, \"\\n\");\n+\tr = color_vfprintf(fp, color, fmt, args, \"\\n\");\n \tva_end(args);\n \treturn r;\n }\ndiff --git a/color.h b/color.h\nindex 88bb8ff..6809800 100644\n--- a/color.h\n+++ b/color.h\n@@ -6,7 +6,7 @@\n \n int git_config_colorbool(const char *var, const char *value);\n void color_parse(const char *var, const char *value, char *dst);\n-int color_printf(const char *color, const char *fmt, ...);\n-int color_printf_ln(const char *color, const char *fmt, ...);\n+int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);\n+int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);\n \n #endif /* COLOR_H */\ndiff --git a/wt-status.c b/wt-status.c\nindex 5205420..65a7259 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -52,31 +52,33 @@ void wt_status_prepare(struct wt_status *s)\n \thead = resolve_ref(\"HEAD\", sha1, 0, NULL);\n \ts->branch = head ? xstrdup(head) : NULL;\n \ts->reference = \"HEAD\";\n+\ts->fp = stdout;\n }\n \n-static void wt_status_print_cached_header(const char *reference)\n+static void wt_status_print_cached_header(struct wt_status *s)\n {\n \tconst char *c = color(WT_STATUS_HEADER);\n-\tcolor_printf_ln(c, \"# Changes to be committed:\");\n-\tif (reference) {\n-\t\tcolor_printf_ln(c, \"#   (use \\\"git reset %s <file>...\\\" to unstage)\", reference);\n+\tcolor_fprintf_ln(s->fp, c, \"# Changes to be committed:\");\n+\tif (s->reference) {\n+\t\tcolor_fprintf_ln(s->fp, c, \"#   (use \\\"git reset %s <file>...\\\" to unstage)\", s->reference);\n \t} else {\n-\t\tcolor_printf_ln(c, \"#   (use \\\"git rm --cached <file>...\\\" to unstage)\");\n+\t\tcolor_fprintf_ln(s->fp, c, \"#   (use \\\"git rm --cached <file>...\\\" to unstage)\");\n \t}\n-\tcolor_printf_ln(c, \"#\");\n+\tcolor_fprintf_ln(s->fp, c, \"#\");\n }\n \n-static void wt_status_print_header(const char *main, const char *sub)\n+static void wt_status_print_header(struct wt_status *s,\n+\t\t\t\t   const char *main, const char *sub)\n {\n \tconst char *c = color(WT_STATUS_HEADER);\n-\tcolor_printf_ln(c, \"# %s:\", main);\n-\tcolor_printf_ln(c, \"#   (%s)\", sub);\n-\tcolor_printf_ln(c, \"#\");\n+\tcolor_fprintf_ln(s->fp, c, \"# %s:\", main);\n+\tcolor_fprintf_ln(s->fp, c, \"#   (%s)\", sub);\n+\tcolor_fprintf_ln(s->fp, c, \"#\");\n }\n \n-static void wt_status_print_trailer(void)\n+static void wt_status_print_trailer(struct wt_status *s)\n {\n-\tcolor_printf_ln(color(WT_STATUS_HEADER), \"#\");\n+\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER), \"#\");\n }\n \n static const char *quote_crlf(const char *in, char *buf, size_t sz)\n@@ -108,7 +110,8 @@ static const char *quote_crlf(const char *in, char *buf, size_t sz)\n \treturn ret;\n }\n \n-static void wt_status_print_filepair(int t, struct diff_filepair *p)\n+static void wt_status_print_filepair(struct wt_status *s,\n+\t\t\t\t     int t, struct diff_filepair *p)\n {\n \tconst char *c = color(t);\n \tconst char *one, *two;\n@@ -117,36 +120,36 @@ static void wt_status_print_filepair(int t, struct diff_filepair *p)\n \tone = quote_crlf(p->one->path, onebuf, sizeof(onebuf));\n \ttwo = quote_crlf(p->two->path, twobuf, sizeof(twobuf));\n \n-\tcolor_printf(color(WT_STATUS_HEADER), \"#\\t\");\n+\tcolor_fprintf(s->fp, color(WT_STATUS_HEADER), \"#\\t\");\n \tswitch (p->status) {\n \tcase DIFF_STATUS_ADDED:\n-\t\tcolor_printf(c, \"new file:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"new file:   %s\", one);\n \t\tbreak;\n \tcase DIFF_STATUS_COPIED:\n-\t\tcolor_printf(c, \"copied:     %s -> %s\", one, two);\n+\t\tcolor_fprintf(s->fp, c, \"copied:     %s -> %s\", one, two);\n \t\tbreak;\n \tcase DIFF_STATUS_DELETED:\n-\t\tcolor_printf(c, \"deleted:    %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"deleted:    %s\", one);\n \t\tbreak;\n \tcase DIFF_STATUS_MODIFIED:\n-\t\tcolor_printf(c, \"modified:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"modified:   %s\", one);\n \t\tbreak;\n \tcase DIFF_STATUS_RENAMED:\n-\t\tcolor_printf(c, \"renamed:    %s -> %s\", one, two);\n+\t\tcolor_fprintf(s->fp, c, \"renamed:    %s -> %s\", one, two);\n \t\tbreak;\n \tcase DIFF_STATUS_TYPE_CHANGED:\n-\t\tcolor_printf(c, \"typechange: %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"typechange: %s\", one);\n \t\tbreak;\n \tcase DIFF_STATUS_UNKNOWN:\n-\t\tcolor_printf(c, \"unknown:    %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"unknown:    %s\", one);\n \t\tbreak;\n \tcase DIFF_STATUS_UNMERGED:\n-\t\tcolor_printf(c, \"unmerged:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"unmerged:   %s\", one);\n \t\tbreak;\n \tdefault:\n \t\tdie(\"bug: unhandled diff status %c\", p->status);\n \t}\n-\tprintf(\"\\n\");\n+\tfprintf(s->fp, \"\\n\");\n }\n \n static void wt_status_print_updated_cb(struct diff_queue_struct *q,\n@@ -160,14 +163,14 @@ static void wt_status_print_updated_cb(struct diff_queue_struct *q,\n \t\tif (q->queue[i]->status == 'U')\n \t\t\tcontinue;\n \t\tif (!shown_header) {\n-\t\t\twt_status_print_cached_header(s->reference);\n+\t\t\twt_status_print_cached_header(s);\n \t\t\ts->commitable = 1;\n \t\t\tshown_header = 1;\n \t\t}\n-\t\twt_status_print_filepair(WT_STATUS_UPDATED, q->queue[i]);\n+\t\twt_status_print_filepair(s, WT_STATUS_UPDATED, q->queue[i]);\n \t}\n \tif (shown_header)\n-\t\twt_status_print_trailer();\n+\t\twt_status_print_trailer(s);\n }\n \n static void wt_status_print_changed_cb(struct diff_queue_struct *q,\n@@ -184,12 +187,12 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q,\n \t\t\t\tmsg = use_add_rm_msg;\n \t\t\t\tbreak;\n \t\t\t}\n-\t\twt_status_print_header(\"Changed but not updated\", msg);\n+\t\twt_status_print_header(s, \"Changed but not updated\", msg);\n \t}\n \tfor (i = 0; i < q->nr; i++)\n-\t\twt_status_print_filepair(WT_STATUS_CHANGED, q->queue[i]);\n+\t\twt_status_print_filepair(s, WT_STATUS_CHANGED, q->queue[i]);\n \tif (q->nr)\n-\t\twt_status_print_trailer();\n+\t\twt_status_print_trailer(s);\n }\n \n static void wt_read_cache(struct wt_status *s)\n@@ -206,16 +209,16 @@ static void wt_status_print_initial(struct wt_status *s)\n \twt_read_cache(s);\n \tif (active_nr) {\n \t\ts->commitable = 1;\n-\t\twt_status_print_cached_header(NULL);\n+\t\twt_status_print_cached_header(s);\n \t}\n \tfor (i = 0; i < active_nr; i++) {\n-\t\tcolor_printf(color(WT_STATUS_HEADER), \"#\\t\");\n-\t\tcolor_printf_ln(color(WT_STATUS_UPDATED), \"new file: %s\",\n+\t\tcolor_fprintf(s->fp, color(WT_STATUS_HEADER), \"#\\t\");\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), \"new file: %s\",\n \t\t\t\tquote_crlf(active_cache[i]->name,\n \t\t\t\t\t   buf, sizeof(buf)));\n \t}\n \tif (active_nr)\n-\t\twt_status_print_trailer();\n+\t\twt_status_print_trailer(s);\n }\n \n static void wt_status_print_updated(struct wt_status *s)\n@@ -281,12 +284,12 @@ static void wt_status_print_untracked(struct wt_status *s)\n \t\t}\n \t\tif (!shown_header) {\n \t\t\ts->workdir_untracked = 1;\n-\t\t\twt_status_print_header(\"Untracked files\",\n+\t\t\twt_status_print_header(s, \"Untracked files\",\n \t\t\t\t\t       use_add_to_include_msg);\n \t\t\tshown_header = 1;\n \t\t}\n-\t\tcolor_printf(color(WT_STATUS_HEADER), \"#\\t\");\n-\t\tcolor_printf_ln(color(WT_STATUS_UNTRACKED), \"%.*s\",\n+\t\tcolor_fprintf(s->fp, color(WT_STATUS_HEADER), \"#\\t\");\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), \"%.*s\",\n \t\t\t\tent->len, ent->name);\n \t}\n }\n@@ -316,14 +319,14 @@ void wt_status_print(struct wt_status *s)\n \t\t\tbranch_name = \"\";\n \t\t\ton_what = \"Not currently on any branch.\";\n \t\t}\n-\t\tcolor_printf_ln(color(WT_STATUS_HEADER),\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER),\n \t\t\t\"# %s%s\", on_what, branch_name);\n \t}\n \n \tif (s->is_initial) {\n-\t\tcolor_printf_ln(color(WT_STATUS_HEADER), \"#\");\n-\t\tcolor_printf_ln(color(WT_STATUS_HEADER), \"# Initial commit\");\n-\t\tcolor_printf_ln(color(WT_STATUS_HEADER), \"#\");\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER), \"#\");\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER), \"# Initial commit\");\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER), \"#\");\n \t\twt_status_print_initial(s);\n \t}\n \telse {\n@@ -337,7 +340,7 @@ void wt_status_print(struct wt_status *s)\n \t\twt_status_print_verbose(s);\n \tif (!s->commitable) {\n \t\tif (s->amend)\n-\t\t\tprintf(\"# No changes\\n\");\n+\t\t\tfprintf(s->fp, \"# No changes\\n\");\n \t\telse if (s->workdir_dirty)\n \t\t\tprintf(\"no changes added to commit (use \\\"git add\\\" and/or \\\"git commit -a\\\")\\n\");\n \t\telse if (s->workdir_untracked)\ndiff --git a/wt-status.h b/wt-status.h\nindex cfea4ae..4f3a615 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -1,6 +1,8 @@\n #ifndef STATUS_H\n #define STATUS_H\n \n+#include <stdio.h>\n+\n enum color_wt_status {\n \tWT_STATUS_HEADER,\n \tWT_STATUS_UPDATED,\n@@ -19,6 +21,7 @@ struct wt_status {\n \tint commitable;\n \tint workdir_dirty;\n \tint workdir_untracked;\n+\tFILE *fp;\n };\n \n int git_status_config(const char *var, const char *value);\n-- \n1.5.2.GIT\n"},{"id":"52654","messageId":"11890382242333-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382183913-git-send-email-krh@redhat.com","subject":"[PATCH 2/9] Enable wt-status to run against non-standard index file.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:31Z","receivedAt":"2007-09-06T00:23:31Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"We still default to get_index_file(), but this can be overridden\nby setting wt_status.index_file after calling wt_status_prepare().\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n wt-status.c |    3 ++-\n wt-status.h |    1 +\n 2 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 65a7259..0cf9b81 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -53,6 +53,7 @@ void wt_status_prepare(struct wt_status *s)\n \ts->branch = head ? xstrdup(head) : NULL;\n \ts->reference = \"HEAD\";\n \ts->fp = stdout;\n+\ts->index_file = get_index_file();\n }\n \n static void wt_status_print_cached_header(struct wt_status *s)\n@@ -198,7 +199,7 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q,\n static void wt_read_cache(struct wt_status *s)\n {\n \tdiscard_cache();\n-\tread_cache();\n+\tread_cache_from(s->index_file);\n }\n \n static void wt_status_print_initial(struct wt_status *s)\ndiff --git a/wt-status.h b/wt-status.h\nindex 4f3a615..7744932 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -21,6 +21,7 @@ struct wt_status {\n \tint commitable;\n \tint workdir_dirty;\n \tint workdir_untracked;\n+\tconst char *index_file;\n \tFILE *fp;\n };\n \n-- \n1.5.2.GIT\n"},{"id":"52656","messageId":"11890382243290-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382242333-git-send-email-krh@redhat.com","subject":"[PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:32Z","receivedAt":"2007-09-06T00:23:32Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Also, expose strbuf_add() and strbuf_add_char() to add raw data to the buffer.\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n strbuf.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------\n strbuf.h |    3 ++\n 2 files changed, 65 insertions(+), 7 deletions(-)\n\ndiff --git a/strbuf.c b/strbuf.c\nindex e33d06b..2805c11 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -11,16 +11,26 @@ static void strbuf_begin(struct strbuf *sb) {\n \tstrbuf_init(sb);\n }\n \n-static void inline strbuf_add(struct strbuf *sb, int ch) {\n-\tif (sb->alloc <= sb->len) {\n-\t\tsb->alloc = sb->alloc * 3 / 2 + 16;\n-\t\tsb->buf = xrealloc(sb->buf, sb->alloc);\n-\t}\n+static void inline strbuf_grow(struct strbuf *sb, size_t extra)\n+{\n+\tALLOC_GROW(sb->buf, sb->len + extra, sb->alloc);\n+}\n+\n+void strbuf_add(struct strbuf *sb, const char *data, size_t len)\n+{\n+\tstrbuf_grow(sb, len);\n+\tmemcpy(sb->buf + sb->len, data, len);\n+\tsb->len += len;\n+}\n+\n+void strbuf_add_char(struct strbuf *sb, int ch)\n+{\n+\tstrbuf_grow(sb, 1);\n \tsb->buf[sb->len++] = ch;\n }\n \n static void strbuf_end(struct strbuf *sb) {\n-\tstrbuf_add(sb, 0);\n+\tstrbuf_add_char(sb, 0);\n }\n \n void read_line(struct strbuf *sb, FILE *fp, int term) {\n@@ -33,9 +43,54 @@ void read_line(struct strbuf *sb, FILE *fp, int term) {\n \twhile ((ch = fgetc(fp)) != EOF) {\n \t\tif (ch == term)\n \t\t\tbreak;\n-\t\tstrbuf_add(sb, ch);\n+\t\tstrbuf_add_char(sb, ch);\n \t}\n \tif (ch == EOF && sb->len == 0)\n \t\tsb->eof = 1;\n \tstrbuf_end(sb);\n }\n+\n+void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tchar buffer[2048];\n+\tva_list args;\n+\tint len, size = 2 * sizeof buffer;\n+\n+\tva_start(args, fmt);\n+\tlen = vsnprintf(buffer, sizeof(buffer), fmt, args);\n+\tva_end(args);\n+\n+\tif (len > sizeof(buffer)) {\n+\t\t/*\n+\t\t * Didn't fit in the buffer, but this vsnprintf at\n+\t\t * least gives us the required length back.  Grow the\n+\t\t * buffer acccordingly and try again.\n+\t\t */\n+\t\tstrbuf_grow(sb, len);\n+\t\tva_start(args, fmt);\n+\t\tlen = vsnprintf(sb->buf + sb->len,\n+\t\t\t\tsb->alloc - sb->len, fmt, args);\n+\t\tva_end(args);\n+\t} else if (len >= 0) {\n+\t\t/*\n+\t\t * The initial vsnprintf fit in the temp buffer, just\n+\t\t * copy it to the strbuf.\n+\t\t */\n+\t\tstrbuf_add(sb, buffer, len);\n+\t} else {\n+\t\t/*\n+\t\t * This vnsprintf sucks and just returns -1 when the\n+\t\t * buffer is too small.  Keep doubling the size until\n+\t\t * it fits.\n+\t\t */\n+\t\twhile (len < 0) {\n+\t\t\tstrbuf_grow(sb, size);\n+\t\t\tva_start(args, fmt);\n+\t\t\tlen = vsnprintf(sb->buf + sb->len,\n+\t\t\t\t\tsb->alloc - sb->len, fmt, args);\n+\t\t\tva_end(args);\n+\t\t\tsize *= 2;\n+\t\t}\n+\t}\n+}\n+\ndiff --git a/strbuf.h b/strbuf.h\nindex 74cc012..1e5d09e 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -9,5 +9,8 @@ struct strbuf {\n \n extern void strbuf_init(struct strbuf *);\n extern void read_line(struct strbuf *, FILE *, int);\n+extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);\n+extern void strbuf_add_char(struct strbuf *sb, int ch);\n+extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);\n \n #endif /* STRBUF_H */\n-- \n1.5.2.GIT\n"},{"id":"52655","messageId":"11890382253220-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382243290-git-send-email-krh@redhat.com","subject":"[PATCH 4/9] Introduce entry point for launching add--interactive.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:33Z","receivedAt":"2007-09-06T00:23:33Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"This refactors builtin-add.c a little to provide a unique entry point\nfor launching git add --interactive, which will be used by\nbuiltin-commit too.  If we later want to make add --interactive a\nbuiltin or change how it is launched, we just start from this function.\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n builtin-add.c |   15 ++++++++++-----\n commit.h      |    9 +++++++++\n 2 files changed, 19 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 3dd4ded..e79e8f7 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -12,6 +12,7 @@\n #include \"diffcore.h\"\n #include \"commit.h\"\n #include \"revision.h\"\n+#include \"run-command.h\"\n \n static const char builtin_add_usage[] =\n \"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...\";\n@@ -153,6 +154,13 @@ static int git_add_config(const char *var, const char *value)\n \treturn git_default_config(var, value);\n }\n \n+int interactive_add(void)\n+{\n+\tconst char *argv[2] = { \"add--interactive\", NULL };\n+\n+\treturn run_command_v_opt(argv, RUN_GIT_CMD);\n+}\n+\n static struct lock_file lock_file;\n \n static const char ignore_warning[] =\n@@ -172,12 +180,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\t\tadd_interactive++;\n \t}\n \tif (add_interactive) {\n-\t\tconst char *args[] = { \"add--interactive\", NULL };\n-\n-\t\tif (add_interactive != 1 || argc != 2)\n+\t\tif (argc != 2)\n \t\t\tdie(\"add --interactive does not take any parameters\");\n-\t\texecv_git_cmd(args);\n-\t\texit(1);\n+\t\texit(interactive_add());\n \t}\n \n \tgit_config(git_add_config);\ndiff --git a/commit.h b/commit.h\nindex 467872e..64e1d4b 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -122,4 +122,13 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,\n \t\tint depth, int shallow_flag, int not_shallow_flag);\n \n int in_merge_bases(struct commit *, struct commit **, int);\n+\n+extern const unsigned char *\n+create_commit(const unsigned char *tree_sha1,\n+\t      unsigned char parent_sha1[][20], int parents,\n+\t      const char *author_info, const char *committer_info,\n+\t      const char *message, int length);\n+\n+extern int interactive_add(void);\n+\n #endif /* COMMIT_H */\n-- \n1.5.2.GIT\n"},{"id":"52653","messageId":"11890382252522-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382253220-git-send-email-krh@redhat.com","subject":"[PATCH 5/9] Introduce strbuf_read_fd().","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:34Z","receivedAt":"2007-09-06T00:23:34Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"This function reads from a given fd into a strbuf until end of file.\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n strbuf.c |   19 +++++++++++++++++++\n strbuf.h |    1 +\n 2 files changed, 20 insertions(+), 0 deletions(-)\n\ndiff --git a/strbuf.c b/strbuf.c\nindex 2805c11..fcfc05e 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -50,6 +50,25 @@ void read_line(struct strbuf *sb, FILE *fp, int term) {\n \tstrbuf_end(sb);\n }\n \n+int strbuf_read_fd(struct strbuf *sb, int fd)\n+{\n+\tint len, total = 0;\n+\n+\tdo {\n+\t\tstrbuf_grow(sb, 1024);\n+\t\tlen = xread(fd, sb->buf + sb->len, sb->alloc - sb->len);\n+\t\tif (len > 0) {\n+\t\t\ttotal += len;\n+\t\t\tsb->len += len;\n+\t\t}\n+\t} while (len > 0);\n+\n+\tif (len < 0)\n+\t\treturn len;\n+\n+\treturn total;\n+}\n+\n void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n {\n \tchar buffer[2048];\ndiff --git a/strbuf.h b/strbuf.h\nindex 1e5d09e..6e630ea 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -12,5 +12,6 @@ extern void read_line(struct strbuf *, FILE *, int);\n extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);\n extern void strbuf_add_char(struct strbuf *sb, int ch);\n extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);\n+extern int strbuf_read_fd(struct strbuf *sb, int fd);\n \n #endif /* STRBUF_H */\n-- \n1.5.2.GIT\n"},{"id":"52659","messageId":"1189038225525-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382252522-git-send-email-krh@redhat.com","subject":"[PATCH 6/9] Rewrite launch_editor, create_tag and stripspace to use strbufs.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:35Z","receivedAt":"2007-09-06T00:23:35Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Signed-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n builtin-stripspace.c |   45 +++++++++++++-------------\n builtin-tag.c        |   84 +++++++++++++++++++++-----------------------------\n builtin.h            |    1 -\n strbuf.c             |   43 +++++---------------------\n strbuf.h             |    2 +\n 5 files changed, 68 insertions(+), 107 deletions(-)\n\ndiff --git a/builtin-stripspace.c b/builtin-stripspace.c\nindex 916355c..f0264a8 100644\n--- a/builtin-stripspace.c\n+++ b/builtin-stripspace.c\n@@ -1,5 +1,6 @@\n #include \"builtin.h\"\n #include \"cache.h\"\n+#include \"strbuf.h\"\n \n /*\n  * Returns the length of a line, without trailing spaces.\n@@ -34,34 +35,34 @@ static size_t cleanup(char *line, size_t len)\n  * If the input has only empty lines and spaces,\n  * no output will be produced.\n  *\n- * If last line has a newline at the end, it will be removed.\n+ * If the last line does not have a newline, one will be added.\n  *\n  * Enable skip_comments to skip every line starting with \"#\".\n  */\n-size_t stripspace(char *buffer, size_t length, int skip_comments)\n+size_t stripspace(struct strbuf *sb, int skip_comments)\n {\n \tint empties = -1;\n \tsize_t i, j, len, newlen;\n \tchar *eol;\n \n-\tfor (i = j = 0; i < length; i += len, j += newlen) {\n-\t\teol = memchr(buffer + i, '\\n', length - i);\n-\t\tlen = eol ? eol - (buffer + i) + 1 : length - i;\n+\tfor (i = j = 0; i < sb->len; i += len, j += newlen) {\n+\t\teol = memchr(sb->buf + i, '\\n', sb->len - i);\n+\t\tlen = eol ? eol - (sb->buf + i) + 1 : sb->len - i;\n \n-\t\tif (skip_comments && len && buffer[i] == '#') {\n+\t\tif (skip_comments && len && sb->buf[i] == '#') {\n \t\t\tnewlen = 0;\n \t\t\tcontinue;\n \t\t}\n-\t\tnewlen = cleanup(buffer + i, len);\n+\t\tnewlen = cleanup(sb->buf + i, len);\n \n \t\t/* Not just an empty line? */\n \t\tif (newlen) {\n \t\t\tif (empties != -1)\n-\t\t\t\tbuffer[j++] = '\\n';\n+\t\t\t\tsb->buf[j++] = '\\n';\n \t\t\tif (empties > 0)\n-\t\t\t\tbuffer[j++] = '\\n';\n+\t\t\t\tsb->buf[j++] = '\\n';\n \t\t\tempties = 0;\n-\t\t\tmemmove(buffer + j, buffer + i, newlen);\n+\t\t\tmemmove(sb->buf + j, sb->buf + i, newlen);\n \t\t\tcontinue;\n \t\t}\n \t\tif (empties < 0)\n@@ -69,31 +70,31 @@ size_t stripspace(char *buffer, size_t length, int skip_comments)\n \t\tempties++;\n \t}\n \n-\treturn j;\n+\tsb->len = j;\n+\tif (j > 0)\n+\t\tstrbuf_add_char(sb, '\\n');\n+\n+\treturn sb->len;\n }\n \n int cmd_stripspace(int argc, const char **argv, const char *prefix)\n {\n-\tchar *buffer;\n-\tunsigned long size;\n+\tstruct strbuf sb;\n \tint strip_comments = 0;\n \n \tif (argc > 1 && (!strcmp(argv[1], \"-s\") ||\n \t\t\t\t!strcmp(argv[1], \"--strip-comments\")))\n \t\tstrip_comments = 1;\n \n-\tsize = 1024;\n-\tbuffer = xmalloc(size);\n-\tif (read_fd(0, &buffer, &size)) {\n-\t\tfree(buffer);\n+\tstrbuf_init(&sb);\n+\tif (strbuf_read_fd(&sb, 0) < 0) {\n+\t\tstrbuf_release(&sb);\n \t\tdie(\"could not read the input\");\n \t}\n \n-\tsize = stripspace(buffer, size, strip_comments);\n-\twrite_or_die(1, buffer, size);\n-\tif (size)\n-\t\tputc('\\n', stdout);\n+\tstripspace(&sb, strip_comments);\n+\twrite_or_die(1, sb.buf, sb.len);\n+\tstrbuf_release(&sb);\n \n-\tfree(buffer);\n \treturn 0;\n }\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex d6d38ad..1aff952 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -11,13 +11,14 @@\n #include \"refs.h\"\n #include \"tag.h\"\n #include \"run-command.h\"\n+#include \"strbuf.h\"\n \n static const char builtin_tag_usage[] =\n   \"git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>] <tagname> [<head>]\";\n \n static char signingkey[1000];\n \n-static void launch_editor(const char *path, char **buffer, unsigned long *len)\n+static void launch_editor(const char *path, struct strbuf *sb)\n {\n \tconst char *editor, *terminal;\n \tstruct child_process child;\n@@ -55,10 +56,9 @@ static void launch_editor(const char *path, char **buffer, unsigned long *len)\n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n \t\tdie(\"could not open '%s': %s\", path, strerror(errno));\n-\tif (read_fd(fd, buffer, len)) {\n-\t\tfree(*buffer);\n+\tif (strbuf_read_fd(sb, fd) < 0) {\n \t\tdie(\"could not read message file '%s': %s\",\n-\t\t\t\t\t\tpath, strerror(errno));\n+\t\t    path, strerror(errno));\n \t}\n \tclose(fd);\n }\n@@ -191,7 +191,7 @@ static int verify_tag(const char *name, const char *ref,\n \treturn 0;\n }\n \n-static ssize_t do_sign(char *buffer, size_t size, size_t max)\n+static int do_sign(struct strbuf *sb)\n {\n \tstruct child_process gpg;\n \tconst char *args[4];\n@@ -219,17 +219,13 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)\n \tif (start_command(&gpg))\n \t\treturn error(\"could not run gpg.\");\n \n-\twrite_or_die(gpg.in, buffer, size);\n+\twrite_or_die(gpg.in, sb->buf, sb->len);\n \tclose(gpg.in);\n \tgpg.close_in = 0;\n-\tlen = read_in_full(gpg.out, buffer + size, max - size);\n-\n+\tlen = strbuf_read_fd(sb, gpg.out);\n \tfinish_command(&gpg);\n \n-\tif (len == max - size)\n-\t\treturn error(\"could not read the entire signature from gpg.\");\n-\n-\treturn size + len;\n+\treturn len;\n }\n \n static const char tag_template[] =\n@@ -258,26 +254,24 @@ static void create_tag(const unsigned char *object, const char *tag,\n \t\t       char *message, int sign, unsigned char *result)\n {\n \tenum object_type type;\n-\tchar header_buf[1024], *buffer = NULL;\n-\tint header_len, max_size;\n-\tunsigned long size = 0;\n+\tstruct strbuf sb;\n+\tint header_len;\n \n \ttype = sha1_object_info(object, NULL);\n \tif (type <= OBJ_NONE)\n \t    die(\"bad object type.\");\n \n-\theader_len = snprintf(header_buf, sizeof(header_buf),\n-\t\t\t  \"object %s\\n\"\n-\t\t\t  \"type %s\\n\"\n-\t\t\t  \"tag %s\\n\"\n-\t\t\t  \"tagger %s\\n\\n\",\n-\t\t\t  sha1_to_hex(object),\n-\t\t\t  typename(type),\n-\t\t\t  tag,\n-\t\t\t  git_committer_info(1));\n-\n-\tif (header_len > sizeof(header_buf) - 1)\n-\t\tdie(\"tag header too big.\");\n+\tstrbuf_init(&sb);\n+\tstrbuf_printf(&sb,\n+\t\t      \"object %s\\n\"\n+\t\t      \"type %s\\n\"\n+\t\t      \"tag %s\\n\"\n+\t\t      \"tagger %s\\n\\n\",\n+\t\t      sha1_to_hex(object),\n+\t\t      typename(type),\n+\t\t      tag,\n+\t\t      git_committer_info(1));\n+\theader_len = sb.len;\n \n \tif (!message) {\n \t\tchar *path;\n@@ -292,39 +286,31 @@ static void create_tag(const unsigned char *object, const char *tag,\n \t\twrite_or_die(fd, tag_template, strlen(tag_template));\n \t\tclose(fd);\n \n-\t\tlaunch_editor(path, &buffer, &size);\n+\t\tlaunch_editor(path, &sb);\n \n \t\tunlink(path);\n \t\tfree(path);\n \t}\n \telse {\n-\t\tbuffer = message;\n-\t\tsize = strlen(message);\n+\t\tstrbuf_add(&sb, message, strlen(message));\n \t}\n \n-\tsize = stripspace(buffer, size, 1);\n-\n-\tif (!message && !size)\n+\tif (stripspace(&sb, 1) <= header_len && !message)\n \t\tdie(\"no tag message?\");\n \n-\t/* insert the header and add the '\\n' if needed: */\n-\tmax_size = header_len + size + (sign ? MAX_SIGNATURE_LENGTH : 0) + 1;\n-\tbuffer = xrealloc(buffer, max_size);\n-\tif (size)\n-\t\tbuffer[size++] = '\\n';\n-\tmemmove(buffer + header_len, buffer, size);\n-\tmemcpy(buffer, header_buf, header_len);\n-\tsize += header_len;\n-\n-\tif (sign) {\n-\t\tsize = do_sign(buffer, size, max_size);\n-\t\tif (size < 0)\n-\t\t\tdie(\"unable to sign the tag\");\n-\t}\n+\t/* Debatable, but makes t7401-tag.sh pass.  Creates an extra\n+\t * blank line after the header block for tags with empty\n+\t * messages. */\n+\tif (sb.len < header_len)\n+\t\tstrbuf_add_char(&sb, '\\n');\n \n-\tif (write_sha1_file(buffer, size, tag_type, result) < 0)\n+\tif (sign && do_sign(&sb) < 0)\n+\t\tdie(\"unable to sign the tag\");\n+\n+\tif (write_sha1_file(sb.buf, sb.len, tag_type, result) < 0)\n \t\tdie(\"unable to write tag file\");\n-\tfree(buffer);\n+\n+\tstrbuf_release(&sb);\n }\n \n int cmd_tag(int argc, const char **argv, const char *prefix)\ndiff --git a/builtin.h b/builtin.h\nindex bb72000..91bc595 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -7,7 +7,6 @@ extern const char git_version_string[];\n extern const char git_usage_string[];\n \n extern void help_unknown_cmd(const char *cmd);\n-extern size_t stripspace(char *buffer, size_t length, int skip_comments);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\n extern void prune_packed_objects(int);\n \ndiff --git a/strbuf.c b/strbuf.c\nindex fcfc05e..ed2afea 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -6,7 +6,8 @@ void strbuf_init(struct strbuf *sb) {\n \tsb->eof = sb->alloc = sb->len = 0;\n }\n \n-static void strbuf_begin(struct strbuf *sb) {\n+void strbuf_release(struct strbuf *sb)\n+{\n \tfree(sb->buf);\n \tstrbuf_init(sb);\n }\n@@ -35,7 +36,7 @@ static void strbuf_end(struct strbuf *sb) {\n \n void read_line(struct strbuf *sb, FILE *fp, int term) {\n \tint ch;\n-\tstrbuf_begin(sb);\n+\tstrbuf_release(sb);\n \tif (feof(fp)) {\n \t\tsb->eof = 1;\n \t\treturn;\n@@ -73,43 +74,15 @@ void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n {\n \tchar buffer[2048];\n \tva_list args;\n-\tint len, size = 2 * sizeof buffer;\n+\tint len;\n \n \tva_start(args, fmt);\n \tlen = vsnprintf(buffer, sizeof(buffer), fmt, args);\n \tva_end(args);\n \n-\tif (len > sizeof(buffer)) {\n-\t\t/*\n-\t\t * Didn't fit in the buffer, but this vsnprintf at\n-\t\t * least gives us the required length back.  Grow the\n-\t\t * buffer acccordingly and try again.\n-\t\t */\n-\t\tstrbuf_grow(sb, len);\n-\t\tva_start(args, fmt);\n-\t\tlen = vsnprintf(sb->buf + sb->len,\n-\t\t\t\tsb->alloc - sb->len, fmt, args);\n-\t\tva_end(args);\n-\t} else if (len >= 0) {\n-\t\t/*\n-\t\t * The initial vsnprintf fit in the temp buffer, just\n-\t\t * copy it to the strbuf.\n-\t\t */\n-\t\tstrbuf_add(sb, buffer, len);\n-\t} else {\n-\t\t/*\n-\t\t * This vnsprintf sucks and just returns -1 when the\n-\t\t * buffer is too small.  Keep doubling the size until\n-\t\t * it fits.\n-\t\t */\n-\t\twhile (len < 0) {\n-\t\t\tstrbuf_grow(sb, size);\n-\t\t\tva_start(args, fmt);\n-\t\t\tlen = vsnprintf(sb->buf + sb->len,\n-\t\t\t\t\tsb->alloc - sb->len, fmt, args);\n-\t\t\tva_end(args);\n-\t\t\tsize *= 2;\n-\t\t}\n-\t}\n+\tif (len > sizeof(buffer) || len < 0)\n+\t\tdie(\"out of buffer space\\n\");\n+\n+\tstrbuf_add(sb, buffer, len);\n }\n \ndiff --git a/strbuf.h b/strbuf.h\nindex 6e630ea..a93b9e1 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -8,10 +8,12 @@ struct strbuf {\n };\n \n extern void strbuf_init(struct strbuf *);\n+extern void strbuf_release(struct strbuf *);\n extern void read_line(struct strbuf *, FILE *, int);\n extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);\n extern void strbuf_add_char(struct strbuf *sb, int ch);\n extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);\n extern int strbuf_read_fd(struct strbuf *sb, int fd);\n+extern size_t stripspace(struct strbuf *sb, int skip_comments);\n \n #endif /* STRBUF_H */\n-- \n1.5.2.GIT\n"},{"id":"52658","messageId":"11890382262161-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"1189038225525-git-send-email-krh@redhat.com","subject":"[PATCH 7/9] Add strbuf_read_path().","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:36Z","receivedAt":"2007-09-06T00:23:36Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Signed-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n builtin-tag.c |    7 +------\n strbuf.c      |   15 +++++++++++++++\n strbuf.h      |    1 +\n 3 files changed, 17 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex 1aff952..8724d49 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -53,14 +53,9 @@ static void launch_editor(const char *path, struct strbuf *sb)\n \tif (run_command(&child))\n \t\tdie(\"There was a problem with the editor %s.\", editor);\n \n-\tfd = open(path, O_RDONLY);\n-\tif (fd < 0)\n-\t\tdie(\"could not open '%s': %s\", path, strerror(errno));\n-\tif (strbuf_read_fd(sb, fd) < 0) {\n+\tif (strbuf_read_path(sb, path) < 0)\n \t\tdie(\"could not read message file '%s': %s\",\n \t\t    path, strerror(errno));\n-\t}\n-\tclose(fd);\n }\n \n struct tag_filter {\ndiff --git a/strbuf.c b/strbuf.c\nindex ed2afea..1951a5b 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -70,6 +70,21 @@ int strbuf_read_fd(struct strbuf *sb, int fd)\n \treturn total;\n }\n \n+int strbuf_read_path(struct strbuf *sb, const char *path)\n+{\n+\tint fd, len;\n+\n+\tfd = open(path, O_RDONLY);\n+\tif (fd < 0)\n+\t\treturn -1;\n+\tlen = strbuf_read_fd(sb, fd);\n+\tif (len < 0)\n+\t\treturn -1;\n+\tclose(fd);\n+\n+\treturn len;\n+}\n+\n void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n {\n \tchar buffer[2048];\ndiff --git a/strbuf.h b/strbuf.h\nindex a93b9e1..e852070 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -14,6 +14,7 @@ extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);\n extern void strbuf_add_char(struct strbuf *sb, int ch);\n extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);\n extern int strbuf_read_fd(struct strbuf *sb, int fd);\n+extern int strbuf_read_path(struct strbuf *sb, const char *path);\n extern size_t stripspace(struct strbuf *sb, int skip_comments);\n \n #endif /* STRBUF_H */\n-- \n1.5.2.GIT\n"},{"id":"52660","messageId":"11890382264046-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382262161-git-send-email-krh@redhat.com","subject":"[PATCH 8/9] Export rerere() and launch_editor().","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:37Z","receivedAt":"2007-09-06T00:23:37Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Signed-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n builtin-rerere.c |   16 ++++++++++++++++\n builtin-tag.c    |    3 +--\n commit.h         |    1 +\n strbuf.h         |    1 +\n 4 files changed, 19 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex 29d057c..eb22a28 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -415,6 +415,22 @@ static int is_rerere_enabled(void)\n \treturn 1;\n }\n \n+/* Export for builtin-commit. */\n+int rerere(void)\n+{\n+\tstruct path_list merge_rr = { NULL, 0, 0, 1 };\n+\tint fd;\n+\n+\tgit_config(git_rerere_config);\n+\tif (!is_rerere_enabled())\n+\t\treturn 0;\n+\n+\tmerge_rr_path = xstrdup(git_path(\"rr-cache/MERGE_RR\"));\n+\tfd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);\n+\tread_rr(&merge_rr);\n+\treturn do_plain_rerere(&merge_rr, fd);\n+}\n+\n int cmd_rerere(int argc, const char **argv, const char *prefix)\n {\n \tstruct path_list merge_rr = { NULL, 0, 0, 1 };\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex 8724d49..3b181f5 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -18,12 +18,11 @@ static const char builtin_tag_usage[] =\n \n static char signingkey[1000];\n \n-static void launch_editor(const char *path, struct strbuf *sb)\n+void launch_editor(const char *path, struct strbuf *sb)\n {\n \tconst char *editor, *terminal;\n \tstruct child_process child;\n \tconst char *args[3];\n-\tint fd;\n \n \teditor = getenv(\"GIT_EDITOR\");\n \tif (!editor && editor_program)\ndiff --git a/commit.h b/commit.h\nindex 64e1d4b..39934cc 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -130,5 +130,6 @@ create_commit(const unsigned char *tree_sha1,\n \t      const char *message, int length);\n \n extern int interactive_add(void);\n+extern int rerere(void);\n \n #endif /* COMMIT_H */\ndiff --git a/strbuf.h b/strbuf.h\nindex e852070..b009b4b 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -16,5 +16,6 @@ extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);\n extern int strbuf_read_fd(struct strbuf *sb, int fd);\n extern int strbuf_read_path(struct strbuf *sb, const char *path);\n extern size_t stripspace(struct strbuf *sb, int skip_comments);\n+extern void launch_editor(const char *path, struct strbuf *sb);\n \n #endif /* STRBUF_H */\n-- \n1.5.2.GIT\n"},{"id":"52661","messageId":"11890382271931-git-send-email-krh@redhat.com","threadId":"9792","inReplyTo":"11890382264046-git-send-email-krh@redhat.com","subject":"[PATCH 9/9] Implement git commit as a builtin command.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-06T00:23:38Z","receivedAt":"2007-09-06T00:23:38Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"Move git-commit.sh to contrib/examples.\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n Makefile                       |    9 +-\n builtin-commit.c               |  742 ++++++++++++++++++++++++++++++++++++++++\n builtin.h                      |    3 +-\n contrib/examples/git-commit.sh |  665 +++++++++++++++++++++++++++++++++++\n git-commit.sh                  |  665 -----------------------------------\n git.c                          |    3 +-\n 6 files changed, 1414 insertions(+), 673 deletions(-)\n create mode 100644 builtin-commit.c\n create mode 100755 contrib/examples/git-commit.sh\n delete mode 100755 git-commit.sh\n\ndiff --git a/Makefile b/Makefile\nindex 4eb4637..beb3cbb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -201,7 +201,7 @@ BASIC_LDFLAGS =\n \n SCRIPT_SH = \\\n \tgit-bisect.sh git-checkout.sh \\\n-\tgit-clean.sh git-clone.sh git-commit.sh \\\n+\tgit-clean.sh git-clone.sh \\\n \tgit-fetch.sh \\\n \tgit-ls-remote.sh \\\n \tgit-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \\\n@@ -250,7 +250,7 @@ EXTRA_PROGRAMS =\n BUILT_INS = \\\n \tgit-format-patch$X git-show$X git-whatchanged$X git-cherry$X \\\n \tgit-get-tar-commit-id$X git-init$X git-repo-config$X \\\n-\tgit-fsck-objects$X git-cherry-pick$X \\\n+\tgit-fsck-objects$X git-cherry-pick$X git-status$X\\\n \t$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))\n \n # what 'all' will build and 'install' will install, in gitexecdir\n@@ -322,6 +322,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-check-attr.o \\\n \tbuiltin-checkout-index.o \\\n \tbuiltin-check-ref-format.o \\\n+\tbuiltin-commit.o \\\n \tbuiltin-commit-tree.o \\\n \tbuiltin-count-objects.o \\\n \tbuiltin-describe.o \\\n@@ -357,7 +358,6 @@ BUILTIN_OBJS = \\\n \tbuiltin-rev-parse.o \\\n \tbuiltin-revert.o \\\n \tbuiltin-rm.o \\\n-\tbuiltin-runstatus.o \\\n \tbuiltin-shortlog.o \\\n \tbuiltin-show-branch.o \\\n \tbuiltin-stripspace.o \\\n@@ -797,9 +797,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl\n \tchmod +x $@+ && \\\n \tmv $@+ $@\n \n-git-status: git-commit\n-\t$(QUIET_GEN)cp $< $@+ && mv $@+ $@\n-\n gitweb/gitweb.cgi: gitweb/gitweb.perl\n \t$(QUIET_GEN)$(RM) $@ $@+ && \\\n \tsed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \\\ndiff --git a/builtin-commit.c b/builtin-commit.c\nnew file mode 100644\nindex 0000000..aca5ff8\n--- /dev/null\n+++ b/builtin-commit.c\n@@ -0,0 +1,742 @@\n+/*\n+ * Builtin \"git commit\"\n+ *\n+ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>\n+ * Based on git-commit.sh by Junio C Hamano and Linus Torvalds\n+ */\n+\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <unistd.h>\n+\n+#include \"cache.h\"\n+#include \"cache-tree.h\"\n+#include \"builtin.h\"\n+#include \"diff.h\"\n+#include \"diffcore.h\"\n+#include \"commit.h\"\n+#include \"revision.h\"\n+#include \"wt-status.h\"\n+#include \"run-command.h\"\n+#include \"refs.h\"\n+#include \"log-tree.h\"\n+#include \"strbuf.h\"\n+#include \"utf8.h\"\n+\n+void launch_editor(const char *path, struct strbuf *sb);\n+int rerere(void);\n+\n+static const char builtin_commit_usage[] =\n+\t\"[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]\";\n+\n+static unsigned char head_sha1[20], merge_head_sha1[20];\n+static char *use_message_buffer;\n+static const char commit_editmsg[] = \"COMMIT_EDITMSG\";\n+static struct lock_file lock_file;\n+\n+enum option_type {\n+    OPTION_NONE,\n+    OPTION_STRING,\n+    OPTION_INTEGER,\n+    OPTION_LAST,\n+};\n+\n+struct option {\n+    enum option_type type;\n+    const char *long_name;\n+    char short_name;\n+    void *value;\n+};\n+\n+static int scan_options(const char ***argv, struct option *options)\n+{\n+\tconst char *value, *eq;\n+\tint i;\n+\n+\tif (**argv == NULL)\n+\t\treturn 0;\n+\tif ((**argv)[0] != '-')\n+\t\treturn 0;\n+\tif (!strcmp(**argv, \"--\"))\n+\t\treturn 0;\n+\n+\tvalue = NULL;\n+\tfor (i = 0; options[i].type != OPTION_LAST; i++) {\n+\t\tif ((**argv)[1] == '-') {\n+\t\t\tif (!prefixcmp(options[i].long_name, **argv + 2)) {\n+\t\t\t\tif (options[i].type != OPTION_NONE)\n+\t\t\t\t\tvalue = *++(*argv);\n+\t\t\t\tgoto match;\n+\t\t\t}\n+\n+\t\t\teq = strchr(**argv + 2, '=');\n+\t\t\tif (eq && options[i].type != OPTION_NONE &&\n+\t\t\t    !strncmp(**argv + 2, \n+\t\t\t\t     options[i].long_name, eq - **argv - 2)) {\n+\t\t\t\tvalue = eq + 1;\n+\t\t\t\tgoto match;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif ((**argv)[1] == options[i].short_name) {\n+\t\t\tif ((**argv)[2] == '\\0') {\n+\t\t\t\tif (options[i].type != OPTION_NONE)\n+\t\t\t\t\tvalue = *++(*argv);\n+\t\t\t\tgoto match;\n+\t\t\t}\n+\n+\t\t\tif (options[i].type != OPTION_NONE) {\n+\t\t\t\tvalue = **argv + 2;\n+\t\t\t\tgoto match;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tusage(builtin_commit_usage);\n+\n+ match:\n+\tswitch (options[i].type) {\n+\tcase OPTION_NONE:\n+\t\t*(int *)options[i].value = 1;\n+\t\tbreak;\n+\tcase OPTION_STRING:\n+\t\tif (value == NULL)\n+\t\t\tdie(\"option %s requires a value.\", (*argv)[-1]);\n+\t\t*(const char **)options[i].value = value;\n+\t\tbreak;\n+\tcase OPTION_INTEGER:\n+\t\tif (value == NULL)\n+\t\t\tdie(\"option %s requires a value.\", (*argv)[-1]);\n+\t\t*(int *)options[i].value = atoi(value);\n+\t\tbreak;\n+\tdefault:\n+\t\tassert(0);\n+\t}\n+\n+\t(*argv)++;\n+\n+\treturn 1;\n+}\n+\n+static char *logfile, *force_author, *message, *template_file;\n+static char *edit_message, *use_message;\n+static int all, edit_flag, also, interactive, only, no_verify, amend, signoff;\n+static int quiet, verbose, untracked_files;\n+\n+static int no_edit, initial_commit, in_merge;\n+const char *only_include_assumed;\n+\n+static struct option commit_options[] = {\n+\t{ OPTION_STRING, \"file\", 'F', (void *) &logfile },\n+\t{ OPTION_NONE, \"all\", 'a', &all },\n+\t{ OPTION_STRING, \"author\", 0, (void *) &force_author },\n+\t{ OPTION_NONE, \"edit\", 'e', &edit_flag },\n+\t{ OPTION_NONE, \"include\", 'i', &also },\n+\t{ OPTION_NONE, \"interactive\", 0, &interactive },\n+\t{ OPTION_NONE, \"only\", 'o', &only },\n+\t{ OPTION_STRING, \"message\", 'm', &message },\n+\t{ OPTION_NONE, \"no-verify\", 'n', &no_verify },\n+\t{ OPTION_NONE, \"amend\", 0, &amend },\n+\t{ OPTION_STRING, \"reedit-message\", 'c', &edit_message },\n+\t{ OPTION_STRING, \"reuse-message\", 'C', &use_message },\n+\t{ OPTION_NONE, \"signoff\", 's', &signoff },\n+\t{ OPTION_NONE, \"quiet\", 'q', &quiet },\n+\t{ OPTION_NONE, \"verbose\", 'v', &verbose },\n+\t{ OPTION_NONE, \"untracked-files\", 0, &untracked_files },\n+\t{ OPTION_STRING, \"template\", 't', &template_file },\n+\t{ OPTION_LAST },\n+};\n+\n+/* FIXME: Taken from builtin-add, should be shared. */\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\tcase DIFF_STATUS_TYPE_CHANGED:\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\tcache_tree_invalidate_path(active_cache_tree, 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\n+add_files_to_cache(int fd, const char **files, const char *prefix)\n+{\n+\tstruct rev_info rev;\n+\n+\tinit_revisions(&rev, \"\");\n+\tsetup_revisions(0, NULL, &rev, NULL);\n+\trev.prune_data = get_pathspec(prefix, files);\n+\trev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;\n+\trev.diffopt.format_callback = update_callback;\n+\trev.diffopt.format_callback_data = &verbose;\n+\n+\trun_diff_files(&rev, 0);\n+\trefresh_cache(REFRESH_QUIET);\n+\n+\tif (write_cache(fd, active_cache, active_nr) || close(fd))\n+\t\tdie(\"unable to write new index file\");\n+}\n+\n+static char *\n+prepare_index(const char **files, const char *prefix)\n+{\n+\tint fd;\n+\tstruct tree *tree;\n+\tstruct lock_file *next_index_lock;\n+\n+\tfd = hold_locked_index(&lock_file, 1);\n+\tif (read_cache() < 0)\n+\t\tdie(\"index file corrupt\");\n+\n+\tif (all) {\n+\t\tadd_files_to_cache(fd, files, NULL);\n+\t\treturn lock_file.filename;\n+\t} else if (also) {\n+\t\tadd_files_to_cache(fd, files, prefix);\n+\t\treturn lock_file.filename;\n+\t}\n+\n+\tif (interactive)\n+\t\tinteractive_add();\n+\n+\tif (*files == NULL) {\n+\t\t/* Commit index as-is. */\n+\t\trollback_lock_file(&lock_file);\n+\t\treturn get_index_file();\n+\t}\n+\n+\t/*\n+\t * FIXME: Warn on unknown files.  Shell script does\n+\t *\n+\t *   commit_only=`git-ls-files --error-unmatch -- \"$@\"`\n+\t */\n+\n+\t/*\n+\t * FIXME: shell script does\n+\t *\n+\t *   git-read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n+\t *\n+\t * which warns about unmerged files in the index.\n+\t */\n+\n+\t/* update the user index file */\n+\tadd_files_to_cache(fd, files, prefix);\n+\n+\tif (!initial_commit) {\n+\t\ttree = parse_tree_indirect(head_sha1);\n+\t\tif (!tree)\n+\t\t\tdie(\"failed to unpack HEAD tree object\");\n+\t\tif (read_tree(tree, 0, NULL))\n+\t\t\tdie(\"failed to read HEAD tree object\");\n+\t}\n+\n+\t/* Uh oh, abusing lock_file to create a garbage collected file */\n+\tnext_index_lock = xmalloc(sizeof(*next_index_lock));\n+\tfd = hold_lock_file_for_update(next_index_lock,\n+\t\t\t\t       git_path(\"next-index-%d\", getpid()), 1);\n+\tadd_files_to_cache(fd, files, prefix);\n+\n+\treturn next_index_lock->filename;\n+}\n+\n+static int run_status(FILE *fp, const char *index_file)\n+{\n+\tstruct wt_status s;\n+\n+\twt_status_prepare(&s);\n+\n+\tif (amend) {\n+\t\ts.amend = 1;\n+\t\ts.reference = \"HEAD^1\";\n+\t}\n+\ts.verbose = verbose;\n+\ts.untracked = untracked_files;\n+\ts.index_file = index_file;\n+\ts.fp = fp;\n+\n+\twt_status_print(&s);\n+\n+\treturn s.commitable;\n+}\n+\n+static const char sign_off_header[] = \"Signed-off-by: \";\n+\n+static int prepare_log_message(const char *index_file)\n+{\n+\tstruct stat statbuf;\n+\tint commitable;\n+\tstruct strbuf sb;\n+\tchar *buffer;\n+\tFILE *fp;\n+\n+\tstrbuf_init(&sb);\n+\tif (message) {\n+\t\tstrbuf_add(&sb, message, strlen(message));\n+\t} else if (logfile && !strcmp(logfile, \"-\")) {\n+\t\tif (isatty(0))\n+\t\t\tfprintf(stderr, \"(reading log message from standard input)\\n\");\n+\t\tif (strbuf_read_fd(&sb, 0) < 0)\n+\t\t\tdie(\"could not read log from standard input\");\n+\t} else if (logfile) {\n+\t\tif (strbuf_read_path(&sb, logfile) < 0)\n+\t\t\tdie(\"could not read log file '%s': %s\",\n+\t\t\t    logfile, strerror(errno));\n+\t} else if (use_message) {\n+\t\tbuffer = strstr(use_message_buffer, \"\\n\\n\");\n+\t\tif (!buffer || buffer[2] == '\\0')\n+\t\t\tdie(\"commit has empty message\");\n+\t\tstrbuf_add(&sb, buffer + 2, strlen(buffer + 2));\n+\t} else if (!stat(git_path(\"MERGE_MSG\"), &statbuf)) {\n+\t\tif (strbuf_read_path(&sb, git_path(\"MERGE_MSG\")) < 0)\n+\t\t\tdie(\"could not read MERGE_MSG: %s\", strerror(errno));\n+\t} else if (!stat(git_path(\"SQUASH_MSG\"), &statbuf)) {\n+\t\tif (strbuf_read_path(&sb, git_path(\"SQUASH_MSG\")) < 0)\n+\t\t\tdie(\"could not read SQUASH_MSG: %s\", strerror(errno));\n+\t} else if (!stat(template_file, &statbuf)) {\n+\t\tif (strbuf_read_path(&sb, template_file) < 0)\n+\t\t\tdie(\"could not read %s: %s\",\n+\t\t\t    template_file, strerror(errno));\n+\t}\n+\n+\tfp = fopen(git_path(commit_editmsg), \"w\");\n+\tif (fp == NULL)\n+\t\tdie(\"could not open %s\\n\", git_path(commit_editmsg));\n+\t\t\n+\tstripspace(&sb, 0);\n+\tif (fwrite(sb.buf, 1, sb.len, fp) < sb.len)\n+\t\tdie(\"could not write commit template: %s\\n\",\n+\t\t    strerror(errno));\n+\n+\tif (signoff) {\n+\t\tconst char *info, *bol;\n+\n+\t\tinfo = git_committer_info(1);\n+\t\tstrbuf_add_char(&sb, '\\0');\n+\t\tbol = strrchr(sb.buf + sb.len - 1, '\\n');\n+\t\tif (!bol || prefixcmp(bol, sign_off_header))\n+\t\t\tfprintf(fp, \"\\n\");\n+\t\tfprintf(fp, \"Signed-off-by: %s\\n\", git_committer_info(1));\n+\t}\n+\n+\tstrbuf_release(&sb);\n+\n+\tif (in_merge && !no_edit) {\n+\t\tfprintf(fp,\n+\t\t\t\"#\\n\"\n+\t\t\t\"# It looks like you may be committing a MERGE.\\n\"\n+\t\t\t\"# If this is not correct, please remove the file\\n\"\n+\t\t\t\"#\t%s\\n\"\n+\t\t\t\"# and try again.\\n\"\n+\t\t\t\"#\\n\",\n+\t\t\tgit_path(\"MERGE_HEAD\"));\n+\t}\n+\n+\tfprintf(fp,\n+\t\t\"\\n\"\n+\t\t\"# Please enter the commit message for your changes.\\n\"\n+\t\t\"# (Comment lines starting with '#' will not be included)\\n\");\n+\tif (only_include_assumed)\n+\t\tfprintf(fp, \"# %s\\n\", only_include_assumed);\n+\n+\tcommitable = run_status(fp, index_file);\n+\n+\tfclose(fp);\n+\n+\treturn commitable;\n+}\n+\n+/* Find out if the message starting at position 'start' in the strbuf\n+ * contains only whitespace and Signed-off-by lines. */\n+static int message_is_empty(struct strbuf *sb, int start)\n+{\n+\tstatic const char signed_off_by[] = \"Signed-off-by: \";\n+\tstruct strbuf tmpl;\n+\tconst char *nl;\n+\tint eol, i;\n+\n+\t/* See if the template is just a prefix of the message. */\n+\tstrbuf_init(&tmpl);\n+\tif (template_file && strbuf_read_path(&tmpl, template_file) > 0) {\n+\t\tstripspace(&tmpl, 1);\n+\t\tif (start + tmpl.len <= sb->len &&\n+\t\t    memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)\n+\t\t\tstart += tmpl.len;\n+\t}\n+\tstrbuf_release(&tmpl);\n+\n+\t/* Check if the rest is just whitespace and Signed-of-by's. */\n+\tfor (i = start; i < sb->len; i++) {\n+\t\tnl = memchr(sb->buf + i, '\\n', sb->len - i);\n+\t\tif (nl)\n+\t\t\teol = nl - sb->buf;\n+\t\telse\n+\t\t\teol = sb->len;\n+\n+\t\tif (strlen(signed_off_by) <= eol - i &&\n+\t\t    !prefixcmp(sb->buf + i, signed_off_by)) {\n+\t\t\ti = eol;\n+\t\t\tcontinue;\n+\t\t}\n+\t\twhile (i < eol)\n+\t\t\tif (!isspace(sb->buf[i++]))\n+\t\t\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+static void determine_author_info(struct strbuf *sb)\n+{\n+\tchar *p, *eol;\n+\tchar *name = NULL, *email = NULL;\n+\n+\tif (use_message) {\n+\t\tp = strstr(use_message_buffer, \"\\nauthor\");\n+\t\tif (!p)\n+\t\t\tdie(\"invalid commit: %s\\n\", use_message);\n+\t\tp++;\n+\t\teol = strchr(p, '\\n');\n+\t\tif (!eol)\n+\t\t\tdie(\"invalid commit: %s\\n\", use_message);\n+\n+\t\tstrbuf_add(sb, p, eol + 1 - p);\n+\t} else if (force_author) {\n+\t\tconst char *eoname = strstr(force_author, \" <\");\n+\t\tconst char *eomail = strchr(force_author, '>');\n+\n+\t\tif (!eoname || !eomail)\n+\t\t\tdie(\"malformed --author parameter\\n\");\n+\t\tname = xstrndup(force_author, eoname - force_author);\n+\t\temail = xstrndup(eoname + 2, eomail - eoname - 2);\n+\t\tstrbuf_printf(sb, \"author %s\\n\",\n+\t\t\t      fmt_ident(name, email, \n+\t\t\t\t\tgetenv(\"GIT_AUTHOR_DATE\"), 1));\n+\t\tfree(name);\n+\t\tfree(email);\n+\t} else {\n+\t\tstrbuf_printf(sb, \"author %s\\n\", git_author_info(1));\n+\t}\n+}\n+\n+static void parse_and_validate_options(const char ***argv)\n+{\n+\tint f = 0;\n+\n+\t(*argv)++;\n+\twhile (scan_options(argv, commit_options))\n+\t\t;\n+\n+\tif (logfile || message || use_message)\n+\t\tno_edit = 1;\n+\tif (edit_flag)\n+\t\tno_edit = 0;\n+\n+\tif (get_sha1(\"HEAD\", head_sha1))\n+\t\tinitial_commit = 1;\n+\n+\tif (!get_sha1(\"MERGE_HEAD\", merge_head_sha1))\n+\t\tin_merge = 1;\n+\n+\t/* Sanity check options */\n+\tif (amend && initial_commit)\n+\t\tdie(\"You have nothing to amend.\");\n+\tif (amend && in_merge)\n+\t\tdie(\"You are in the middle of a merger -- cannot amend.\");\n+\n+\tif (use_message)\n+\t\tf++;\n+\tif (edit_message)\n+\t\tf++;\n+\tif (logfile)\n+\t\tf++;\n+\tif (f > 1)\n+\t\tdie(\"Only one of -c/-C/-F can be used.\");\n+\tif (message && f > 0)\n+\t\tdie(\"Option -m cannot be combined with -c/-C/-F.\");\n+\tif (edit_message)\n+\t\tuse_message = edit_message;\n+\tif (amend)\n+\t\tuse_message = \"HEAD\";\n+\tif (use_message) {\n+\t\tunsigned char sha1[20];\n+\t\tstatic char utf8[] = \"UTF-8\";\n+\t\tchar *enc, *end, *out_enc;\n+\t\tstruct commit *commit;\n+\n+\t\tif (get_sha1(use_message, sha1))\n+\t\t\tdie(\"could not lookup commit %s\", use_message);\n+\t\tcommit = lookup_commit(sha1);\n+\t\tif (!commit || parse_commit(commit))\n+\t\t\tdie(\"could not parse commit %s\", use_message);\n+\n+\t\tenc = strstr(commit->buffer, \"\\nencoding\");\n+\t\tif (enc) {\n+\t\t\tend = strchr(enc + 10, '\\n');\n+\t\t\tenc = xstrndup(enc + 10, end - (enc + 10));\n+\t\t} else {\n+\t\t\tenc = utf8;\n+\t\t}\n+\t\tout_enc = git_commit_encoding ? git_commit_encoding : utf8;\n+\n+\t\tuse_message_buffer =\n+\t\t\treencode_string(commit->buffer, out_enc, enc);\n+\t\tif (enc != utf8)\n+\t\t\tfree(enc);\n+\t}\n+\n+\tif (also && only)\n+\t\tdie(\"Only one of --include/--only can be used.\");\n+\tif (!*argv && (also || (only && !amend)))\n+\t\tdie(\"No paths with --include/--only does not make sense.\");\n+\tif (!*argv && only && amend)\n+\t\tonly_include_assumed = \"Clever... amending the last one with dirty index.\";\n+\tif (*argv && !also && !only) {\n+\t\tonly_include_assumed = \"Explicit paths specified without -i nor -o; assuming --only paths...\";\n+\t\talso = 0;\n+\t}\n+\n+\tif (all && interactive)\n+\t\tdie(\"Cannot use -a, --interactive or -i at the same time.\");\n+\telse if (all && **argv)\n+\t\tdie(\"Paths with -a does not make sense.\");\n+\telse if (interactive && **argv)\n+\t\tdie(\"Paths with --interactive does not make sense.\");\n+}\n+\n+int cmd_status(int argc, const char **argv, const char *prefix)\n+{\n+\tconst char *index_file;\n+\tint commitable;\n+\n+\tgit_config(git_status_config);\n+\n+\tparse_and_validate_options(&argv);\n+\n+\tindex_file = prepare_index(argv, prefix);\n+\n+\tcommitable = run_status(stdout, index_file);\n+\n+\trollback_lock_file(&lock_file);\n+\n+\treturn commitable ? 0 : 1;\n+}\n+\n+static int run_hook(const char *index_file, const char *name, const char *arg)\n+{\n+\tstruct child_process hook;\n+\tconst char *argv[3], *env[2];\n+\tchar index[PATH_MAX];\n+\n+\targv[0] = git_path(\"hooks/%s\", name);\n+\targv[1] = arg;\n+\targv[2] = NULL;\n+\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n+\tenv[0] = index;\n+\tenv[1] = NULL;\n+\n+\tif (access(argv[0], X_OK) < 0)\n+\t\treturn 0;\n+\n+\tmemset(&hook, 0, sizeof(hook));\n+\thook.argv = argv;\n+\thook.no_stdin = 1;\n+\thook.stdout_to_stderr = 1;\n+\thook.env = env;\n+\n+\treturn run_command(&hook);\n+}\n+\n+static void print_summary(const char *prefix, const unsigned char *sha1)\n+{\n+\tstruct rev_info rev;\n+\tstruct commit *commit;\n+\n+\tcommit = lookup_commit(sha1);\n+\tif (!commit)\n+\t\tdie(\"couldn't look up newly created commit\\n\");\n+\tif (!commit || parse_commit(commit))\n+\t\tdie(\"could not parse newly created commit\");\n+\n+\tinit_revisions(&rev, prefix);\n+\tsetup_revisions(0, NULL, &rev, NULL);\n+\n+\trev.abbrev = 0;\n+\trev.diff = 1;\n+\trev.diffopt.output_format =\n+\t\tDIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;\n+\n+\trev.verbose_header = 1;\n+\trev.show_root_diff = 1;\n+\trev.commit_format = get_commit_format(\"format:%h: %s\");\n+\trev.always_show_header = 1;\n+\t\t\n+\tprintf(\"Created %scommit \", initial_commit ? \"initial \" : \"\");\n+\n+\tlog_tree_commit(&rev, commit);\n+}\n+\n+int git_commit_config(const char *k, const char *v)\n+{\n+\tif (!strcmp(k, \"commit.template\")) {\n+\t\ttemplate_file = xstrdup(v);\n+\t\treturn 0;\n+\t}\n+\n+\treturn git_status_config(k, v);\n+}\n+\n+static const char commit_utf8_warn[] =\n+\"Warning: commit message does not conform to UTF-8.\\n\"\n+\"You may want to amend it after fixing the message, or set the config\\n\"\n+\"variable i18n.commitencoding to the encoding your project uses.\\n\";\n+\n+int cmd_commit(int argc, const char **argv, const char *prefix)\n+{\n+\tint header_len, parent_count = 0;\n+\tstruct strbuf sb;\n+\tconst char *index_file, *reflog_msg;\n+\tchar *nl, *header_line;\n+\tunsigned char commit_sha1[20];\n+\tstruct ref_lock *ref_lock;\n+\n+\tgit_config(git_commit_config);\n+\n+\tparse_and_validate_options(&argv);\n+\n+\tindex_file = prepare_index(argv, prefix);\n+\n+\tif (run_hook(index_file, \"pre-commit\", NULL))\n+\t\texit(1);\n+\n+\tif (!prepare_log_message(index_file)) {\n+\t\trun_status(stdout, index_file);\n+\t\tunlink(commit_editmsg);\n+\t\treturn 1;\n+\t}\n+\n+\tstrbuf_init(&sb);\n+\n+\t/* Start building up the commit header */\n+\tread_cache_from(index_file);\n+\tactive_cache_tree = cache_tree();\n+\tif (cache_tree_update(active_cache_tree,\n+\t\t\t      active_cache, active_nr, 0, 0) < 0)\n+\t\tdie(\"Error building trees\");\n+\tstrbuf_printf(&sb, \"tree %s\\n\",\n+\t\t      sha1_to_hex(active_cache_tree->sha1));\n+\n+\t/* Determine parents */\n+\tif (initial_commit) {\n+\t\treflog_msg = \"commit (initial)\"; \n+\t\tparent_count = 0;\n+\t} else if (amend) {\n+\t\tstruct commit_list *c;\n+\t\tstruct commit *commit;\n+\n+\t\treflog_msg = \"commit (amend)\";\n+\t\tcommit = lookup_commit(head_sha1);\n+\t\tif (!commit || parse_commit(commit))\n+\t\t\tdie(\"could not parse HEAD commit\");\n+\n+\t\tfor (c = commit->parents; c; c = c->next)\n+\t\t\tstrbuf_printf(&sb, \"parent %s\\n\",\n+\t\t\t\t      sha1_to_hex(c->item->object.sha1));\n+\t} else if (in_merge) {\n+\t\tstruct strbuf m;\n+\t\tFILE *fp;\n+\n+\t\treflog_msg = \"commit (merge)\";\n+\t\tstrbuf_printf(&sb, \"parent %s\\n\", sha1_to_hex(head_sha1));\n+\t\tstrbuf_init(&m);\n+\t\tfp = fopen(git_path(\"MERGE_HEAD\"), \"r\");\n+\t\tif (fp == NULL)\n+\t\t\tdie(\"could not open %s for reading: %s\",\n+\t\t\t    git_path(\"MERGE_HEAD\"), strerror(errno));\n+\t\twhile (!m.eof) {\n+\t\t\tread_line(&m, fp, '\\n');\n+\t\t\tif (!m.eof)\n+\t\t\t\tstrbuf_printf(&sb, \"parent %s\\n\", m.buf);\n+\t\t}\n+\t\tfclose(fp);\n+\t\tstrbuf_release(&m);\n+\t} else {\n+\t\treflog_msg = \"commit\";\n+\t\tstrbuf_printf(&sb, \"parent %s\\n\", sha1_to_hex(head_sha1));\n+\t}\n+\n+\tdetermine_author_info(&sb);\n+\tstrbuf_printf(&sb, \"committer %s\\n\", git_committer_info(1));\n+\tif (!is_encoding_utf8(git_commit_encoding))\n+\t\tstrbuf_printf(&sb, \"encoding %s\\n\", git_commit_encoding);\n+\tstrbuf_add_char(&sb, '\\n');\n+\n+\t/* Get the commit message and validate it */\n+\theader_len = sb.len;\n+\tif (!no_edit) {\n+\t\tfprintf(stderr, \"launching editor, log %s\\n\", logfile);\n+\t\tlaunch_editor(git_path(commit_editmsg), &sb);\n+\t}\n+\telse if (strbuf_read_path(&sb, git_path(commit_editmsg)) < 0)\n+\t\tdie(\"could not read commit message\\n\");\n+\tif (run_hook(index_file, \"commit-msg\", commit_editmsg))\n+\t\texit(1);\n+\tif (stripspace(&sb, 1) < header_len ||\n+\t    message_is_empty(&sb, header_len))\n+\t\tdie(\"* no commit message?  aborting commit.\");\n+\tstrbuf_add_char(&sb, '\\0');\n+\tif (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))\n+\t\tfprintf(stderr, commit_utf8_warn);\n+\n+\tif (write_sha1_file(sb.buf, sb.len - 1, commit_type, commit_sha1))\n+\t\tdie(\"failed to write commit object\");\n+\t\t       \n+\tref_lock = lock_any_ref_for_update(\"HEAD\",\n+\t\t\t\t\t   initial_commit ? NULL : head_sha1,\n+\t\t\t\t\t   0);\n+\n+\tnl = strchr(sb.buf + header_len, '\\n');\n+\theader_line = xstrndup(sb.buf + header_len,\n+\t\t\t       nl - (sb.buf + header_len));\n+\tstrbuf_release(&sb);\n+\tstrbuf_printf(&sb, \"%s: %s\\n\", reflog_msg, header_line);\n+\tstrbuf_add_char(&sb, '\\0');\n+\tfree(header_line);\n+\n+\tif (!ref_lock)\n+\t\tdie(\"cannot lock HEAD ref\");\n+\tif (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0)\n+\t\tdie(\"cannot update HEAD ref\");\n+\n+\tunlink(git_path(\"MERGE_HEAD\"));\n+\tunlink(git_path(\"MERGE_MSG\"));\n+\n+\tif (lock_file.filename[0] && commit_locked_index(&lock_file))\n+\t\tdie(\"failed to write new index\");\n+\n+\trerere();\n+\n+\trun_hook(index_file, \"post-commit\", NULL);\n+\n+\tif (!quiet)\n+\t\tprint_summary(prefix, commit_sha1);\n+\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 91bc595..c23cd6d 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -23,6 +23,7 @@ extern int cmd_check_attr(int argc, const char **argv, const char *prefix);\n extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);\n+extern int cmd_commit(int argc, const char **argv, const char *prefix);\n extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_count_objects(int argc, const char **argv, const char *prefix);\n extern int cmd_describe(int argc, const char **argv, const char *prefix);\n@@ -63,10 +64,10 @@ extern int cmd_rev_list(int argc, const char **argv, const char *prefix);\n extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);\n extern int cmd_revert(int argc, const char **argv, const char *prefix);\n extern int cmd_rm(int argc, const char **argv, const char *prefix);\n-extern int cmd_runstatus(int argc, const char **argv, const char *prefix);\n extern int cmd_shortlog(int argc, const char **argv, const char *prefix);\n extern int cmd_show(int argc, const char **argv, const char *prefix);\n extern int cmd_show_branch(int argc, const char **argv, const char *prefix);\n+extern int cmd_status(int argc, const char **argv, const char *prefix);\n extern int cmd_stripspace(int argc, const char **argv, const char *prefix);\n extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);\n extern int cmd_tag(int argc, const char **argv, const char *prefix);\ndiff --git a/contrib/examples/git-commit.sh b/contrib/examples/git-commit.sh\nnew file mode 100755\nindex 0000000..d7e7028\n--- /dev/null\n+++ b/contrib/examples/git-commit.sh\n@@ -0,0 +1,665 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Linus Torvalds\n+# Copyright (c) 2006 Junio C Hamano\n+\n+USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'\n+SUBDIRECTORY_OK=Yes\n+. git-sh-setup\n+require_work_tree\n+\n+git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t\n+\n+case \"$0\" in\n+*status)\n+\tstatus_only=t\n+\t;;\n+*commit)\n+\tstatus_only=\n+\t;;\n+esac\n+\n+refuse_partial () {\n+\techo >&2 \"$1\"\n+\techo >&2 \"You might have meant to say 'git commit -i paths...', perhaps?\"\n+\texit 1\n+}\n+\n+THIS_INDEX=\"$GIT_DIR/index\"\n+NEXT_INDEX=\"$GIT_DIR/next-index$$\"\n+rm -f \"$NEXT_INDEX\"\n+save_index () {\n+\tcp -p \"$THIS_INDEX\" \"$NEXT_INDEX\"\n+}\n+\n+run_status () {\n+\t# If TMP_INDEX is defined, that means we are doing\n+\t# \"--only\" partial commit, and that index file is used\n+\t# to build the tree for the commit.  Otherwise, if\n+\t# NEXT_INDEX exists, that is the index file used to\n+\t# make the commit.  Otherwise we are using as-is commit\n+\t# so the regular index file is what we use to compare.\n+\tif test '' != \"$TMP_INDEX\"\n+\tthen\n+\t\tGIT_INDEX_FILE=\"$TMP_INDEX\"\n+\t\texport GIT_INDEX_FILE\n+\telif test -f \"$NEXT_INDEX\"\n+\tthen\n+\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\"\n+\t\texport GIT_INDEX_FILE\n+\tfi\n+\n+\tcase \"$status_only\" in\n+\tt) color= ;;\n+\t*) color=--nocolor ;;\n+\tesac\n+\tgit runstatus ${color} \\\n+\t\t${verbose:+--verbose} \\\n+\t\t${amend:+--amend} \\\n+\t\t${untracked_files:+--untracked}\n+}\n+\n+trap '\n+\ttest -z \"$TMP_INDEX\" || {\n+\t\ttest -f \"$TMP_INDEX\" && rm -f \"$TMP_INDEX\"\n+\t}\n+\trm -f \"$NEXT_INDEX\"\n+' 0\n+\n+################################################################\n+# Command line argument parsing and sanity checking\n+\n+all=\n+also=\n+interactive=\n+only=\n+logfile=\n+use_commit=\n+amend=\n+edit_flag=\n+no_edit=\n+log_given=\n+log_message=\n+verify=t\n+quiet=\n+verbose=\n+signoff=\n+force_author=\n+only_include_assumed=\n+untracked_files=\n+templatefile=\"`git config commit.template`\"\n+while case \"$#\" in 0) break;; esac\n+do\n+\tcase \"$1\" in\n+\t-F|--F|-f|--f|--fi|--fil|--file)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tno_edit=t\n+\t\tlog_given=t$log_given\n+\t\tlogfile=\"$1\"\n+\t\tshift\n+\t\t;;\n+\t-F*|-f*)\n+\t\tno_edit=t\n+\t\tlog_given=t$log_given\n+\t\tlogfile=`expr \"z$1\" : 'z-[Ff]\\(.*\\)'`\n+\t\tshift\n+\t\t;;\n+\t--F=*|--f=*|--fi=*|--fil=*|--file=*)\n+\t\tno_edit=t\n+\t\tlog_given=t$log_given\n+\t\tlogfile=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n+\t\tshift\n+\t\t;;\n+\t-a|--a|--al|--all)\n+\t\tall=t\n+\t\tshift\n+\t\t;;\n+\t--au=*|--aut=*|--auth=*|--autho=*|--author=*)\n+\t\tforce_author=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n+\t\tshift\n+\t\t;;\n+\t--au|--aut|--auth|--autho|--author)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tforce_author=\"$1\"\n+\t\tshift\n+\t\t;;\n+\t-e|--e|--ed|--edi|--edit)\n+\t\tedit_flag=t\n+\t\tshift\n+\t\t;;\n+\t-i|--i|--in|--inc|--incl|--inclu|--includ|--include)\n+\t\talso=t\n+\t\tshift\n+\t\t;;\n+\t--int|--inte|--inter|--intera|--interac|--interact|--interacti|\\\n+\t--interactiv|--interactive)\n+\t\tinteractive=t\n+\t\tshift\n+\t\t;;\n+\t-o|--o|--on|--onl|--only)\n+\t\tonly=t\n+\t\tshift\n+\t\t;;\n+\t-m|--m|--me|--mes|--mess|--messa|--messag|--message)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tlog_given=m$log_given\n+\t\tif test \"$log_message\" = ''\n+\t\tthen\n+\t\t    log_message=\"$1\"\n+\t\telse\n+\t\t    log_message=\"$log_message\n+\n+$1\"\n+\t\tfi\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t-m*)\n+\t\tlog_given=m$log_given\n+\t\tif test \"$log_message\" = ''\n+\t\tthen\n+\t\t    log_message=`expr \"z$1\" : 'z-m\\(.*\\)'`\n+\t\telse\n+\t\t    log_message=\"$log_message\n+\n+`expr \"z$1\" : 'z-m\\(.*\\)'`\"\n+\t\tfi\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)\n+\t\tlog_given=m$log_given\n+\t\tif test \"$log_message\" = ''\n+\t\tthen\n+\t\t    log_message=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n+\t\telse\n+\t\t    log_message=\"$log_message\n+\n+`expr \"z$1\" : 'zq-[^=]*=\\(.*\\)'`\"\n+\t\tfi\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t-n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\\\n+\t--no-verify)\n+\t\tverify=\n+\t\tshift\n+\t\t;;\n+\t--a|--am|--ame|--amen|--amend)\n+\t\tamend=t\n+\t\tuse_commit=HEAD\n+\t\tshift\n+\t\t;;\n+\t-c)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=\"$1\"\n+\t\tno_edit=\n+\t\tshift\n+\t\t;;\n+\t--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\\\n+\t--reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\\\n+\t--reedit-messag=*|--reedit-message=*)\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n+\t\tno_edit=\n+\t\tshift\n+\t\t;;\n+\t--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\\\n+\t--reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\\\n+\t--reedit-message)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=\"$1\"\n+\t\tno_edit=\n+\t\tshift\n+\t\t;;\n+\t-C)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=\"$1\"\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\\\n+\t--reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\\\n+\t--reuse-message=*)\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\\\n+\t--reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\tlog_given=t$log_given\n+\t\tuse_commit=\"$1\"\n+\t\tno_edit=t\n+\t\tshift\n+\t\t;;\n+\t-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)\n+\t\tsignoff=t\n+\t\tshift\n+\t\t;;\n+\t-t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)\n+\t\tcase \"$#\" in 1) usage ;; esac\n+\t\tshift\n+\t\ttemplatefile=\"$1\"\n+\t\tno_edit=\n+\t\tshift\n+\t\t;;\n+\t-q|--q|--qu|--qui|--quie|--quiet)\n+\t\tquiet=t\n+\t\tshift\n+\t\t;;\n+\t-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)\n+\t\tverbose=t\n+\t\tshift\n+\t\t;;\n+\t-u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\\\n+\t--untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\\\n+\t--untracked-file|--untracked-files)\n+\t\tuntracked_files=t\n+\t\tshift\n+\t\t;;\n+\t--)\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n+\t-*)\n+\t\tusage\n+\t\t;;\n+\t*)\n+\t\tbreak\n+\t\t;;\n+\tesac\n+done\n+case \"$edit_flag\" in t) no_edit= ;; esac\n+\n+################################################################\n+# Sanity check options\n+\n+case \"$amend,$initial_commit\" in\n+t,t)\n+\tdie \"You do not have anything to amend.\" ;;\n+t,)\n+\tif [ -f \"$GIT_DIR/MERGE_HEAD\" ]; then\n+\t\tdie \"You are in the middle of a merge -- cannot amend.\"\n+\tfi ;;\n+esac\n+\n+case \"$log_given\" in\n+tt*)\n+\tdie \"Only one of -c/-C/-F can be used.\" ;;\n+*tm*|*mt*)\n+\tdie \"Option -m cannot be combined with -c/-C/-F.\" ;;\n+esac\n+\n+case \"$#,$also,$only,$amend\" in\n+*,t,t,*)\n+\tdie \"Only one of --include/--only can be used.\" ;;\n+0,t,,* | 0,,t,)\n+\tdie \"No paths with --include/--only does not make sense.\" ;;\n+0,,t,t)\n+\tonly_include_assumed=\"# Clever... amending the last one with dirty index.\" ;;\n+0,,,*)\n+\t;;\n+*,,,*)\n+\tonly_include_assumed=\"# Explicit paths specified without -i nor -o; assuming --only paths...\"\n+\talso=\n+\t;;\n+esac\n+unset only\n+case \"$all,$interactive,$also,$#\" in\n+*t,*t,*)\n+\tdie \"Cannot use -a, --interactive or -i at the same time.\" ;;\n+t,,[1-9]*)\n+\tdie \"Paths with -a does not make sense.\" ;;\n+,t,[1-9]*)\n+\tdie \"Paths with --interactive does not make sense.\" ;;\n+,,t,0)\n+\tdie \"No paths with -i does not make sense.\" ;;\n+esac\n+\n+if test ! -z \"$templatefile\" -a -z \"$log_given\"\n+then\n+\tif test ! -f \"$templatefile\"\n+\tthen\n+\t\tdie \"Commit template file does not exist.\"\n+\tfi\n+fi\n+\n+################################################################\n+# Prepare index to have a tree to be committed\n+\n+case \"$all,$also\" in\n+t,)\n+\tif test ! -f \"$THIS_INDEX\"\n+\tthen\n+\t\tdie 'nothing to commit (use \"git add file1 file2\" to include for commit)'\n+\tfi\n+\tsave_index &&\n+\t(\n+\t\tcd_to_toplevel &&\n+\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\" &&\n+\t\texport GIT_INDEX_FILE &&\n+\t\tgit diff-files --name-only -z |\n+\t\tgit update-index --remove -z --stdin\n+\t) || exit\n+\t;;\n+,t)\n+\tsave_index &&\n+\tgit ls-files --error-unmatch -- \"$@\" >/dev/null || exit\n+\n+\tgit diff-files --name-only -z -- \"$@\"  |\n+\t(\n+\t\tcd_to_toplevel &&\n+\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\" &&\n+\t\texport GIT_INDEX_FILE &&\n+\t\tgit update-index --remove -z --stdin\n+\t) || exit\n+\t;;\n+,)\n+\tif test \"$interactive\" = t; then\n+\t\tgit add --interactive || exit\n+\tfi\n+\tcase \"$#\" in\n+\t0)\n+\t\t;; # commit as-is\n+\t*)\n+\t\tif test -f \"$GIT_DIR/MERGE_HEAD\"\n+\t\tthen\n+\t\t\trefuse_partial \"Cannot do a partial commit during a merge.\"\n+\t\tfi\n+\t\tTMP_INDEX=\"$GIT_DIR/tmp-index$$\"\n+\t\tcommit_only=`git ls-files --error-unmatch -- \"$@\"` || exit\n+\n+\t\t# Build a temporary index and update the real index\n+\t\t# the same way.\n+\t\tif test -z \"$initial_commit\"\n+\t\tthen\n+\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" \\\n+\t\t\tgit read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n+\t\telse\n+\t\t\trm -f \"$TMP_INDEX\"\n+\t\tfi || exit\n+\n+\t\tprintf '%s\\n' \"$commit_only\" |\n+\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" \\\n+\t\tgit update-index --add --remove --stdin &&\n+\n+\t\tsave_index &&\n+\t\tprintf '%s\\n' \"$commit_only\" |\n+\t\t(\n+\t\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\"\n+\t\t\texport GIT_INDEX_FILE\n+\t\t\tgit update-index --remove --stdin\n+\t\t) || exit\n+\t\t;;\n+\tesac\n+\t;;\n+esac\n+\n+################################################################\n+# If we do as-is commit, the index file will be THIS_INDEX,\n+# otherwise NEXT_INDEX after we make this commit.  We leave\n+# the index as is if we abort.\n+\n+if test -f \"$NEXT_INDEX\"\n+then\n+\tUSE_INDEX=\"$NEXT_INDEX\"\n+else\n+\tUSE_INDEX=\"$THIS_INDEX\"\n+fi\n+\n+case \"$status_only\" in\n+t)\n+\t# This will silently fail in a read-only repository, which is\n+\t# what we want.\n+\tGIT_INDEX_FILE=\"$USE_INDEX\" git update-index -q --unmerged --refresh\n+\trun_status\n+\texit $?\n+\t;;\n+'')\n+\tGIT_INDEX_FILE=\"$USE_INDEX\" git update-index -q --refresh || exit\n+\t;;\n+esac\n+\n+################################################################\n+# Grab commit message, write out tree and make commit.\n+\n+if test t = \"$verify\" && test -x \"$GIT_DIR\"/hooks/pre-commit\n+then\n+\tif test \"$TMP_INDEX\"\n+\tthen\n+\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" \"$GIT_DIR\"/hooks/pre-commit\n+\telse\n+\t\tGIT_INDEX_FILE=\"$USE_INDEX\" \"$GIT_DIR\"/hooks/pre-commit\n+\tfi || exit\n+fi\n+\n+if test \"$log_message\" != ''\n+then\n+\tprintf '%s\\n' \"$log_message\"\n+elif test \"$logfile\" != \"\"\n+then\n+\tif test \"$logfile\" = -\n+\tthen\n+\t\ttest -t 0 &&\n+\t\techo >&2 \"(reading log message from standard input)\"\n+\t\tcat\n+\telse\n+\t\tcat <\"$logfile\"\n+\tfi\n+elif test \"$use_commit\" != \"\"\n+then\n+\tencoding=$(git config i18n.commitencoding || echo UTF-8)\n+\tgit show -s --pretty=raw --encoding=\"$encoding\" \"$use_commit\" |\n+\tsed -e '1,/^$/d' -e 's/^    //'\n+elif test -f \"$GIT_DIR/MERGE_MSG\"\n+then\n+\tcat \"$GIT_DIR/MERGE_MSG\"\n+elif test -f \"$GIT_DIR/SQUASH_MSG\"\n+then\n+\tcat \"$GIT_DIR/SQUASH_MSG\"\n+elif test \"$templatefile\" != \"\"\n+then\n+\tcat \"$templatefile\"\n+fi | git stripspace >\"$GIT_DIR\"/COMMIT_EDITMSG\n+\n+case \"$signoff\" in\n+t)\n+\tsign=$(git-var GIT_COMMITTER_IDENT | sed -e '\n+\t\ts/>.*/>/\n+\t\ts/^/Signed-off-by: /\n+\t\t')\n+\tblank_before_signoff=\n+\ttail -n 1 \"$GIT_DIR\"/COMMIT_EDITMSG |\n+\tgrep 'Signed-off-by:' >/dev/null || blank_before_signoff='\n+'\n+\ttail -n 1 \"$GIT_DIR\"/COMMIT_EDITMSG |\n+\tgrep \"$sign\"$ >/dev/null ||\n+\tprintf '%s%s\\n' \"$blank_before_signoff\" \"$sign\" \\\n+\t\t>>\"$GIT_DIR\"/COMMIT_EDITMSG\n+\t;;\n+esac\n+\n+if test -f \"$GIT_DIR/MERGE_HEAD\" && test -z \"$no_edit\"; then\n+\techo \"#\"\n+\techo \"# It looks like you may be committing a MERGE.\"\n+\techo \"# If this is not correct, please remove the file\"\n+\tprintf '%s\\n' \"#\t$GIT_DIR/MERGE_HEAD\"\n+\techo \"# and try again\"\n+\techo \"#\"\n+fi >>\"$GIT_DIR\"/COMMIT_EDITMSG\n+\n+# Author\n+if test '' != \"$use_commit\"\n+then\n+\teval \"$(get_author_ident_from_commit \"$use_commit\")\"\n+\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE\n+fi\n+if test '' != \"$force_author\"\n+then\n+\tGIT_AUTHOR_NAME=`expr \"z$force_author\" : 'z\\(.*[^ ]\\) *<.*'` &&\n+\tGIT_AUTHOR_EMAIL=`expr \"z$force_author\" : '.*\\(<.*\\)'` &&\n+\ttest '' != \"$GIT_AUTHOR_NAME\" &&\n+\ttest '' != \"$GIT_AUTHOR_EMAIL\" ||\n+\tdie \"malformed --author parameter\"\n+\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL\n+fi\n+\n+PARENTS=\"-p HEAD\"\n+if test -z \"$initial_commit\"\n+then\n+\trloga='commit'\n+\tif [ -f \"$GIT_DIR/MERGE_HEAD\" ]; then\n+\t\trloga='commit (merge)'\n+\t\tPARENTS=\"-p HEAD \"`sed -e 's/^/-p /' \"$GIT_DIR/MERGE_HEAD\"`\n+\telif test -n \"$amend\"; then\n+\t\trloga='commit (amend)'\n+\t\tPARENTS=$(git cat-file commit HEAD |\n+\t\t\tsed -n -e '/^$/q' -e 's/^parent /-p /p')\n+\tfi\n+\tcurrent=\"$(git rev-parse --verify HEAD)\"\n+else\n+\tif [ -z \"$(git ls-files)\" ]; then\n+\t\techo >&2 'nothing to commit (use \"git add file1 file2\" to include for commit)'\n+\t\texit 1\n+\tfi\n+\tPARENTS=\"\"\n+\trloga='commit (initial)'\n+\tcurrent=''\n+fi\n+set_reflog_action \"$rloga\"\n+\n+if test -z \"$no_edit\"\n+then\n+\t{\n+\t\techo \"\"\n+\t\techo \"# Please enter the commit message for your changes.\"\n+\t\techo \"# (Comment lines starting with '#' will not be included)\"\n+\t\ttest -z \"$only_include_assumed\" || echo \"$only_include_assumed\"\n+\t\trun_status\n+\t} >>\"$GIT_DIR\"/COMMIT_EDITMSG\n+else\n+\t# we need to check if there is anything to commit\n+\trun_status >/dev/null\n+fi\n+if [ \"$?\" != \"0\" -a ! -f \"$GIT_DIR/MERGE_HEAD\" -a -z \"$amend\" ]\n+then\n+\trm -f \"$GIT_DIR/COMMIT_EDITMSG\" \"$GIT_DIR/SQUASH_MSG\"\n+\trun_status\n+\texit 1\n+fi\n+\n+case \"$no_edit\" in\n+'')\n+\tgit-var GIT_AUTHOR_IDENT > /dev/null  || die\n+\tgit-var GIT_COMMITTER_IDENT > /dev/null  || die\n+\tgit_editor \"$GIT_DIR/COMMIT_EDITMSG\"\n+\t;;\n+esac\n+\n+case \"$verify\" in\n+t)\n+\tif test -x \"$GIT_DIR\"/hooks/commit-msg\n+\tthen\n+\t\t\"$GIT_DIR\"/hooks/commit-msg \"$GIT_DIR\"/COMMIT_EDITMSG || exit\n+\tfi\n+esac\n+\n+if test -z \"$no_edit\"\n+then\n+    sed -e '\n+        /^diff --git a\\/.*/{\n+\t    s///\n+\t    q\n+\t}\n+\t/^#/d\n+    ' \"$GIT_DIR\"/COMMIT_EDITMSG\n+else\n+    cat \"$GIT_DIR\"/COMMIT_EDITMSG\n+fi |\n+git stripspace >\"$GIT_DIR\"/COMMIT_MSG\n+\n+# Test whether the commit message has any content we didn't supply.\n+have_commitmsg=\n+grep -v -i '^Signed-off-by' \"$GIT_DIR\"/COMMIT_MSG |\n+\tgit stripspace > \"$GIT_DIR\"/COMMIT_BAREMSG\n+\n+# Is the commit message totally empty?\n+if test -s \"$GIT_DIR\"/COMMIT_BAREMSG\n+then\n+\tif test \"$templatefile\" != \"\"\n+\tthen\n+\t\t# Test whether this is just the unaltered template.\n+\t\tif cnt=`sed -e '/^#/d' < \"$templatefile\" |\n+\t\t\tgit stripspace |\n+\t\t\tdiff \"$GIT_DIR\"/COMMIT_BAREMSG - |\n+\t\t\twc -l` &&\n+\t\t   test 0 -lt $cnt\n+\t\tthen\n+\t\t\thave_commitmsg=t\n+\t\tfi\n+\telse\n+\t\t# No template, so the content in the commit message must\n+\t\t# have come from the user.\n+\t\thave_commitmsg=t\n+\tfi\n+fi\n+\n+rm -f \"$GIT_DIR\"/COMMIT_BAREMSG\n+\n+if test \"$have_commitmsg\" = \"t\"\n+then\n+\tif test -z \"$TMP_INDEX\"\n+\tthen\n+\t\ttree=$(GIT_INDEX_FILE=\"$USE_INDEX\" git write-tree)\n+\telse\n+\t\ttree=$(GIT_INDEX_FILE=\"$TMP_INDEX\" git write-tree) &&\n+\t\trm -f \"$TMP_INDEX\"\n+\tfi &&\n+\tcommit=$(git commit-tree $tree $PARENTS <\"$GIT_DIR/COMMIT_MSG\") &&\n+\trlogm=$(sed -e 1q \"$GIT_DIR\"/COMMIT_MSG) &&\n+\tgit update-ref -m \"$GIT_REFLOG_ACTION: $rlogm\" HEAD $commit \"$current\" &&\n+\trm -f -- \"$GIT_DIR/MERGE_HEAD\" \"$GIT_DIR/MERGE_MSG\" &&\n+\tif test -f \"$NEXT_INDEX\"\n+\tthen\n+\t\tmv \"$NEXT_INDEX\" \"$THIS_INDEX\"\n+\telse\n+\t\t: ;# happy\n+\tfi\n+else\n+\techo >&2 \"* no commit message?  aborting commit.\"\n+\tfalse\n+fi\n+ret=\"$?\"\n+rm -f \"$GIT_DIR/COMMIT_MSG\" \"$GIT_DIR/COMMIT_EDITMSG\" \"$GIT_DIR/SQUASH_MSG\"\n+\n+cd_to_toplevel\n+\n+git rerere\n+\n+if test \"$ret\" = 0\n+then\n+\tif test -x \"$GIT_DIR\"/hooks/post-commit\n+\tthen\n+\t\t\"$GIT_DIR\"/hooks/post-commit\n+\tfi\n+\tif test -z \"$quiet\"\n+\tthen\n+\t\tcommit=`git diff-tree --always --shortstat --pretty=\"format:%h: %s\"\\\n+\t\t       --summary --root HEAD --`\n+\t\techo \"Created${initial_commit:+ initial} commit $commit\"\n+\tfi\n+fi\n+\n+exit \"$ret\"\ndiff --git a/git-commit.sh b/git-commit.sh\ndeleted file mode 100755\nindex d7e7028..0000000\n--- a/git-commit.sh\n+++ /dev/null\n@@ -1,665 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Linus Torvalds\n-# Copyright (c) 2006 Junio C Hamano\n-\n-USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'\n-SUBDIRECTORY_OK=Yes\n-. git-sh-setup\n-require_work_tree\n-\n-git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t\n-\n-case \"$0\" in\n-*status)\n-\tstatus_only=t\n-\t;;\n-*commit)\n-\tstatus_only=\n-\t;;\n-esac\n-\n-refuse_partial () {\n-\techo >&2 \"$1\"\n-\techo >&2 \"You might have meant to say 'git commit -i paths...', perhaps?\"\n-\texit 1\n-}\n-\n-THIS_INDEX=\"$GIT_DIR/index\"\n-NEXT_INDEX=\"$GIT_DIR/next-index$$\"\n-rm -f \"$NEXT_INDEX\"\n-save_index () {\n-\tcp -p \"$THIS_INDEX\" \"$NEXT_INDEX\"\n-}\n-\n-run_status () {\n-\t# If TMP_INDEX is defined, that means we are doing\n-\t# \"--only\" partial commit, and that index file is used\n-\t# to build the tree for the commit.  Otherwise, if\n-\t# NEXT_INDEX exists, that is the index file used to\n-\t# make the commit.  Otherwise we are using as-is commit\n-\t# so the regular index file is what we use to compare.\n-\tif test '' != \"$TMP_INDEX\"\n-\tthen\n-\t\tGIT_INDEX_FILE=\"$TMP_INDEX\"\n-\t\texport GIT_INDEX_FILE\n-\telif test -f \"$NEXT_INDEX\"\n-\tthen\n-\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\"\n-\t\texport GIT_INDEX_FILE\n-\tfi\n-\n-\tcase \"$status_only\" in\n-\tt) color= ;;\n-\t*) color=--nocolor ;;\n-\tesac\n-\tgit runstatus ${color} \\\n-\t\t${verbose:+--verbose} \\\n-\t\t${amend:+--amend} \\\n-\t\t${untracked_files:+--untracked}\n-}\n-\n-trap '\n-\ttest -z \"$TMP_INDEX\" || {\n-\t\ttest -f \"$TMP_INDEX\" && rm -f \"$TMP_INDEX\"\n-\t}\n-\trm -f \"$NEXT_INDEX\"\n-' 0\n-\n-################################################################\n-# Command line argument parsing and sanity checking\n-\n-all=\n-also=\n-interactive=\n-only=\n-logfile=\n-use_commit=\n-amend=\n-edit_flag=\n-no_edit=\n-log_given=\n-log_message=\n-verify=t\n-quiet=\n-verbose=\n-signoff=\n-force_author=\n-only_include_assumed=\n-untracked_files=\n-templatefile=\"`git config commit.template`\"\n-while case \"$#\" in 0) break;; esac\n-do\n-\tcase \"$1\" in\n-\t-F|--F|-f|--f|--fi|--fil|--file)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tno_edit=t\n-\t\tlog_given=t$log_given\n-\t\tlogfile=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t-F*|-f*)\n-\t\tno_edit=t\n-\t\tlog_given=t$log_given\n-\t\tlogfile=`expr \"z$1\" : 'z-[Ff]\\(.*\\)'`\n-\t\tshift\n-\t\t;;\n-\t--F=*|--f=*|--fi=*|--fil=*|--file=*)\n-\t\tno_edit=t\n-\t\tlog_given=t$log_given\n-\t\tlogfile=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n-\t\tshift\n-\t\t;;\n-\t-a|--a|--al|--all)\n-\t\tall=t\n-\t\tshift\n-\t\t;;\n-\t--au=*|--aut=*|--auth=*|--autho=*|--author=*)\n-\t\tforce_author=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n-\t\tshift\n-\t\t;;\n-\t--au|--aut|--auth|--autho|--author)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tforce_author=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t-e|--e|--ed|--edi|--edit)\n-\t\tedit_flag=t\n-\t\tshift\n-\t\t;;\n-\t-i|--i|--in|--inc|--incl|--inclu|--includ|--include)\n-\t\talso=t\n-\t\tshift\n-\t\t;;\n-\t--int|--inte|--inter|--intera|--interac|--interact|--interacti|\\\n-\t--interactiv|--interactive)\n-\t\tinteractive=t\n-\t\tshift\n-\t\t;;\n-\t-o|--o|--on|--onl|--only)\n-\t\tonly=t\n-\t\tshift\n-\t\t;;\n-\t-m|--m|--me|--mes|--mess|--messa|--messag|--message)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tlog_given=m$log_given\n-\t\tif test \"$log_message\" = ''\n-\t\tthen\n-\t\t    log_message=\"$1\"\n-\t\telse\n-\t\t    log_message=\"$log_message\n-\n-$1\"\n-\t\tfi\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t-m*)\n-\t\tlog_given=m$log_given\n-\t\tif test \"$log_message\" = ''\n-\t\tthen\n-\t\t    log_message=`expr \"z$1\" : 'z-m\\(.*\\)'`\n-\t\telse\n-\t\t    log_message=\"$log_message\n-\n-`expr \"z$1\" : 'z-m\\(.*\\)'`\"\n-\t\tfi\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)\n-\t\tlog_given=m$log_given\n-\t\tif test \"$log_message\" = ''\n-\t\tthen\n-\t\t    log_message=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n-\t\telse\n-\t\t    log_message=\"$log_message\n-\n-`expr \"z$1\" : 'zq-[^=]*=\\(.*\\)'`\"\n-\t\tfi\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t-n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\\\n-\t--no-verify)\n-\t\tverify=\n-\t\tshift\n-\t\t;;\n-\t--a|--am|--ame|--amen|--amend)\n-\t\tamend=t\n-\t\tuse_commit=HEAD\n-\t\tshift\n-\t\t;;\n-\t-c)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=\"$1\"\n-\t\tno_edit=\n-\t\tshift\n-\t\t;;\n-\t--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\\\n-\t--reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\\\n-\t--reedit-messag=*|--reedit-message=*)\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n-\t\tno_edit=\n-\t\tshift\n-\t\t;;\n-\t--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\\\n-\t--reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\\\n-\t--reedit-message)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=\"$1\"\n-\t\tno_edit=\n-\t\tshift\n-\t\t;;\n-\t-C)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=\"$1\"\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\\\n-\t--reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\\\n-\t--reuse-message=*)\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'`\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\\\n-\t--reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\tlog_given=t$log_given\n-\t\tuse_commit=\"$1\"\n-\t\tno_edit=t\n-\t\tshift\n-\t\t;;\n-\t-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)\n-\t\tsignoff=t\n-\t\tshift\n-\t\t;;\n-\t-t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)\n-\t\tcase \"$#\" in 1) usage ;; esac\n-\t\tshift\n-\t\ttemplatefile=\"$1\"\n-\t\tno_edit=\n-\t\tshift\n-\t\t;;\n-\t-q|--q|--qu|--qui|--quie|--quiet)\n-\t\tquiet=t\n-\t\tshift\n-\t\t;;\n-\t-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)\n-\t\tverbose=t\n-\t\tshift\n-\t\t;;\n-\t-u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\\\n-\t--untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\\\n-\t--untracked-file|--untracked-files)\n-\t\tuntracked_files=t\n-\t\tshift\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\t-*)\n-\t\tusage\n-\t\t;;\n-\t*)\n-\t\tbreak\n-\t\t;;\n-\tesac\n-done\n-case \"$edit_flag\" in t) no_edit= ;; esac\n-\n-################################################################\n-# Sanity check options\n-\n-case \"$amend,$initial_commit\" in\n-t,t)\n-\tdie \"You do not have anything to amend.\" ;;\n-t,)\n-\tif [ -f \"$GIT_DIR/MERGE_HEAD\" ]; then\n-\t\tdie \"You are in the middle of a merge -- cannot amend.\"\n-\tfi ;;\n-esac\n-\n-case \"$log_given\" in\n-tt*)\n-\tdie \"Only one of -c/-C/-F can be used.\" ;;\n-*tm*|*mt*)\n-\tdie \"Option -m cannot be combined with -c/-C/-F.\" ;;\n-esac\n-\n-case \"$#,$also,$only,$amend\" in\n-*,t,t,*)\n-\tdie \"Only one of --include/--only can be used.\" ;;\n-0,t,,* | 0,,t,)\n-\tdie \"No paths with --include/--only does not make sense.\" ;;\n-0,,t,t)\n-\tonly_include_assumed=\"# Clever... amending the last one with dirty index.\" ;;\n-0,,,*)\n-\t;;\n-*,,,*)\n-\tonly_include_assumed=\"# Explicit paths specified without -i nor -o; assuming --only paths...\"\n-\talso=\n-\t;;\n-esac\n-unset only\n-case \"$all,$interactive,$also,$#\" in\n-*t,*t,*)\n-\tdie \"Cannot use -a, --interactive or -i at the same time.\" ;;\n-t,,[1-9]*)\n-\tdie \"Paths with -a does not make sense.\" ;;\n-,t,[1-9]*)\n-\tdie \"Paths with --interactive does not make sense.\" ;;\n-,,t,0)\n-\tdie \"No paths with -i does not make sense.\" ;;\n-esac\n-\n-if test ! -z \"$templatefile\" -a -z \"$log_given\"\n-then\n-\tif test ! -f \"$templatefile\"\n-\tthen\n-\t\tdie \"Commit template file does not exist.\"\n-\tfi\n-fi\n-\n-################################################################\n-# Prepare index to have a tree to be committed\n-\n-case \"$all,$also\" in\n-t,)\n-\tif test ! -f \"$THIS_INDEX\"\n-\tthen\n-\t\tdie 'nothing to commit (use \"git add file1 file2\" to include for commit)'\n-\tfi\n-\tsave_index &&\n-\t(\n-\t\tcd_to_toplevel &&\n-\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\" &&\n-\t\texport GIT_INDEX_FILE &&\n-\t\tgit diff-files --name-only -z |\n-\t\tgit update-index --remove -z --stdin\n-\t) || exit\n-\t;;\n-,t)\n-\tsave_index &&\n-\tgit ls-files --error-unmatch -- \"$@\" >/dev/null || exit\n-\n-\tgit diff-files --name-only -z -- \"$@\"  |\n-\t(\n-\t\tcd_to_toplevel &&\n-\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\" &&\n-\t\texport GIT_INDEX_FILE &&\n-\t\tgit update-index --remove -z --stdin\n-\t) || exit\n-\t;;\n-,)\n-\tif test \"$interactive\" = t; then\n-\t\tgit add --interactive || exit\n-\tfi\n-\tcase \"$#\" in\n-\t0)\n-\t\t;; # commit as-is\n-\t*)\n-\t\tif test -f \"$GIT_DIR/MERGE_HEAD\"\n-\t\tthen\n-\t\t\trefuse_partial \"Cannot do a partial commit during a merge.\"\n-\t\tfi\n-\t\tTMP_INDEX=\"$GIT_DIR/tmp-index$$\"\n-\t\tcommit_only=`git ls-files --error-unmatch -- \"$@\"` || exit\n-\n-\t\t# Build a temporary index and update the real index\n-\t\t# the same way.\n-\t\tif test -z \"$initial_commit\"\n-\t\tthen\n-\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" \\\n-\t\t\tgit read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n-\t\telse\n-\t\t\trm -f \"$TMP_INDEX\"\n-\t\tfi || exit\n-\n-\t\tprintf '%s\\n' \"$commit_only\" |\n-\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" \\\n-\t\tgit update-index --add --remove --stdin &&\n-\n-\t\tsave_index &&\n-\t\tprintf '%s\\n' \"$commit_only\" |\n-\t\t(\n-\t\t\tGIT_INDEX_FILE=\"$NEXT_INDEX\"\n-\t\t\texport GIT_INDEX_FILE\n-\t\t\tgit update-index --remove --stdin\n-\t\t) || exit\n-\t\t;;\n-\tesac\n-\t;;\n-esac\n-\n-################################################################\n-# If we do as-is commit, the index file will be THIS_INDEX,\n-# otherwise NEXT_INDEX after we make this commit.  We leave\n-# the index as is if we abort.\n-\n-if test -f \"$NEXT_INDEX\"\n-then\n-\tUSE_INDEX=\"$NEXT_INDEX\"\n-else\n-\tUSE_INDEX=\"$THIS_INDEX\"\n-fi\n-\n-case \"$status_only\" in\n-t)\n-\t# This will silently fail in a read-only repository, which is\n-\t# what we want.\n-\tGIT_INDEX_FILE=\"$USE_INDEX\" git update-index -q --unmerged --refresh\n-\trun_status\n-\texit $?\n-\t;;\n-'')\n-\tGIT_INDEX_FILE=\"$USE_INDEX\" git update-index -q --refresh || exit\n-\t;;\n-esac\n-\n-################################################################\n-# Grab commit message, write out tree and make commit.\n-\n-if test t = \"$verify\" && test -x \"$GIT_DIR\"/hooks/pre-commit\n-then\n-\tif test \"$TMP_INDEX\"\n-\tthen\n-\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" \"$GIT_DIR\"/hooks/pre-commit\n-\telse\n-\t\tGIT_INDEX_FILE=\"$USE_INDEX\" \"$GIT_DIR\"/hooks/pre-commit\n-\tfi || exit\n-fi\n-\n-if test \"$log_message\" != ''\n-then\n-\tprintf '%s\\n' \"$log_message\"\n-elif test \"$logfile\" != \"\"\n-then\n-\tif test \"$logfile\" = -\n-\tthen\n-\t\ttest -t 0 &&\n-\t\techo >&2 \"(reading log message from standard input)\"\n-\t\tcat\n-\telse\n-\t\tcat <\"$logfile\"\n-\tfi\n-elif test \"$use_commit\" != \"\"\n-then\n-\tencoding=$(git config i18n.commitencoding || echo UTF-8)\n-\tgit show -s --pretty=raw --encoding=\"$encoding\" \"$use_commit\" |\n-\tsed -e '1,/^$/d' -e 's/^    //'\n-elif test -f \"$GIT_DIR/MERGE_MSG\"\n-then\n-\tcat \"$GIT_DIR/MERGE_MSG\"\n-elif test -f \"$GIT_DIR/SQUASH_MSG\"\n-then\n-\tcat \"$GIT_DIR/SQUASH_MSG\"\n-elif test \"$templatefile\" != \"\"\n-then\n-\tcat \"$templatefile\"\n-fi | git stripspace >\"$GIT_DIR\"/COMMIT_EDITMSG\n-\n-case \"$signoff\" in\n-t)\n-\tsign=$(git-var GIT_COMMITTER_IDENT | sed -e '\n-\t\ts/>.*/>/\n-\t\ts/^/Signed-off-by: /\n-\t\t')\n-\tblank_before_signoff=\n-\ttail -n 1 \"$GIT_DIR\"/COMMIT_EDITMSG |\n-\tgrep 'Signed-off-by:' >/dev/null || blank_before_signoff='\n-'\n-\ttail -n 1 \"$GIT_DIR\"/COMMIT_EDITMSG |\n-\tgrep \"$sign\"$ >/dev/null ||\n-\tprintf '%s%s\\n' \"$blank_before_signoff\" \"$sign\" \\\n-\t\t>>\"$GIT_DIR\"/COMMIT_EDITMSG\n-\t;;\n-esac\n-\n-if test -f \"$GIT_DIR/MERGE_HEAD\" && test -z \"$no_edit\"; then\n-\techo \"#\"\n-\techo \"# It looks like you may be committing a MERGE.\"\n-\techo \"# If this is not correct, please remove the file\"\n-\tprintf '%s\\n' \"#\t$GIT_DIR/MERGE_HEAD\"\n-\techo \"# and try again\"\n-\techo \"#\"\n-fi >>\"$GIT_DIR\"/COMMIT_EDITMSG\n-\n-# Author\n-if test '' != \"$use_commit\"\n-then\n-\teval \"$(get_author_ident_from_commit \"$use_commit\")\"\n-\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE\n-fi\n-if test '' != \"$force_author\"\n-then\n-\tGIT_AUTHOR_NAME=`expr \"z$force_author\" : 'z\\(.*[^ ]\\) *<.*'` &&\n-\tGIT_AUTHOR_EMAIL=`expr \"z$force_author\" : '.*\\(<.*\\)'` &&\n-\ttest '' != \"$GIT_AUTHOR_NAME\" &&\n-\ttest '' != \"$GIT_AUTHOR_EMAIL\" ||\n-\tdie \"malformed --author parameter\"\n-\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL\n-fi\n-\n-PARENTS=\"-p HEAD\"\n-if test -z \"$initial_commit\"\n-then\n-\trloga='commit'\n-\tif [ -f \"$GIT_DIR/MERGE_HEAD\" ]; then\n-\t\trloga='commit (merge)'\n-\t\tPARENTS=\"-p HEAD \"`sed -e 's/^/-p /' \"$GIT_DIR/MERGE_HEAD\"`\n-\telif test -n \"$amend\"; then\n-\t\trloga='commit (amend)'\n-\t\tPARENTS=$(git cat-file commit HEAD |\n-\t\t\tsed -n -e '/^$/q' -e 's/^parent /-p /p')\n-\tfi\n-\tcurrent=\"$(git rev-parse --verify HEAD)\"\n-else\n-\tif [ -z \"$(git ls-files)\" ]; then\n-\t\techo >&2 'nothing to commit (use \"git add file1 file2\" to include for commit)'\n-\t\texit 1\n-\tfi\n-\tPARENTS=\"\"\n-\trloga='commit (initial)'\n-\tcurrent=''\n-fi\n-set_reflog_action \"$rloga\"\n-\n-if test -z \"$no_edit\"\n-then\n-\t{\n-\t\techo \"\"\n-\t\techo \"# Please enter the commit message for your changes.\"\n-\t\techo \"# (Comment lines starting with '#' will not be included)\"\n-\t\ttest -z \"$only_include_assumed\" || echo \"$only_include_assumed\"\n-\t\trun_status\n-\t} >>\"$GIT_DIR\"/COMMIT_EDITMSG\n-else\n-\t# we need to check if there is anything to commit\n-\trun_status >/dev/null\n-fi\n-if [ \"$?\" != \"0\" -a ! -f \"$GIT_DIR/MERGE_HEAD\" -a -z \"$amend\" ]\n-then\n-\trm -f \"$GIT_DIR/COMMIT_EDITMSG\" \"$GIT_DIR/SQUASH_MSG\"\n-\trun_status\n-\texit 1\n-fi\n-\n-case \"$no_edit\" in\n-'')\n-\tgit-var GIT_AUTHOR_IDENT > /dev/null  || die\n-\tgit-var GIT_COMMITTER_IDENT > /dev/null  || die\n-\tgit_editor \"$GIT_DIR/COMMIT_EDITMSG\"\n-\t;;\n-esac\n-\n-case \"$verify\" in\n-t)\n-\tif test -x \"$GIT_DIR\"/hooks/commit-msg\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/commit-msg \"$GIT_DIR\"/COMMIT_EDITMSG || exit\n-\tfi\n-esac\n-\n-if test -z \"$no_edit\"\n-then\n-    sed -e '\n-        /^diff --git a\\/.*/{\n-\t    s///\n-\t    q\n-\t}\n-\t/^#/d\n-    ' \"$GIT_DIR\"/COMMIT_EDITMSG\n-else\n-    cat \"$GIT_DIR\"/COMMIT_EDITMSG\n-fi |\n-git stripspace >\"$GIT_DIR\"/COMMIT_MSG\n-\n-# Test whether the commit message has any content we didn't supply.\n-have_commitmsg=\n-grep -v -i '^Signed-off-by' \"$GIT_DIR\"/COMMIT_MSG |\n-\tgit stripspace > \"$GIT_DIR\"/COMMIT_BAREMSG\n-\n-# Is the commit message totally empty?\n-if test -s \"$GIT_DIR\"/COMMIT_BAREMSG\n-then\n-\tif test \"$templatefile\" != \"\"\n-\tthen\n-\t\t# Test whether this is just the unaltered template.\n-\t\tif cnt=`sed -e '/^#/d' < \"$templatefile\" |\n-\t\t\tgit stripspace |\n-\t\t\tdiff \"$GIT_DIR\"/COMMIT_BAREMSG - |\n-\t\t\twc -l` &&\n-\t\t   test 0 -lt $cnt\n-\t\tthen\n-\t\t\thave_commitmsg=t\n-\t\tfi\n-\telse\n-\t\t# No template, so the content in the commit message must\n-\t\t# have come from the user.\n-\t\thave_commitmsg=t\n-\tfi\n-fi\n-\n-rm -f \"$GIT_DIR\"/COMMIT_BAREMSG\n-\n-if test \"$have_commitmsg\" = \"t\"\n-then\n-\tif test -z \"$TMP_INDEX\"\n-\tthen\n-\t\ttree=$(GIT_INDEX_FILE=\"$USE_INDEX\" git write-tree)\n-\telse\n-\t\ttree=$(GIT_INDEX_FILE=\"$TMP_INDEX\" git write-tree) &&\n-\t\trm -f \"$TMP_INDEX\"\n-\tfi &&\n-\tcommit=$(git commit-tree $tree $PARENTS <\"$GIT_DIR/COMMIT_MSG\") &&\n-\trlogm=$(sed -e 1q \"$GIT_DIR\"/COMMIT_MSG) &&\n-\tgit update-ref -m \"$GIT_REFLOG_ACTION: $rlogm\" HEAD $commit \"$current\" &&\n-\trm -f -- \"$GIT_DIR/MERGE_HEAD\" \"$GIT_DIR/MERGE_MSG\" &&\n-\tif test -f \"$NEXT_INDEX\"\n-\tthen\n-\t\tmv \"$NEXT_INDEX\" \"$THIS_INDEX\"\n-\telse\n-\t\t: ;# happy\n-\tfi\n-else\n-\techo >&2 \"* no commit message?  aborting commit.\"\n-\tfalse\n-fi\n-ret=\"$?\"\n-rm -f \"$GIT_DIR/COMMIT_MSG\" \"$GIT_DIR/COMMIT_EDITMSG\" \"$GIT_DIR/SQUASH_MSG\"\n-\n-cd_to_toplevel\n-\n-git rerere\n-\n-if test \"$ret\" = 0\n-then\n-\tif test -x \"$GIT_DIR\"/hooks/post-commit\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/post-commit\n-\tfi\n-\tif test -z \"$quiet\"\n-\tthen\n-\t\tcommit=`git diff-tree --always --shortstat --pretty=\"format:%h: %s\"\\\n-\t\t       --summary --root HEAD --`\n-\t\techo \"Created${initial_commit:+ initial} commit $commit\"\n-\tfi\n-fi\n-\n-exit \"$ret\"\ndiff --git a/git.c b/git.c\nindex cab0e72..62859a2 100644\n--- a/git.c\n+++ b/git.c\n@@ -321,6 +321,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"check-attr\", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n \t\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n+\t\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n \t\t{ \"config\", cmd_config },\n \t\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n@@ -363,10 +364,10 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"rev-parse\", cmd_rev_parse, RUN_SETUP },\n \t\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"rm\", cmd_rm, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"runstatus\", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"shortlog\", cmd_shortlog, RUN_SETUP | USE_PAGER },\n \t\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n \t\t{ \"show\", cmd_show, RUN_SETUP | USE_PAGER },\n+\t\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"stripspace\", cmd_stripspace },\n \t\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n \t\t{ \"tag\", cmd_tag, RUN_SETUP },\n-- \n1.5.2.GIT\n"},{"id":"52715","messageId":"7vwsv4b2bl.fsf@gitster.siamese.dyndns.org","threadId":"9792","inReplyTo":"11890382243290-git-send-email-krh@redhat.com","subject":"Re: [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-06T08:55:26Z","receivedAt":"2007-09-06T08:55:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"As you noted in your follow-up message, this one has overlaps\nwith the other strbuf series.  I could adjust them if I wanted\nto, but I do not have time for it right now.  I might try over\nthe weekend but no promises.\n"},{"id":"52721","messageId":"20070906094323.GB8451@artemis.corp","threadId":"9792","inReplyTo":"7vwsv4b2bl.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-06T09:43:23Z","receivedAt":"2007-09-06T09:43:23Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"On Thu, Sep 06, 2007 at 08:55:26AM +0000, Junio C Hamano wrote:\n> As you noted in your follow-up message, this one has overlaps\n> with the other strbuf series.  I could adjust them if I wanted\n> to, but I do not have time for it right now.  I might try over\n> the weekend but no promises.\n\n  This one is exactly the same as the one that follows, I corrected a\ntypo in the comment of the commit, and I forgot to cleanse my tree\nbefore running format-patch again, so you have the \"second\" patch twice\n(name of the patch changed, hence the new one did not replaced the\nprevious, but created a 0002-foo.patch instead of overwriting the\n0002-bar.patch).\n\n  You just must drop the one I followup-ed to.\n\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"52723","messageId":"20070906095016.GD8451@artemis.corp","threadId":"9792","inReplyTo":"20070906094323.GB8451@artemis.corp","subject":"Re: [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-06T09:50:16Z","receivedAt":"2007-09-06T09:50:16Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"On Thu, Sep 06, 2007 at 09:43:23AM +0000, Pierre Habouzit wrote:\n> On Thu, Sep 06, 2007 at 08:55:26AM +0000, Junio C Hamano wrote:\n> > As you noted in your follow-up message, this one has overlaps\n> > with the other strbuf series.  I could adjust them if I wanted\n> > to, but I do not have time for it right now.  I might try over\n> > the weekend but no promises.\n> \n>   This one is exactly the same as the one that follows, I corrected a\n> typo in the comment of the commit, and I forgot to cleanse my tree\n> before running format-patch again, so you have the \"second\" patch twice\n> (name of the patch changed, hence the new one did not replaced the\n> previous, but created a 0002-foo.patch instead of overwriting the\n> 0002-bar.patch).\n> \n>   You just must drop the one I followup-ed to.\n\n  err sorry, I mixed up with another thread. Did not had coffee yet :/\n\n  Just nvm\n\n\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"52770","messageId":"Pine.LNX.4.64.0709061726010.28586@racer.site","threadId":"9792","inReplyTo":"11890382183913-git-send-email-krh@redhat.com","subject":"Re: [PATCH 1/9] Enable wt-status output to a given FILE pointer.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-06T16:27:59Z","receivedAt":"2007-09-06T16:27:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n\n> Still defaults to stdout, but you can now override wt_status.fp after \n> calling wt_status_prepare().\n\nWould it not be easier to freopen(filename, \"a\", stdout)?\n\nCiao,\nDscho\n"},{"id":"52771","messageId":"Pine.LNX.4.64.0709061729270.28586@racer.site","threadId":"9792","inReplyTo":"11890382253220-git-send-email-krh@redhat.com","subject":"Re: [PATCH 4/9] Introduce entry point for launching add--interactive.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-06T16:31:39Z","receivedAt":"2007-09-06T16:31:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n\n> diff --git a/builtin-add.c b/builtin-add.c\n> index 3dd4ded..e79e8f7 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -153,6 +154,13 @@ static int git_add_config(const char *var, const char *value)\n>  \treturn git_default_config(var, value);\n>  }\n>  \n> +int interactive_add(void)\n> +{\n> +\tconst char *argv[2] = { \"add--interactive\", NULL };\n> +\n> +\treturn run_command_v_opt(argv, RUN_GIT_CMD);\n> +}\n\nI'd rather have this in builtin-commit.c, since it is quite funny if \nbuiltin-add.c has code to fork() and exec() itself (eventually, that \nis) ;-)\n\n> diff --git a/commit.h b/commit.h\n> index 467872e..64e1d4b 100644\n> --- a/commit.h\n> +++ b/commit.h\n> @@ -122,4 +122,13 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,\n>  \t\tint depth, int shallow_flag, int not_shallow_flag);\n>  \n>  int in_merge_bases(struct commit *, struct commit **, int);\n> +\n> +extern const unsigned char *\n> +create_commit(const unsigned char *tree_sha1,\n> +\t      unsigned char parent_sha1[][20], int parents,\n> +\t      const char *author_info, const char *committer_info,\n> +\t      const char *message, int length);\n> +\n> +extern int interactive_add(void);\n> +\n\nJust a guess: you did not want create_commit() to creep in here, right?\n\nCiao,\nDscho\n"},{"id":"52774","messageId":"Pine.LNX.4.64.0709061732480.28586@racer.site","threadId":"9792","inReplyTo":"1189038225525-git-send-email-krh@redhat.com","subject":"Re: [PATCH 6/9] Rewrite launch_editor, create_tag and stripspace to use strbufs.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-06T16:38:35Z","receivedAt":"2007-09-06T16:38:35Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n\n> diff --git a/strbuf.c b/strbuf.c\n> index fcfc05e..ed2afea 100644\n> --- a/strbuf.c\n> +++ b/strbuf.c\n> @@ -73,43 +74,15 @@ void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n>  {\n>  \tchar buffer[2048];\n>  \tva_list args;\n> -\tint len, size = 2 * sizeof buffer;\n> +\tint len;\n>  \n>  \tva_start(args, fmt);\n>  \tlen = vsnprintf(buffer, sizeof(buffer), fmt, args);\n>  \tva_end(args);\n>  \n> -\tif (len > sizeof(buffer)) {\n> -\t\t/*\n> -\t\t * Didn't fit in the buffer, but this vsnprintf at\n> -\t\t * least gives us the required length back.  Grow the\n> -\t\t * buffer acccordingly and try again.\n> -\t\t */\n> -\t\tstrbuf_grow(sb, len);\n> -\t\tva_start(args, fmt);\n> -\t\tlen = vsnprintf(sb->buf + sb->len,\n> -\t\t\t\tsb->alloc - sb->len, fmt, args);\n> -\t\tva_end(args);\n> -\t} else if (len >= 0) {\n> -\t\t/*\n> -\t\t * The initial vsnprintf fit in the temp buffer, just\n> -\t\t * copy it to the strbuf.\n> -\t\t */\n> -\t\tstrbuf_add(sb, buffer, len);\n> -\t} else {\n> -\t\t/*\n> -\t\t * This vnsprintf sucks and just returns -1 when the\n> -\t\t * buffer is too small.  Keep doubling the size until\n> -\t\t * it fits.\n> -\t\t */\n> -\t\twhile (len < 0) {\n> -\t\t\tstrbuf_grow(sb, size);\n> -\t\t\tva_start(args, fmt);\n> -\t\t\tlen = vsnprintf(sb->buf + sb->len,\n> -\t\t\t\t\tsb->alloc - sb->len, fmt, args);\n> -\t\t\tva_end(args);\n> -\t\t\tsize *= 2;\n> -\t\t}\n> -\t}\n> +\tif (len > sizeof(buffer) || len < 0)\n> +\t\tdie(\"out of buffer space\\n\");\n> +\n> +\tstrbuf_add(sb, buffer, len);\n>  }\n\nReally?\n\n(If you find the time, it would be really nice to rebase that patch series \non top of Pierre's strbuf work...)\n\nCiao,\nDscho\n"},{"id":"52776","messageId":"Pine.LNX.4.64.0709061739090.28586@racer.site","threadId":"9792","inReplyTo":"11890382262161-git-send-email-krh@redhat.com","subject":"Re: [PATCH 7/9] Add strbuf_read_path().","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-06T16:40:02Z","receivedAt":"2007-09-06T16:40:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n\n> +extern int strbuf_read_path(struct strbuf *sb, const char *path);\n\nMay I suggest renaming this to \"strbuf_read_file()\"?  I kind of expected a \nfunction which reads in the absolute path of a file, judging by the \nname...\n\nCiao,\nDscho\n"},{"id":"52778","messageId":"Pine.LNX.4.64.0709061741370.28586@racer.site","threadId":"9792","inReplyTo":"11890382271931-git-send-email-krh@redhat.com","subject":"Re: [PATCH 9/9] Implement git commit as a builtin command.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-06T16:59:52Z","receivedAt":"2007-09-06T16:59:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n\n>  contrib/examples/git-commit.sh |  665 +++++++++++++++++++++++++++++++++++\n>  git-commit.sh                  |  665 -----------------------------------\n\nYou might want to use \"git format-patch -M\" next time ;-)\n\n> @@ -357,7 +358,6 @@ BUILTIN_OBJS = \\\n>  \tbuiltin-rev-parse.o \\\n>  \tbuiltin-revert.o \\\n>  \tbuiltin-rm.o \\\n> -\tbuiltin-runstatus.o \\\n\nBetter keep it; some people's scripts could depend on it.\n\n> +struct option {\n> +    enum option_type type;\n> +    const char *long_name;\n> +    char short_name;\n> +    void *value;\n> +};\n> +\n> +static int scan_options(const char ***argv, struct option *options)\n> +{\n\nI would not (no longer, anyway) be opposed to replacing the option parsing \nin git with getopt(); I hear that it is small enough to keep a copy in \ncompat/getopt.c.\n\nBut let's go forward with builtin-commit; getopt() can come later.\n\n> +static char *\n> +prepare_index(const char **files, const char *prefix)\n> +{\n> +\tint fd;\n> +\tstruct tree *tree;\n> +\tstruct lock_file *next_index_lock;\n> +\n> +\tfd = hold_locked_index(&lock_file, 1);\n> +\tif (read_cache() < 0)\n> +\t\tdie(\"index file corrupt\");\n> +\n> +\tif (all) {\n> +\t\tadd_files_to_cache(fd, files, NULL);\n> +\t\treturn lock_file.filename;\n> +\t} else if (also) {\n> +\t\tadd_files_to_cache(fd, files, prefix);\n> +\t\treturn lock_file.filename;\n> +\t}\n> +\n> +\tif (interactive)\n> +\t\tinteractive_add();\n> +\n> +\tif (*files == NULL) {\n> +\t\t/* Commit index as-is. */\n> +\t\trollback_lock_file(&lock_file);\n> +\t\treturn get_index_file();\n> +\t}\n> +\n> +\t/*\n> +\t * FIXME: Warn on unknown files.  Shell script does\n> +\t *\n> +\t *   commit_only=`git-ls-files --error-unmatch -- \"$@\"`\n> +\t */\n> +\n> +\t/*\n> +\t * FIXME: shell script does\n> +\t *\n> +\t *   git-read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n> +\t *\n> +\t * which warns about unmerged files in the index.\n> +\t */\n> +\n> +\t/* update the user index file */\n> +\tadd_files_to_cache(fd, files, prefix);\n\nI suspect this, or ...\n\n> +\n> +\tif (!initial_commit) {\n> +\t\ttree = parse_tree_indirect(head_sha1);\n> +\t\tif (!tree)\n> +\t\t\tdie(\"failed to unpack HEAD tree object\");\n> +\t\tif (read_tree(tree, 0, NULL))\n> +\t\t\tdie(\"failed to read HEAD tree object\");\n> +\t}\n> +\n> +\t/* Uh oh, abusing lock_file to create a garbage collected file */\n> +\tnext_index_lock = xmalloc(sizeof(*next_index_lock));\n> +\tfd = hold_lock_file_for_update(next_index_lock,\n> +\t\t\t\t       git_path(\"next-index-%d\", getpid()), 1);\n> +\tadd_files_to_cache(fd, files, prefix);\n\n... this, but not both.\n\n> +/* Find out if the message starting at position 'start' in the strbuf\n> + * contains only whitespace and Signed-off-by lines. */\n> +static int message_is_empty(struct strbuf *sb, int start)\n> +{\n> +\tstatic const char signed_off_by[] = \"Signed-off-by: \";\n\nI think you already defined that globally earlier.\n\nIn the function message_is_empty() you write:\n\n> +\t/* See if the template is just a prefix of the message. */\n> +\tstrbuf_init(&tmpl);\n> +\tif (template_file && strbuf_read_path(&tmpl, template_file) > 0) {\n> +\t\tstripspace(&tmpl, 1);\n> +\t\tif (start + tmpl.len <= sb->len &&\n> +\t\t    memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)\n> +\t\t\tstart += tmpl.len;\n\nCould we not bail out here, if there is no match?  In that case, the \nmessage is clearly not empty...\n\n> +\t/* Check if the rest is just whitespace and Signed-of-by's. */\n> +\tfor (i = start; i < sb->len; i++) {\n> +\t\tnl = memchr(sb->buf + i, '\\n', sb->len - i);\n> +\t\tif (nl)\n> +\t\t\teol = nl - sb->buf;\n> +\t\telse\n> +\t\t\teol = sb->len;\n\nWhy not just \"if (isspace(sb->buf[i]) || sb->buf[i] == '\\n') continue;\"? \nThis would also catch the cases where people indent their S-O-Bs.\n\n> +\n> +\t\tif (strlen(signed_off_by) <= eol - i &&\n> +\t\t    !prefixcmp(sb->buf + i, signed_off_by)) {\n> +\t\t\ti = eol;\n> +\t\t\tcontinue;\n> +\t\t}\n> +\t\twhile (i < eol)\n> +\t\t\tif (!isspace(sb->buf[i++]))\n> +\t\t\t\treturn 0;\n> +\t}\n> +\n> +\treturn 1;\n> +}\n\nI did not review the rest of the code closely yet...\n\nAll in all: well done!\n\nCiao,\nDscho\n"},{"id":"53362","messageId":"1190069881.10112.10.camel@hinata.boston.redhat.com","threadId":"9792","inReplyTo":"Pine.LNX.4.64.0709061741370.28586@racer.site","subject":"Re: [PATCH 9/9] Implement git commit as a builtin command.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-17T22:58:01Z","receivedAt":"2007-09-17T22:58:01Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2007-09-06 at 17:59 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> \n> >  contrib/examples/git-commit.sh |  665 +++++++++++++++++++++++++++++++++++\n> >  git-commit.sh                  |  665 -----------------------------------\n> \n> You might want to use \"git format-patch -M\" next time ;-)\n> \n> > @@ -357,7 +358,6 @@ BUILTIN_OBJS = \\\n> >  \tbuiltin-rev-parse.o \\\n> >  \tbuiltin-revert.o \\\n> >  \tbuiltin-rm.o \\\n> > -\tbuiltin-runstatus.o \\\n> \n> Better keep it; some people's scripts could depend on it.\n\nSeriously?  Why don't we remove it and see if somebody yells?  It's more\nof an implementation detail than most other git commands; if you need\nstatus output in your script why wouldn't you just run git status?\n\n> > +struct option {\n> > +    enum option_type type;\n> > +    const char *long_name;\n> > +    char short_name;\n> > +    void *value;\n> > +};\n> > +\n> > +static int scan_options(const char ***argv, struct option *options)\n> > +{\n> \n> I would not (no longer, anyway) be opposed to replacing the option parsing \n> in git with getopt(); I hear that it is small enough to keep a copy in \n> compat/getopt.c.\n> \n> But let's go forward with builtin-commit; getopt() can come later.\n\nI don't know.  I think it's a situation much like the string library\ndiscussion.  It's a small enough dependency (70 lines!) that there's no\ngain in depending on an external implementation, and we can tailor it to\ngits needs as we extend the use within git.  And we can call it gitopt!\n\n> > +static char *\n> > +prepare_index(const char **files, const char *prefix)\n> > +{\n> > +\tint fd;\n> > +\tstruct tree *tree;\n> > +\tstruct lock_file *next_index_lock;\n> > +\n> > +\tfd = hold_locked_index(&lock_file, 1);\n> > +\tif (read_cache() < 0)\n> > +\t\tdie(\"index file corrupt\");\n> > +\n> > +\tif (all) {\n> > +\t\tadd_files_to_cache(fd, files, NULL);\n> > +\t\treturn lock_file.filename;\n> > +\t} else if (also) {\n> > +\t\tadd_files_to_cache(fd, files, prefix);\n> > +\t\treturn lock_file.filename;\n> > +\t}\n> > +\n> > +\tif (interactive)\n> > +\t\tinteractive_add();\n> > +\n> > +\tif (*files == NULL) {\n> > +\t\t/* Commit index as-is. */\n> > +\t\trollback_lock_file(&lock_file);\n> > +\t\treturn get_index_file();\n> > +\t}\n> > +\n> > +\t/*\n> > +\t * FIXME: Warn on unknown files.  Shell script does\n> > +\t *\n> > +\t *   commit_only=`git-ls-files --error-unmatch -- \"$@\"`\n> > +\t */\n> > +\n> > +\t/*\n> > +\t * FIXME: shell script does\n> > +\t *\n> > +\t *   git-read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n> > +\t *\n> > +\t * which warns about unmerged files in the index.\n> > +\t */\n> > +\n> > +\t/* update the user index file */\n> > +\tadd_files_to_cache(fd, files, prefix);\n> \n> I suspect this, or ...\n> \n> > +\n> > +\tif (!initial_commit) {\n> > +\t\ttree = parse_tree_indirect(head_sha1);\n> > +\t\tif (!tree)\n> > +\t\t\tdie(\"failed to unpack HEAD tree object\");\n> > +\t\tif (read_tree(tree, 0, NULL))\n> > +\t\t\tdie(\"failed to read HEAD tree object\");\n> > +\t}\n> > +\n> > +\t/* Uh oh, abusing lock_file to create a garbage collected file */\n> > +\tnext_index_lock = xmalloc(sizeof(*next_index_lock));\n> > +\tfd = hold_lock_file_for_update(next_index_lock,\n> > +\t\t\t\t       git_path(\"next-index-%d\", getpid()), 1);\n> > +\tadd_files_to_cache(fd, files, prefix);\n> \n> ... this, but not both.\n\nNo, this needs both.  The first add_files_to_cache() call updates the\nuser index (.git/index) by adding the given files, then we build a\ntemporary index from a tree and add the files to that index.\n\n> \n> > +/* Find out if the message starting at position 'start' in the strbuf\n> > + * contains only whitespace and Signed-off-by lines. */\n> > +static int message_is_empty(struct strbuf *sb, int start)\n> > +{\n> > +\tstatic const char signed_off_by[] = \"Signed-off-by: \";\n> \n> I think you already defined that globally earlier.\n\nAh, yes, fixed.\n\n> In the function message_is_empty() you write:\n> \n> > +\t/* See if the template is just a prefix of the message. */\n> > +\tstrbuf_init(&tmpl);\n> > +\tif (template_file && strbuf_read_path(&tmpl, template_file) > 0) {\n> > +\t\tstripspace(&tmpl, 1);\n> > +\t\tif (start + tmpl.len <= sb->len &&\n> > +\t\t    memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)\n> > +\t\t\tstart += tmpl.len;\n> \n> Could we not bail out here, if there is no match?  In that case, the \n> message is clearly not empty...\n\nThe contents could be just sign-off-by's.\n\n> > +\t/* Check if the rest is just whitespace and Signed-of-by's. */\n> > +\tfor (i = start; i < sb->len; i++) {\n> > +\t\tnl = memchr(sb->buf + i, '\\n', sb->len - i);\n> > +\t\tif (nl)\n> > +\t\t\teol = nl - sb->buf;\n> > +\t\telse\n> > +\t\t\teol = sb->len;\n> \n> Why not just \"if (isspace(sb->buf[i]) || sb->buf[i] == '\\n') continue;\"? \n> This would also catch the cases where people indent their S-O-Bs.\n> \n> > +\n> > +\t\tif (strlen(signed_off_by) <= eol - i &&\n> > +\t\t    !prefixcmp(sb->buf + i, signed_off_by)) {\n> > +\t\t\ti = eol;\n> > +\t\t\tcontinue;\n> > +\t\t}\n> > +\t\twhile (i < eol)\n> > +\t\t\tif (!isspace(sb->buf[i++]))\n> > +\t\t\t\treturn 0;\n> > +\t}\n> > +\n> > +\treturn 1;\n> > +}\n> \n> I did not review the rest of the code closely yet...\n\nI'm sending an updated version against Pierre's strbuf changes now.\nIt's a smaller patch set, so hopefully we can get it in soon.\n\nKristian\n"},{"id":"53363","messageId":"1190069981.10112.12.camel@hinata.boston.redhat.com","threadId":"9792","inReplyTo":"Pine.LNX.4.64.0709061732480.28586@racer.site","subject":"Re: [PATCH 6/9] Rewrite launch_editor, create_tag and stripspace to use strbufs.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-17T22:59:41Z","receivedAt":"2007-09-17T22:59:41Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2007-09-06 at 17:38 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> \n> > diff --git a/strbuf.c b/strbuf.c\n> > index fcfc05e..ed2afea 100644\n> > --- a/strbuf.c\n> > +++ b/strbuf.c\n> > @@ -73,43 +74,15 @@ void strbuf_printf(struct strbuf *sb, const char *fmt, ...)\n> >  {\n> >  \tchar buffer[2048];\n> >  \tva_list args;\n> > -\tint len, size = 2 * sizeof buffer;\n> > +\tint len;\n> >  \n> >  \tva_start(args, fmt);\n> >  \tlen = vsnprintf(buffer, sizeof(buffer), fmt, args);\n> >  \tva_end(args);\n> >  \n> > -\tif (len > sizeof(buffer)) {\n> > -\t\t/*\n> > -\t\t * Didn't fit in the buffer, but this vsnprintf at\n> > -\t\t * least gives us the required length back.  Grow the\n> > -\t\t * buffer acccordingly and try again.\n> > -\t\t */\n> > -\t\tstrbuf_grow(sb, len);\n> > -\t\tva_start(args, fmt);\n> > -\t\tlen = vsnprintf(sb->buf + sb->len,\n> > -\t\t\t\tsb->alloc - sb->len, fmt, args);\n> > -\t\tva_end(args);\n> > -\t} else if (len >= 0) {\n> > -\t\t/*\n> > -\t\t * The initial vsnprintf fit in the temp buffer, just\n> > -\t\t * copy it to the strbuf.\n> > -\t\t */\n> > -\t\tstrbuf_add(sb, buffer, len);\n> > -\t} else {\n> > -\t\t/*\n> > -\t\t * This vnsprintf sucks and just returns -1 when the\n> > -\t\t * buffer is too small.  Keep doubling the size until\n> > -\t\t * it fits.\n> > -\t\t */\n> > -\t\twhile (len < 0) {\n> > -\t\t\tstrbuf_grow(sb, size);\n> > -\t\t\tva_start(args, fmt);\n> > -\t\t\tlen = vsnprintf(sb->buf + sb->len,\n> > -\t\t\t\t\tsb->alloc - sb->len, fmt, args);\n> > -\t\t\tva_end(args);\n> > -\t\t\tsize *= 2;\n> > -\t\t}\n> > -\t}\n> > +\tif (len > sizeof(buffer) || len < 0)\n> > +\t\tdie(\"out of buffer space\\n\");\n> > +\n> > +\tstrbuf_add(sb, buffer, len);\n> >  }\n> \n> Really?\n> \n> (If you find the time, it would be really nice to rebase that patch series \n> on top of Pierre's strbuf work...)\n\nArgh, this was a screwup when I edited the patch series.  The next\nseries is based on Pierres changes.\n\nKristian\n"},{"id":"53365","messageId":"1190070792.10112.15.camel@hinata.boston.redhat.com","threadId":"9792","inReplyTo":"Pine.LNX.4.64.0709061729270.28586@racer.site","subject":"Re: [PATCH 4/9] Introduce entry point for launching add--interactive.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-17T23:13:12Z","receivedAt":"2007-09-17T23:13:12Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2007-09-06 at 17:31 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> \n> > diff --git a/builtin-add.c b/builtin-add.c\n> > index 3dd4ded..e79e8f7 100644\n> > --- a/builtin-add.c\n> > +++ b/builtin-add.c\n> > @@ -153,6 +154,13 @@ static int git_add_config(const char *var, const char *value)\n> >  \treturn git_default_config(var, value);\n> >  }\n> >  \n> > +int interactive_add(void)\n> > +{\n> > +\tconst char *argv[2] = { \"add--interactive\", NULL };\n> > +\n> > +\treturn run_command_v_opt(argv, RUN_GIT_CMD);\n> > +}\n> \n> I'd rather have this in builtin-commit.c, since it is quite funny if \n> builtin-add.c has code to fork() and exec() itself (eventually, that \n> is) ;-)\n\nHuh... it ends up in the same binary, and interactive_add() sounds like\nit should live in builtin-add.c rather than builtin-commit.c.  Either\nway, I don't care too much, but can we fix it up later?\n\n> > diff --git a/commit.h b/commit.h\n> > index 467872e..64e1d4b 100644\n> > --- a/commit.h\n> > +++ b/commit.h\n> > @@ -122,4 +122,13 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,\n> >  \t\tint depth, int shallow_flag, int not_shallow_flag);\n> >  \n> >  int in_merge_bases(struct commit *, struct commit **, int);\n> > +\n> > +extern const unsigned char *\n> > +create_commit(const unsigned char *tree_sha1,\n> > +\t      unsigned char parent_sha1[][20], int parents,\n> > +\t      const char *author_info, const char *committer_info,\n> > +\t      const char *message, int length);\n> > +\n> > +extern int interactive_add(void);\n> > +\n> \n> Just a guess: you did not want create_commit() to creep in here, right?\n\nYeah, that was another oversight, fixed in the next series.\n\nKristian\n"},{"id":"53366","messageId":"Pine.LNX.4.64.0709180012420.28586@racer.site","threadId":"9792","inReplyTo":"1190069881.10112.10.camel@hinata.boston.redhat.com","subject":"Re: [PATCH 9/9] Implement git commit as a builtin command.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-17T23:16:20Z","receivedAt":"2007-09-17T23:16:20Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 17 Sep 2007, Kristian H?gsberg wrote:\n\n> On Thu, 2007-09-06 at 17:59 +0100, Johannes Schindelin wrote:\n> > \n> > On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> > \n> > > -\tbuiltin-runstatus.o \\\n> > \n> > Better keep it; some people's scripts could depend on it.\n> \n> Seriously?  Why don't we remove it and see if somebody yells?  It's more \n> of an implementation detail than most other git commands; if you need \n> status output in your script why wouldn't you just run git status?\n\ngit status is deemed porcelain.\n\nYes, we recently converted a few things to use \"git log\", which is \nporcelain, too, and I was not happy...\n\nBut then, you're right, we could just go and break peoples' scripts, if \nthey indeed did not use \"git diff\" directly.\n\n> > > +struct option {\n> > > +    enum option_type type;\n> > > +    const char *long_name;\n> > > +    char short_name;\n> > > +    void *value;\n> > > +};\n> > > +\n> > > +static int scan_options(const char ***argv, struct option *options)\n> > > +{\n> > \n> > I would not (no longer, anyway) be opposed to replacing the option parsing \n> > in git with getopt(); I hear that it is small enough to keep a copy in \n> > compat/getopt.c.\n> > \n> > But let's go forward with builtin-commit; getopt() can come later.\n> \n> I don't know.  I think it's a situation much like the string library \n> discussion.  It's a small enough dependency (70 lines!) that there's no \n> gain in depending on an external implementation, and we can tailor it to \n> gits needs as we extend the use within git.  And we can call it gitopt!\n\nHm.  I liked the semantics of getopt better, but what the heck.\n\n> I'm sending an updated version against Pierre's strbuf changes now. It's \n> a smaller patch set, so hopefully we can get it in soon.\n\nYes, that would be good.\n\nThanks,\nDscho\n"},{"id":"53368","messageId":"Pine.LNX.4.64.0709180027100.28586@racer.site","threadId":"9792","inReplyTo":"1190070792.10112.15.camel@hinata.boston.redhat.com","subject":"Re: [PATCH 4/9] Introduce entry point for launching add--interactive.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-17T23:27:54Z","receivedAt":"2007-09-17T23:27:54Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 17 Sep 2007, Kristian H?gsberg wrote:\n\n> On Thu, 2007-09-06 at 17:31 +0100, Johannes Schindelin wrote:\n> > \n> > On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> > \n> > > diff --git a/builtin-add.c b/builtin-add.c\n> > > index 3dd4ded..e79e8f7 100644\n> > > --- a/builtin-add.c\n> > > +++ b/builtin-add.c\n> > > @@ -153,6 +154,13 @@ static int git_add_config(const char *var, const char *value)\n> > >  \treturn git_default_config(var, value);\n> > >  }\n> > >  \n> > > +int interactive_add(void)\n> > > +{\n> > > +\tconst char *argv[2] = { \"add--interactive\", NULL };\n> > > +\n> > > +\treturn run_command_v_opt(argv, RUN_GIT_CMD);\n> > > +}\n> > \n> > I'd rather have this in builtin-commit.c, since it is quite funny if \n> > builtin-add.c has code to fork() and exec() itself (eventually, that \n> > is) ;-)\n> \n> Huh... it ends up in the same binary, and interactive_add() sounds like \n> it should live in builtin-add.c rather than builtin-commit.c.  Either \n> way, I don't care too much, but can we fix it up later?\n\nWell, you are probably right on the former, and therefore we do not have \nto do the latter.\n\nThanks,\nDscho\n"},{"id":"53369","messageId":"1190071825.10112.19.camel@hinata.boston.redhat.com","threadId":"9792","inReplyTo":"Pine.LNX.4.64.0709061726010.28586@racer.site","subject":"Re: [PATCH 1/9] Enable wt-status output to a given FILE pointer.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-17T23:30:25Z","receivedAt":"2007-09-17T23:30:25Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2007-09-06 at 17:27 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 5 Sep 2007, Kristian Høgsberg wrote:\n> \n> > Still defaults to stdout, but you can now override wt_status.fp after \n> > calling wt_status_prepare().\n> \n> Would it not be easier to freopen(filename, \"a\", stdout)?\n\nIt's probably easier, but I think this is cleaner and the patch isn't\nthat big.  I don't want to worry about the side effects of freopening\nstdout...\n\nKristian\n"},{"id":"53372","messageId":"20070917235645.GG24342@sigill.intra.peff.net","threadId":"9792","inReplyTo":"1190069881.10112.10.camel@hinata.boston.redhat.com","subject":"Re: [PATCH 9/9] Implement git commit as a builtin command.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-09-17T23:56:45Z","receivedAt":"2007-09-17T23:56:45Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 17, 2007 at 06:58:01PM -0400, Kristian Høgsberg wrote:\n\n> > > -\tbuiltin-runstatus.o \\\n> > \n> > Better keep it; some people's scripts could depend on it.\n> \n> Seriously?  Why don't we remove it and see if somebody yells?  It's more\n> of an implementation detail than most other git commands; if you need\n> status output in your script why wouldn't you just run git status?\n\nAs the author of builtin-runstatus, I had always intended that it was a\ntemporary part of the transition to a C git-commit, and would go away\nthen. But I see in the interim somebody documented it.  It should\nperhaps have been called git-status--helper, and the documentation\nshould have read \"DO NOT USE THIS.\"\n\nSo certainly my intent was for it to go away, but whether it has become\nsomething else is perhaps up to others to judge.\n\n-Peff\n"},{"id":"53380","messageId":"1190074285.10112.25.camel@hinata.boston.redhat.com","threadId":"9792","inReplyTo":"20070917235645.GG24342@sigill.intra.peff.net","subject":"Re: [PATCH 9/9] Implement git commit as a builtin command.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-09-18T00:11:25Z","receivedAt":"2007-09-18T00:11:25Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"\nOn Mon, 2007-09-17 at 19:56 -0400, Jeff King wrote:\n> On Mon, Sep 17, 2007 at 06:58:01PM -0400, Kristian Høgsberg wrote:\n> \n> > > > -\tbuiltin-runstatus.o \\\n> > > \n> > > Better keep it; some people's scripts could depend on it.\n> > \n> > Seriously?  Why don't we remove it and see if somebody yells?  It's more\n> > of an implementation detail than most other git commands; if you need\n> > status output in your script why wouldn't you just run git status?\n> \n> As the author of builtin-runstatus, I had always intended that it was a\n> temporary part of the transition to a C git-commit, and would go away\n> then. But I see in the interim somebody documented it.  It should\n> perhaps have been called git-status--helper, and the documentation\n> should have read \"DO NOT USE THIS.\"\n\nThat's what I suspected, thanks for clearing that up.  It definitely\nfeels more like a step towards a built-in commit than a useful command\non it's own.  It plugs right into this work, so as such, it's been a\nsuccess.\n\nKristian\n"}]}