Tentative built-in format-patch.
authorJunio C Hamano <junkio@cox.net>
Tue, 18 Apr 2006 23:45:27 +0000 (16:45 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 18 Apr 2006 23:45:27 +0000 (16:45 -0700)
This only does --stdout right now. To write into separate files
with pretty-printed filenames like the real thing does, it needs
a bit mroe work.

Signed-off-by: Junio C Hamano <junkio@cox.net>
commit.c
commit.h
git.c
log-tree.c
index 2717dd81c346d89bf5d6727e3aa1f5b65ff39aca..af747bde61d8330716e77a4a6db2839d9f8b59c5 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -36,6 +36,8 @@ enum cmit_fmt get_commit_format(const char *arg)
                return CMIT_FMT_FULL;
        if (!strcmp(arg, "=fuller"))
                return CMIT_FMT_FULLER;
+       if (!strcmp(arg, "=email"))
+               return CMIT_FMT_EMAIL;
        if (!strcmp(arg, "=oneline"))
                return CMIT_FMT_ONELINE;
        die("invalid --pretty format");
@@ -428,6 +430,10 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
        time = strtoul(date, &date, 10);
        tz = strtol(date, NULL, 10);
 
+       if (fmt == CMIT_FMT_EMAIL) {
+               what = "From";
+               filler = "";
+       }
        ret = sprintf(buf, "%s: %.*s%.*s\n", what,
                      (fmt == CMIT_FMT_FULLER) ? 4 : 0,
                      filler, namelen, line);
@@ -435,6 +441,9 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
        case CMIT_FMT_MEDIUM:
                ret += sprintf(buf + ret, "Date:   %s\n", show_date(time, tz));
                break;
+       case CMIT_FMT_EMAIL:
+               ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz));
+               break;
        case CMIT_FMT_FULLER:
                ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz));
                break;
@@ -445,10 +454,12 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
        return ret;
 }
 
-static int is_empty_line(const char *line, int len)
+static int is_empty_line(const char *line, int *len_p)
 {
+       int len = *len_p;
        while (len && isspace(line[len-1]))
                len--;
+       *len_p = len;
        return !len;
 }
 
@@ -457,7 +468,8 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com
        struct commit_list *parent = commit->parents;
        int offset;
 
-       if ((fmt == CMIT_FMT_ONELINE) || !parent || !parent->next)
+       if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) ||
+           !parent || !parent->next)
                return 0;
 
        offset = sprintf(buf, "Merge:");
@@ -480,9 +492,15 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
 {
        int hdr = 1, body = 0;
        unsigned long offset = 0;
-       int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4;
+       int indent = 4;
        int parents_shown = 0;
        const char *msg = commit->buffer;
+       const char *subject = NULL;
+
+       if (fmt == CMIT_FMT_EMAIL)
+               subject = "Subject: ";
+       if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
+               indent = 0;
 
        for (;;) {
                const char *line = msg;
@@ -506,7 +524,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
                if (hdr) {
                        if (linelen == 1) {
                                hdr = 0;
-                               if (fmt != CMIT_FMT_ONELINE)
+                               if ((fmt != CMIT_FMT_ONELINE) && !subject)
                                        buf[offset++] = '\n';
                                continue;
                        }
@@ -544,20 +562,28 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
                        continue;
                }
 
-               if (is_empty_line(line, linelen)) {
+               if (is_empty_line(line, &linelen)) {
                        if (!body)
                                continue;
+                       if (subject)
+                               continue;
                        if (fmt == CMIT_FMT_SHORT)
                                break;
                } else {
                        body = 1;
                }
 
+               if (subject) {
+                       memcpy(buf + offset, subject, 9);
+                       offset += 9;
+               }
                memset(buf + offset, ' ', indent);
                memcpy(buf + offset + indent, line, linelen);
                offset += linelen + indent;
+               buf[offset++] = '\n';
                if (fmt == CMIT_FMT_ONELINE)
                        break;
+               subject = NULL;
        }
        while (offset && isspace(buf[offset-1]))
                offset--;
index de142afe733a6ecd3bcec2abd9f71a358b4ae09d..01eec60a1ecc2ff3c73850cb510ba71767e47e03 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -45,6 +45,7 @@ enum cmit_fmt {
        CMIT_FMT_FULL,
        CMIT_FMT_FULLER,
        CMIT_FMT_ONELINE,
+       CMIT_FMT_EMAIL,
 
        CMIT_FMT_UNSPECIFIED,
 };
diff --git a/git.c b/git.c
index 0be14bb487414153d76919f1f36ed78e899042c1..0c40773a87b81b123b7ef3053dfd59f836b96a04 100644 (file)
--- a/git.c
+++ b/git.c
@@ -276,6 +276,43 @@ static int cmd_help(int argc, const char **argv, char **envp)
        return 0;
 }
 
+static int cmd_format_patch(int argc, const char **argv, char **envp)
+{
+       struct commit *commit;
+       struct commit **list = NULL;
+       struct rev_info rev;
+       int nr = 0;
+
+       init_revisions(&rev);
+       rev.commit_format = CMIT_FMT_EMAIL;
+       rev.verbose_header = 1;
+       rev.diff = 1;
+       rev.diffopt.with_raw = 0;
+       rev.diffopt.with_stat = 1;
+       rev.combine_merges = 0;
+       rev.ignore_merges = 1;
+       rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+       argc = setup_revisions(argc, argv, &rev, "HEAD");
+
+       prepare_revision_walk(&rev);
+       while ((commit = get_revision(&rev)) != NULL) {
+               nr++;
+               list = realloc(list, nr * sizeof(list[0]));
+               list[nr - 1] = commit;
+       }
+       while (0 <= --nr) {
+               int shown;
+               commit = list[nr];
+               shown = log_tree_commit(&rev, commit);
+               free(commit->buffer);
+               commit->buffer = NULL;
+               if (shown)
+                       printf("-- \n%s\n\n", GIT_VERSION);
+       }
+       free(list);
+       return 0;
+}
+
 static int cmd_log_wc(int argc, const char **argv, char **envp,
                      struct rev_info *rev)
 {
@@ -348,6 +385,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "log", cmd_log },
                { "whatchanged", cmd_wc },
                { "show", cmd_show },
+               { "format-patch", cmd_format_patch },
        };
        int i;
 
index 9634c4677f84e7d88965b47b5af32f23668b2142..aaf2b9423f01243584e15e6c93007a3f42c9d917 100644 (file)
@@ -37,12 +37,20 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
        /*
         * Print header line of header..
         */
-       printf("%s%s",
-               opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
-               diff_unique_abbrev(commit->object.sha1, abbrev_commit));
-       if (parent) 
-               printf(" (from %s)", diff_unique_abbrev(parent->object.sha1, abbrev_commit));
-       putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
+
+       if (opt->commit_format == CMIT_FMT_EMAIL)
+               printf("From %s  Thu Apr 7 15:13:13 2005\n",
+                      sha1_to_hex(commit->object.sha1));
+       else {
+               printf("%s%s",
+                      opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
+                      diff_unique_abbrev(commit->object.sha1, abbrev_commit));
+               if (parent) 
+                       printf(" (from %s)",
+                              diff_unique_abbrev(parent->object.sha1,
+                                                 abbrev_commit));
+               putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
+       }
 
        /*
         * And then the pretty-printed message itself
@@ -152,15 +160,18 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
 int log_tree_commit(struct rev_info *opt, struct commit *commit)
 {
        struct log_info log;
+       int shown;
 
        log.commit = commit;
        log.parent = NULL;
        opt->loginfo = &log;
 
-       if (!log_tree_diff(opt, commit, &log) && opt->loginfo && opt->always_show_header) {
+       shown = log_tree_diff(opt, commit, &log);
+       if (!shown && opt->loginfo && opt->always_show_header) {
                log.parent = NULL;
                show_log(opt, opt->loginfo, "");
+               shown = 1;
        }
        opt->loginfo = NULL;
-       return 0;
+       return shown;
 }