Merge branch 'sb/format-patch-patchname'
* 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()
This commit is contained in:
131
builtin-log.c
131
builtin-log.c
@ -417,13 +417,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;
|
||||
@ -523,92 +516,33 @@ static int git_format_config(const char *var, const char *value, void *cb)
|
||||
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 +612,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;
|
||||
@ -689,21 +622,41 @@ 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;
|
||||
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,
|
||||
free(commit->buffer);
|
||||
free(commit);
|
||||
}
|
||||
|
||||
log_write_email_headers(rev, head, &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);
|
||||
@ -1067,6 +1020,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");
|
||||
@ -1115,9 +1070,9 @@ 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))
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user