Merge branch 'jk/format-patch-number-singleton-patch-with-cover'
authorJunio C Hamano <gitster@pobox.com>
Fri, 9 Sep 2016 04:49:47 +0000 (21:49 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 9 Sep 2016 04:49:47 +0000 (21:49 -0700)
"git format-patch --cover-letter HEAD^" to format a single patch
with a separate cover letter now numbers the output as [PATCH 0/1]
and [PATCH 1/1] by default.

* jk/format-patch-number-singleton-patch-with-cover:
format-patch: show 0/1 and 1/1 for singleton patch with cover letter

1  2 
builtin/log.c
diff --combined builtin/log.c
index 92dc34dcb0cc54df27b99c91d08786b6c0d5b62a,b7bfeb9586e0b768a23a0ba81296cfddb04b57c7..49aa534f4a018aaaa650a9dc27718f8ed2f00c6e
@@@ -33,7 -33,6 +33,7 @@@ static const char *default_date_mode = 
  static int default_abbrev_commit;
  static int default_show_root = 1;
  static int default_follow;
 +static int default_show_signature;
  static int decoration_style;
  static int decoration_given;
  static int use_mailmap_config;
@@@ -120,7 -119,6 +120,7 @@@ static void cmd_log_init_defaults(struc
        rev->abbrev_commit = default_abbrev_commit;
        rev->show_root_diff = default_show_root;
        rev->subject_prefix = fmt_patch_subject_prefix;
 +      rev->show_signature = default_show_signature;
        DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
  
        if (default_date_mode)
@@@ -238,17 -236,16 +238,17 @@@ static void show_early_header(struct re
                if (rev->commit_format != CMIT_FMT_ONELINE)
                        putchar(rev->diffopt.line_termination);
        }
 -      printf(_("Final output: %d %s\n"), nr, stage);
 +      fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
  }
  
  static struct itimerval early_output_timer;
  
  static void log_show_early(struct rev_info *revs, struct commit_list *list)
  {
 -      int i = revs->early_output;
 +      int i = revs->early_output, close_file = revs->diffopt.close_file;
        int show_header = 1;
  
 +      revs->diffopt.close_file = 0;
        sort_in_topological_order(&list, revs->sort_order);
        while (list && i) {
                struct commit *commit = list->item;
                case commit_ignore:
                        break;
                case commit_error:
 +                      if (close_file)
 +                              fclose(revs->diffopt.file);
                        return;
                }
                list = list->next;
        }
  
        /* Did we already get enough commits for the early output? */
 -      if (!i)
 +      if (!i) {
 +              if (close_file)
 +                      fclose(revs->diffopt.file);
                return;
 +      }
  
        /*
         * ..if no, then repeat it twice a second until we
@@@ -339,7 -331,7 +339,7 @@@ static int cmd_log_walk(struct rev_inf
  {
        struct commit *commit;
        int saved_nrl = 0;
 -      int saved_dcctc = 0;
 +      int saved_dcctc = 0, close_file = rev->diffopt.close_file;
  
        if (rev->early_output)
                setup_early_output(rev);
         * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
         * retain that state information if replacing rev->diffopt in this loop
         */
 +      rev->diffopt.close_file = 0;
        while ((commit = get_revision(rev)) != NULL) {
                if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
                        /*
        }
        rev->diffopt.degraded_cc_to_c = saved_dcctc;
        rev->diffopt.needed_rename_limit = saved_nrl;
 +      if (close_file)
 +              fclose(rev->diffopt.file);
  
        if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
            DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
@@@ -420,10 -409,6 +420,10 @@@ static int git_log_config(const char *v
                use_mailmap_config = git_config_bool(var, value);
                return 0;
        }
 +      if (!strcmp(var, "log.showsignature")) {
 +              default_show_signature = git_config_bool(var, value);
 +              return 0;
 +      }
  
        if (grep_config(var, value, cb) < 0)
                return -1;
@@@ -460,7 -445,7 +460,7 @@@ static void show_tagger(char *buf, int 
        pp.fmt = rev->commit_format;
        pp.date_mode = rev->date_mode;
        pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
 -      printf("%s", out.buf);
 +      fprintf(rev->diffopt.file, "%s", out.buf);
        strbuf_release(&out);
  }
  
@@@ -471,7 -456,7 +471,7 @@@ static int show_blob_object(const unsig
        char *buf;
        unsigned long size;
  
 -      fflush(stdout);
 +      fflush(rev->diffopt.file);
        if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
            !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
                return stream_blob_to_fd(1, sha1, NULL, 0);
@@@ -511,7 -496,7 +511,7 @@@ static int show_tag_object(const unsign
        }
  
        if (offset < size)
 -              fwrite(buf + offset, size - offset, 1, stdout);
 +              fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
        free(buf);
        return 0;
  }
@@@ -520,8 -505,7 +520,8 @@@ static int show_tree_object(const unsig
                struct strbuf *base,
                const char *pathname, unsigned mode, int stage, void *context)
  {
 -      printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
 +      FILE *file = context;
 +      fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
        return 0;
  }
  
@@@ -581,7 -565,7 +581,7 @@@ int cmd_show(int argc, const char **arg
  
                        if (rev.shown_one)
                                putchar('\n');
 -                      printf("%stag %s%s\n",
 +                      fprintf(rev.diffopt.file, "%stag %s%s\n",
                                        diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        t->tag,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                case OBJ_TREE:
                        if (rev.shown_one)
                                putchar('\n');
 -                      printf("%stree %s%s\n\n",
 +                      fprintf(rev.diffopt.file, "%stree %s%s\n\n",
                                        diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
 -                                      show_tree_object, NULL);
 +                                      show_tree_object, rev.diffopt.file);
                        rev.shown_one = 1;
                        break;
                case OBJ_COMMIT:
@@@ -690,9 -674,9 +690,9 @@@ static int auto_number = 1
  
  static char *default_attach = NULL;
  
 -static struct string_list extra_hdr;
 -static struct string_list extra_to;
 -static struct string_list extra_cc;
 +static struct string_list extra_hdr = STRING_LIST_INIT_NODUP;
 +static struct string_list extra_to = STRING_LIST_INIT_NODUP;
 +static struct string_list extra_cc = STRING_LIST_INIT_NODUP;
  
  static void add_header(const char *value)
  {
  static int thread;
  static int do_signoff;
  static int base_auto;
 +static char *from;
  static const char *signature = git_version_string;
  static const char *signature_file;
  static int config_cover_letter;
@@@ -808,25 -791,15 +808,25 @@@ static int git_format_config(const cha
                base_auto = git_config_bool(var, value);
                return 0;
        }
 +      if (!strcmp(var, "format.from")) {
 +              int b = git_config_maybe_bool(var, value);
 +              free(from);
 +              if (b < 0)
 +                      from = xstrdup(value);
 +              else if (b)
 +                      from = xstrdup(git_committer_info(IDENT_NO_DATE));
 +              else
 +                      from = NULL;
 +              return 0;
 +      }
  
        return git_log_config(var, value, cb);
  }
  
 -static FILE *realstdout = NULL;
  static const char *output_directory = NULL;
  static int outdir_offset;
  
 -static int reopen_stdout(struct commit *commit, const char *subject,
 +static int open_next_file(struct commit *commit, const char *subject,
                         struct rev_info *rev, int quiet)
  {
        struct strbuf filename = STRBUF_INIT;
                fmt_output_subject(&filename, subject, rev);
  
        if (!quiet)
 -              fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
 +              printf("%s\n", filename.buf + outdir_offset);
  
 -      if (freopen(filename.buf, "w", stdout) == NULL)
 +      if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
                return error(_("Cannot open patch file %s"), filename.buf);
  
        strbuf_release(&filename);
@@@ -909,15 -882,15 +909,15 @@@ static void gen_message_id(struct rev_i
        info->message_id = strbuf_detach(&buf, NULL);
  }
  
 -static void print_signature(void)
 +static void print_signature(FILE *file)
  {
        if (!signature || !*signature)
                return;
  
 -      printf("-- \n%s", signature);
 +      fprintf(file, "-- \n%s", signature);
        if (signature[strlen(signature)-1] != '\n')
 -              putchar('\n');
 -      putchar('\n');
 +              putc('\n', file);
 +      putc('\n', file);
  }
  
  static void add_branch_description(struct strbuf *buf, const char *branch_name)
@@@ -980,13 -953,13 +980,13 @@@ static void make_cover_letter(struct re
        struct pretty_print_context pp = {0};
        struct commit *head = list[0];
  
 -      if (rev->commit_format != CMIT_FMT_EMAIL)
 +      if (!cmit_fmt_is_mail(rev->commit_format))
                die(_("Cover letter needs email format"));
  
        committer = git_committer_info(0);
  
        if (!use_stdout &&
 -          reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
 +          open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
                return;
  
        log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
        pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
        pp_remainder(&pp, &msg, &sb, 0);
        add_branch_description(&sb, branch_name);
 -      printf("%s\n", sb.buf);
 +      fprintf(rev->diffopt.file, "%s\n", sb.buf);
  
        strbuf_release(&sb);
  
        log.wrap = 72;
        log.in1 = 2;
        log.in2 = 4;
 +      log.file = rev->diffopt.file;
        for (i = 0; i < nr; i++)
                shortlog_add_commit(&log, list[i]);
  
        diffcore_std(&opts);
        diff_flush(&opts);
  
 -      printf("\n");
 -      print_signature();
 +      fprintf(rev->diffopt.file, "\n");
 +      print_signature(rev->diffopt.file);
  }
  
  static const char *clean_message_id(const char *msg_id)
@@@ -1343,7 -1315,7 +1343,7 @@@ static void prepare_bases(struct base_t
                struct object_id *patch_id;
                if (commit->util)
                        continue;
 -              if (commit_patch_id(commit, &diffopt, sha1))
 +              if (commit_patch_id(commit, &diffopt, sha1, 0))
                        die(_("cannot get patch id"));
                ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
                patch_id = bases->patch_id + bases->nr_patch_id;
        }
  }
  
 -static void print_bases(struct base_tree_info *bases)
 +static void print_bases(struct base_tree_info *bases, FILE *file)
  {
        int i;
  
                return;
  
        /* Show the base commit */
 -      printf("base-commit: %s\n", oid_to_hex(&bases->base_commit));
 +      fprintf(file, "base-commit: %s\n", oid_to_hex(&bases->base_commit));
  
        /* Show the prerequisite patches */
        for (i = bases->nr_patch_id - 1; i >= 0; i--)
 -              printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
 +              fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
  
        free(bases->patch_id);
        bases->nr_patch_id = 0;
@@@ -1396,6 -1368,7 +1396,6 @@@ int cmd_format_patch(int argc, const ch
        int quiet = 0;
        int reroll_count = -1;
        char *branch_name = NULL;
 -      char *from = NULL;
        char *base_commit = NULL;
        struct base_tree_info bases;
  
                setup_pager();
  
        if (output_directory) {
 +              if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
 +                      rev.diffopt.use_color = GIT_COLOR_NEVER;
                if (use_stdout)
                        die(_("standard output, or directory, which one?"));
                if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
                get_patch_ids(&rev, &ids);
        }
  
 -      if (!use_stdout)
 -              realstdout = xfdopen(xdup(1), "w");
 -
        if (prepare_revision_walk(&rev))
                die(_("revision walk setup failed"));
        rev.boundary = 1;
                /* nothing to do */
                return 0;
        total = nr;
-       if (!keep_subject && auto_number && total > 1)
-               numbered = 1;
-       if (numbered)
-               rev.total = total + start_number - 1;
        if (cover_letter == -1) {
                if (config_cover_letter == COVER_AUTO)
                        cover_letter = (total > 1);
                else
                        cover_letter = (config_cover_letter == COVER_ON);
        }
+       if (!keep_subject && auto_number && (total > 1 || cover_letter))
+               numbered = 1;
+       if (numbered)
+               rev.total = total + start_number - 1;
  
        if (!signature) {
                ; /* --no-signature inhibits all signatures */
                        gen_message_id(&rev, "cover");
                make_cover_letter(&rev, use_stdout,
                                  origin, nr, list, branch_name, quiet);
 -              print_bases(&bases);
 +              print_bases(&bases, rev.diffopt.file);
                total++;
                start_number--;
        }
                }
  
                if (!use_stdout &&
 -                  reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
 +                  open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
                        die(_("Failed to create output files"));
                shown = log_tree_commit(&rev, commit);
                free_commit_buffer(commit);
                        rev.shown_one = 0;
                if (shown) {
                        if (rev.mime_boundary)
 -                              printf("\n--%s%s--\n\n\n",
 +                              fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
                                       mime_boundary_leader,
                                       rev.mime_boundary);
                        else
 -                              print_signature();
 -                      print_bases(&bases);
 +                              print_signature(rev.diffopt.file);
 +                      print_bases(&bases, rev.diffopt.file);
                }
                if (!use_stdout)
 -                      fclose(stdout);
 +                      fclose(rev.diffopt.file);
        }
        free(list);
        free(branch_name);
@@@ -1820,15 -1794,15 +1820,15 @@@ static const char * const cherry_usage[
  };
  
  static void print_commit(char sign, struct commit *commit, int verbose,
 -                       int abbrev)
 +                       int abbrev, FILE *file)
  {
        if (!verbose) {
 -              printf("%c %s\n", sign,
 +              fprintf(file, "%c %s\n", sign,
                       find_unique_abbrev(commit->object.oid.hash, abbrev));
        } else {
                struct strbuf buf = STRBUF_INIT;
                pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
 -              printf("%c %s %s\n", sign,
 +              fprintf(file, "%c %s %s\n", sign,
                       find_unique_abbrev(commit->object.oid.hash, abbrev),
                       buf.buf);
                strbuf_release(&buf);
@@@ -1909,7 -1883,7 +1909,7 @@@ int cmd_cherry(int argc, const char **a
                commit = list->item;
                if (has_commit_patch_id(commit, &ids))
                        sign = '-';
 -              print_commit(sign, commit, verbose, abbrev);
 +              print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
                list = list->next;
        }