From 6df514af9dfb44f104baa9b581e91de22af89b8d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 22 Mar 2009 19:14:02 -0700 Subject: format-patch: construct patch filename in one function reopen_stdout() usually takes the oneline subject of a commit, appends the patch suffix, prepends the output directory (if any) and then reopens stdout as the resulting file. Now the patch filename (the oneline subject and the patch suffix) is created in get_patch_filename() and passed to reopen_stdout() which prepends the output directory and reopens stdout as that file. The original function to get the oneline description, get_oneline_for_filename(), has been renamed to get_patch_filename() to reflect its new functionality. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 98 ++++++++++++++++++++--------------------------------------- 1 file changed, 33 insertions(+), 65 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index c7a5772594..193de3ff2e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -419,12 +419,6 @@ int cmd_log(int argc, const char **argv, const char *prefix) /* 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; static int auto_number = 1; @@ -519,61 +513,33 @@ static int git_format_config(const char *var, const char *value, void *cb) } -static const char *get_oneline_for_filename(struct commit *commit, - int keep_subject) +static void get_patch_filename(struct commit *commit, int nr, + const char *suffix, struct strbuf *buf) { - 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; - } - } + int suffix_len = strlen(suffix) + 1; + int start_len = buf->len; - 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'; + strbuf_addf(buf, commit ? "%04d-" : "%d", nr); + if (commit) { + format_commit_message(commit, "%f", buf, DATE_NORMAL); + /* + * Replace characters at the end with the suffix if the + * filename is too long + */ + if (buf->len + suffix_len > FORMAT_PATCH_NAME_MAX + start_len) + strbuf_splice(buf, + start_len + FORMAT_PATCH_NAME_MAX - suffix_len, + suffix_len, suffix, suffix_len); + else + strbuf_addstr(buf, suffix); } - 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(const char *oneline, struct rev_info *rev) { char filename[PATH_MAX]; int len = 0; @@ -589,14 +555,7 @@ static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev) filename[len++] = '/'; } - 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); - } + strncpy(filename + len, oneline, PATH_MAX - len); if (!DIFF_OPT_TST(&rev->diffopt, QUIET)) fprintf(realstdout, "%s\n", filename + outdir_offset); @@ -684,12 +643,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, const char *encoding = "utf-8"; struct diff_options opts; int need_8bit_cte = 0; + char filename[PATH_MAX]; 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)) + if (numbered_files) + sprintf(filename, "0"); + else + sprintf(filename, "%04d-cover-letter%s", 0, fmt_patch_suffix); + + if (!use_stdout && reopen_stdout(filename, rev)) return; head_sha1 = sha1_to_hex(head->object.sha1); @@ -802,6 +766,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct patch_ids ids; char *add_signoff = NULL; struct strbuf buf = STRBUF_INIT; + struct strbuf patch_filename = STRBUF_INIT; git_config(git_format_config, NULL); init_revisions(&rev, prefix); @@ -1104,10 +1069,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } 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)) + + get_patch_filename(numbered_files ? NULL : commit, rev.nr, + fmt_patch_suffix, &patch_filename); + if (!use_stdout && reopen_stdout(patch_filename.buf, &rev)) die("Failed to create output files"); + strbuf_setlen(&patch_filename, 0); shown = log_tree_commit(&rev, commit); free(commit->buffer); commit->buffer = NULL; @@ -1131,6 +1098,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!use_stdout) fclose(stdout); } + strbuf_release(&patch_filename); free(list); if (ignore_if_in_upstream) free_patch_ids(&ids); -- cgit v1.2.1 From cd2ef591c8e753fe5295ac3c6f1dee481f00a185 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 22 Mar 2009 19:14:03 -0700 Subject: format-patch: pass a commit to reopen_stdout() We use the commit to generate the patch filename in reopen_stdout() before we redirect stdout. The cover letter codepath creates a dummy commit with the desired subject line 'cover letter'. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 67 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 193de3ff2e..6a27ce6958 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -539,30 +539,29 @@ static FILE *realstdout = NULL; static const char *output_directory = NULL; static int outdir_offset; -static int reopen_stdout(const char *oneline, 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, '/'); } - strncpy(filename + len, oneline, PATH_MAX - len); + 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; } @@ -643,26 +642,42 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, const char *encoding = "utf-8"; struct diff_options opts; int need_8bit_cte = 0; - char filename[PATH_MAX]; + struct commit *commit = NULL; if (rev->commit_format != CMIT_FMT_EMAIL) die("Cover letter needs email format"); - if (numbered_files) - sprintf(filename, "0"); - else - sprintf(filename, "%04d-cover-letter%s", 0, fmt_patch_suffix); + committer = git_committer_info(0); + head_sha1 = sha1_to_hex(head->object.sha1); - if (!use_stdout && reopen_stdout(filename, rev)) + 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", + head_sha1, committer, committer); + } + + if (!use_stdout && reopen_stdout(commit, rev)) return; - head_sha1 = sha1_to_hex(head->object.sha1); + if (commit) { + + free(commit->buffer); + free(commit); + } log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers, &need_8bit_cte); - committer = git_committer_info(0); - msg = body; pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822, encoding); @@ -766,7 +781,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct patch_ids ids; char *add_signoff = NULL; struct strbuf buf = STRBUF_INIT; - struct strbuf patch_filename = STRBUF_INIT; git_config(git_format_config, NULL); init_revisions(&rev, prefix); @@ -1070,11 +1084,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); } - get_patch_filename(numbered_files ? NULL : commit, rev.nr, - fmt_patch_suffix, &patch_filename); - if (!use_stdout && reopen_stdout(patch_filename.buf, &rev)) + if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit, + &rev)) die("Failed to create output files"); - strbuf_setlen(&patch_filename, 0); shown = log_tree_commit(&rev, commit); free(commit->buffer); commit->buffer = NULL; @@ -1098,7 +1110,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!use_stdout) fclose(stdout); } - strbuf_release(&patch_filename); free(list); if (ignore_if_in_upstream) free_patch_ids(&ids); -- cgit v1.2.1 From 6fa8e6278b210bfa56fcb54ed38d2b485350e7c6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 22 Mar 2009 19:14:04 -0700 Subject: format-patch: move get_patch_filename() into log-tree Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 6a27ce6958..4f438db4c1 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -417,7 +417,6 @@ int cmd_log(int argc, const char **argv, const char *prefix) } /* format-patch */ -#define FORMAT_PATCH_NAME_MAX 64 static const char *fmt_patch_suffix = ".patch"; static int numbered = 0; @@ -512,29 +511,6 @@ static int git_format_config(const char *var, const char *value, void *cb) return git_log_config(var, value, cb); } - -static void get_patch_filename(struct commit *commit, int nr, - const char *suffix, struct strbuf *buf) -{ - int suffix_len = strlen(suffix) + 1; - int start_len = buf->len; - - strbuf_addf(buf, commit ? "%04d-" : "%d", nr); - if (commit) { - format_commit_message(commit, "%f", buf, DATE_NORMAL); - /* - * Replace characters at the end with the suffix if the - * filename is too long - */ - if (buf->len + suffix_len > FORMAT_PATCH_NAME_MAX + start_len) - strbuf_splice(buf, - start_len + FORMAT_PATCH_NAME_MAX - suffix_len, - suffix_len, suffix, suffix_len); - else - strbuf_addstr(buf, suffix); - } -} - static FILE *realstdout = NULL; static const char *output_directory = NULL; static int outdir_offset; -- cgit v1.2.1 From 108dab2811701c20d6d6e8d9fe8af88e41d65d77 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 22 Mar 2009 19:14:05 -0700 Subject: format-patch: --attach/inline uses filename instead of SHA1 Currently when format-patch is used with --attach or --inline the patch attachment has the SHA1 of the commit for its filename. This replaces the SHA1 with the filename used by format-patch when outputting to files. Fix tests relying on the SHA1 output and add a test showing how the --suffix option affects the attachment filename output. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 4f438db4c1..3e3cbc11fd 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -607,7 +607,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, 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; @@ -624,7 +623,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, die("Cover letter needs email format"); committer = git_committer_info(0); - head_sha1 = sha1_to_hex(head->object.sha1); if (!numbered_files) { /* @@ -639,7 +637,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, "author %s\n" "committer %s\n\n" "cover letter\n", - head_sha1, committer, committer); + sha1_to_hex(head->object.sha1), committer, committer); } if (!use_stdout && reopen_stdout(commit, rev)) @@ -651,7 +649,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, free(commit); } - log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers, + log_write_email_headers(rev, head, &subject_start, &extra_headers, &need_8bit_cte); msg = body; @@ -1011,6 +1009,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) 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"); -- cgit v1.2.1