Code

Merge branch 'sb/format-patch-patchname'
authorJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:23 +0000 (00:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:23 +0000 (00:42 -0700)
* sb/format-patch-patchname:
  format_sanitized_subject: Don't trim past initial length of strbuf
  log-tree: fix patch filename computation in "git format-patch"
  format-patch: --numbered-files and --stdout aren't mutually exclusive
  format-patch: --attach/inline uses filename instead of SHA1
  format-patch: move get_patch_filename() into log-tree
  format-patch: pass a commit to reopen_stdout()
  format-patch: construct patch filename in one function
  pretty.c: add %f format specifier to format_commit_message()

1  2 
builtin-log.c
revision.h

diff --combined builtin-log.c
index eb2c0541b5ab833fb5c5f9b73eaa752d2e80e9d0,3e3cbc11fd80d3409a9e880c2307680e9701afb7..5eaec5d24e6ca70af2879ce9439eb2ba831211b6
@@@ -417,13 -417,6 +417,6 @@@ int cmd_log(int argc, const char **argv
  }
  
  /* format-patch */
- #define FORMAT_PATCH_NAME_MAX 64
- static int istitlechar(char c)
- {
-       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
-               (c >= '0' && c <= '9') || c == '.' || c == '_';
- }
  
  static const char *fmt_patch_suffix = ".patch";
  static int numbered = 0;
@@@ -465,7 -458,6 +458,7 @@@ static void add_header(const char *valu
  #define THREAD_SHALLOW 1
  #define THREAD_DEEP 2
  static int thread = 0;
 +static int do_signoff = 0;
  
  static int git_format_config(const char *var, const char *value, void *cb)
  {
                thread = git_config_bool(var, value) && THREAD_SHALLOW;
                return 0;
        }
 +      if (!strcmp(var, "format.signoff")) {
 +              do_signoff = git_config_bool(var, value);
 +              return 0;
 +      }
  
        return git_log_config(var, value, cb);
  }
  
- static const char *get_oneline_for_filename(struct commit *commit,
-                                           int keep_subject)
- {
-       static char filename[PATH_MAX];
-       char *sol;
-       int len = 0;
-       int suffix_len = strlen(fmt_patch_suffix) + 1;
-       sol = strstr(commit->buffer, "\n\n");
-       if (!sol)
-               filename[0] = '\0';
-       else {
-               int j, space = 0;
-               sol += 2;
-               /* strip [PATCH] or [PATCH blabla] */
-               if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
-                       char *eos = strchr(sol + 6, ']');
-                       if (eos) {
-                               while (isspace(*eos))
-                                       eos++;
-                               sol = eos;
-                       }
-               }
-               for (j = 0;
-                    j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&
-                            len < sizeof(filename) - suffix_len &&
-                            sol[j] && sol[j] != '\n';
-                    j++) {
-                       if (istitlechar(sol[j])) {
-                               if (space) {
-                                       filename[len++] = '-';
-                                       space = 0;
-                               }
-                               filename[len++] = sol[j];
-                               if (sol[j] == '.')
-                                       while (sol[j + 1] == '.')
-                                               j++;
-                       } else
-                               space = 1;
-               }
-               while (filename[len - 1] == '.'
-                      || filename[len - 1] == '-')
-                       len--;
-               filename[len] = '\0';
-       }
-       return filename;
- }
  static FILE *realstdout = NULL;
  static const char *output_directory = NULL;
  static int outdir_offset;
  
- static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)
+ static int reopen_stdout(struct commit *commit, struct rev_info *rev)
  {
-       char filename[PATH_MAX];
-       int len = 0;
+       struct strbuf filename = STRBUF_INIT;
        int suffix_len = strlen(fmt_patch_suffix) + 1;
  
        if (output_directory) {
-               len = snprintf(filename, sizeof(filename), "%s",
-                               output_directory);
-               if (len >=
-                   sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)
+               strbuf_addstr(&filename, output_directory);
+               if (filename.len >=
+                   PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
                        return error("name of output directory is too long");
-               if (filename[len - 1] != '/')
-                       filename[len++] = '/';
+               if (filename.buf[filename.len - 1] != '/')
+                       strbuf_addch(&filename, '/');
        }
  
-       if (!oneline)
-               len += sprintf(filename + len, "%d", nr);
-       else {
-               len += sprintf(filename + len, "%04d-", nr);
-               len += snprintf(filename + len, sizeof(filename) - len - 1
-                               - suffix_len, "%s", oneline);
-               strcpy(filename + len, fmt_patch_suffix);
-       }
+       get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
  
        if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
-               fprintf(realstdout, "%s\n", filename + outdir_offset);
+               fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
  
-       if (freopen(filename, "w", stdout) == NULL)
-               return error("Cannot open patch file %s",filename);
+       if (freopen(filename.buf, "w", stdout) == NULL)
+               return error("Cannot open patch file %s", filename.buf);
  
+       strbuf_release(&filename);
        return 0;
  }
  
@@@ -678,7 -607,6 +612,6 @@@ static void make_cover_letter(struct re
                              int nr, struct commit **list, struct commit *head)
  {
        const char *committer;
-       char *head_sha1;
        const char *subject_start = NULL;
        const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
        const char *msg;
        const char *encoding = "utf-8";
        struct diff_options opts;
        int need_8bit_cte = 0;
+       struct commit *commit = NULL;
  
        if (rev->commit_format != CMIT_FMT_EMAIL)
                die("Cover letter needs email format");
  
-       if (!use_stdout && reopen_stdout(numbered_files ?
-                               NULL : "cover-letter", 0, rev))
+       committer = git_committer_info(0);
+       if (!numbered_files) {
+               /*
+                * We fake a commit for the cover letter so we get the filename
+                * desired.
+                */
+               commit = xcalloc(1, sizeof(*commit));
+               commit->buffer = xmalloc(400);
+               snprintf(commit->buffer, 400,
+                       "tree 0000000000000000000000000000000000000000\n"
+                       "parent %s\n"
+                       "author %s\n"
+                       "committer %s\n\n"
+                       "cover letter\n",
+                       sha1_to_hex(head->object.sha1), committer, committer);
+       }
+       if (!use_stdout && reopen_stdout(commit, rev))
                return;
  
-       head_sha1 = sha1_to_hex(head->object.sha1);
+       if (commit) {
  
-       log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers,
-                               &need_8bit_cte);
+               free(commit->buffer);
+               free(commit);
+       }
  
-       committer = git_committer_info(0);
+       log_write_email_headers(rev, head, &subject_start, &extra_headers,
+                               &need_8bit_cte);
  
        msg = body;
        pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,
@@@ -870,7 -818,13 +823,7 @@@ int cmd_format_patch(int argc, const ch
                }
                else if (!strcmp(argv[i], "--signoff") ||
                         !strcmp(argv[i], "-s")) {
 -                      const char *committer;
 -                      const char *endpos;
 -                      committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
 -                      endpos = strchr(committer, '>');
 -                      if (!endpos)
 -                              die("bogus committer info %s", committer);
 -                      add_signoff = xmemdupz(committer, endpos - committer + 1);
 +                      do_signoff = 1;
                }
                else if (!strcmp(argv[i], "--attach")) {
                        rev.mime_boundary = git_version_string;
                        cover_letter = 1;
                else if (!strcmp(argv[i], "--no-binary"))
                        no_binary_diff = 1;
 +              else if (!prefixcmp(argv[i], "--add-header="))
 +                      add_header(argv[i] + 13);
                else
                        argv[j++] = argv[i];
        }
        argc = j;
  
 +      if (do_signoff) {
 +              const char *committer;
 +              const char *endpos;
 +              committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
 +              endpos = strchr(committer, '>');
 +              if (!endpos)
 +                      die("bogus committer info %s", committer);
 +              add_signoff = xmemdupz(committer, endpos - committer + 1);
 +      }
 +
        for (i = 0; i < extra_hdr_nr; i++) {
                strbuf_addstr(&buf, extra_hdr[i]);
                strbuf_addch(&buf, '\n');
                const char *msgid = clean_message_id(in_reply_to);
                string_list_append(msgid, rev.ref_message_ids);
        }
+       rev.numbered_files = numbered_files;
+       rev.patch_suffix = fmt_patch_suffix;
        if (cover_letter) {
                if (thread)
                        gen_message_id(&rev, "cover");
                        }
                        gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
                }
-               if (!use_stdout && reopen_stdout(numbered_files ? NULL :
-                               get_oneline_for_filename(commit, keep_subject),
-                               rev.nr, &rev))
+               if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,
+                                                &rev))
                        die("Failed to create output files");
                shown = log_tree_commit(&rev, commit);
                free(commit->buffer);
diff --combined revision.h
index 6e98b71b49a4db01761d45aa244424f2512c5a41,5259ed519272d49ad8a73e88eb6cb838f62cfd11..5adfc9140544429254bd67ff10504730c7424e1b
@@@ -50,6 -50,7 +50,6 @@@ struct rev_info 
                        edge_hint:1,
                        limited:1,
                        unpacked:1,
 -                      kept_pack_only:1,
                        boundary:2,
                        left_right:1,
                        rewrite_parents:1,
@@@ -85,6 -86,8 +85,8 @@@
        struct log_info *loginfo;
        int             nr, total;
        const char      *mime_boundary;
+       const char      *patch_suffix;
+       int             numbered_files;
        char            *message_id;
        struct string_list *ref_message_ids;
        const char      *add_signoff;