diff options
-rw-r--r-- | Documentation/git-format-patch.txt | 69 | ||||
-rw-r--r-- | builtin-log.c | 38 | ||||
-rw-r--r-- | log-tree.c | 43 | ||||
-rw-r--r-- | revision.h | 2 |
4 files changed, 113 insertions, 39 deletions
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 7cc7fafc1d..493cac22db 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -9,37 +9,46 @@ git-format-patch - Prepare patches for e-mail submission SYNOPSIS -------- [verse] -'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] [-s] [-c] - [--diff-options] <his> [<mine>] +'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] + [-s | --signoff] [--diff-options] [--start-number <n>] + <since>[..<until>] DESCRIPTION ----------- -Prepare each commit with its patch since <mine> head forked from -<his> head, one file per patch formatted to resemble UNIX mailbox -format, for e-mail submission or use with gitlink:git-am[1]. + +Prepare each commit between <since> and <until> with its patch in +one file per commit, formatted to resemble UNIX mailbox format. +If ..<until> is not specified, the head of the current working +tree is implied. + +The output of this command is convenient for e-mail submission or +for use with gitlink:git-am[1]. Each output file is numbered sequentially from 1, and uses the -first line of the commit message (massaged for pathname safety) -as the filename. +first line of the commit message (massaged for pathname safety) as +the filename. The names of the output files are printed to standard +output, unless the --stdout option is specified. -When -o is specified, output files are created in <dir>; otherwise -they are created in the current working directory. This option -is ignored if --stdout is specified. +If -o is specified, output files are created in <dir>. Otherwise +they are created in the current working directory. -When -n is specified, instead of "[PATCH] Subject", the first -line is formatted as "[PATCH N/M] Subject", unless you have only -one patch. +If -n is specified, instead of "[PATCH] Subject", the first line +is formatted as "[PATCH n/m] Subject". OPTIONS ------- -o|--output-directory <dir>:: Use <dir> to store the resulting files, instead of the - current working directory. + current working directory. This option is ignored if + --stdout is specified. -n|--numbered:: Name output in '[PATCH n/m]' format. +--start-number <n>:: + Start numbering the patches at <n> instead of 1. + -k|--keep-subject:: Do not strip/add '[PATCH]' from the first line of the commit log message. @@ -48,17 +57,9 @@ OPTIONS Add `Signed-off-by:` line to the commit message, using the committer identity of yourself. --c|--check:: - Display suspicious lines in the patch. The definition - of 'suspicious lines' is currently the lines that has - trailing whitespaces, and the lines whose indentation - has a SP character immediately followed by a TAB - character. - --stdout:: - This flag generates the mbox formatted output to the - standard output, instead of saving them into a file per - patch and implies --mbox. + Print all commits to the standard output in mbox format, + instead of creating a file for each one. --attach:: Create attachments instead of inlining patches. @@ -82,18 +83,18 @@ git-format-patch -k --stdout R1..R2 | git-am -3 -k:: cherry-pick them. git-format-patch origin:: - Extract commits the current branch accumulated since it - pulled from origin the last time in a patch form for - e-mail submission. + Extract all commits which are in the current branch but + not in the origin branch. For each commit a separate file + is created in the current directory. git-format-patch -M -B origin:: - The same as the previous one, except detect and handle - renames and complete rewrites intelligently to produce - renaming patch. A renaming patch reduces the amount of - text output, and generally makes it easier to review - it. Note that the "patch" program does not understand - renaming patch well, so use it only when you know the - recipient uses git to apply your patch. + The same as the previous one. Additionally, it detects + and handles renames and complete rewrites intelligently to + produce a renaming patch. A renaming patch reduces the + amount of text output, and generally makes it easier to + review it. Note that the "patch" program does not + understand renaming patches, so use it only when you know + the recipient uses git to apply your patch. See Also diff --git a/builtin-log.c b/builtin-log.c index db1912a05b..6612f4c2a8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -85,6 +85,23 @@ static int istitlechar(char c) (c >= '0' && c <= '9') || c == '.' || c == '_'; } +static char *extra_headers = NULL; +static int extra_headers_size = 0; + +static int git_format_config(const char *var, const char *value) +{ + if (!strcmp(var, "format.headers")) { + int len = strlen(value); + extra_headers_size += len + 1; + extra_headers = realloc(extra_headers, extra_headers_size); + extra_headers[extra_headers_size - len - 1] = 0; + strcat(extra_headers, value); + return 0; + } + return git_default_config(var, value); +} + + static FILE *realstdout = NULL; static char *output_directory = NULL; @@ -150,6 +167,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp) int numbered = 0; int start_number = -1; int keep_subject = 0; + char *add_signoff = NULL; init_revisions(&rev); rev.commit_format = CMIT_FMT_EMAIL; @@ -161,6 +179,9 @@ int cmd_format_patch(int argc, const char **argv, char **envp) rev.ignore_merges = 1; rev.diffopt.output_format = DIFF_FORMAT_PATCH; + git_config(git_format_config); + rev.extra_headers = extra_headers; + /* * Parse the arguments before setup_revisions(), or something * like "git fmt-patch -o a123 HEAD^.." may fail; a123 is @@ -179,11 +200,13 @@ int cmd_format_patch(int argc, const char **argv, char **envp) if (i == argc) die("Need a number for --start-number"); start_number = strtol(argv[i], NULL, 10); - } else if (!strcmp(argv[i], "-k") || + } + else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keep-subject")) { keep_subject = 1; rev.total = -1; - } else if (!strcmp(argv[i], "-o")) { + } + else if (!strcmp(argv[i], "-o")) { if (argc < 3) die ("Which directory?"); if (mkdir(argv[i + 1], 0777) < 0 && errno != EEXIST) @@ -192,6 +215,16 @@ int cmd_format_patch(int argc, const char **argv, char **envp) output_directory = strdup(argv[i + 1]); i++; } + else if (!strcmp(argv[i], "--signoff") || + !strcmp(argv[i], "-s")) { + const char *committer = git_committer_info(1); + const char *endpos = strchr(committer, '>'); + if (!endpos) + die("bogos committer info %s\n", committer); + add_signoff = xmalloc(endpos - committer + 2); + memcpy(add_signoff, committer, endpos - committer + 1); + add_signoff[endpos - committer + 1] = 0; + } else if (!strcmp(argv[i], "--attach")) rev.mime_boundary = git_version_string; else if (!strncmp(argv[i], "--attach=", 9)) @@ -230,6 +263,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp) total = nr; if (numbered) rev.total = total + start_number - 1; + rev.add_signoff = add_signoff; while (0 <= --nr) { int shown; commit = list[nr]; diff --git a/log-tree.c b/log-tree.c index 58b016378c..ebb49f2970 100644 --- a/log-tree.c +++ b/log-tree.c @@ -12,6 +12,37 @@ static void show_parents(struct commit *commit, int abbrev) } } +static int append_signoff(char *buf, int buf_sz, int at, const char *signoff) +{ + int signoff_len = strlen(signoff); + static const char signed_off_by[] = "Signed-off-by: "; + char *cp = buf; + + /* Do we have enough space to add it? */ + if (buf_sz - at <= strlen(signed_off_by) + signoff_len + 2) + return at; + + /* First see if we already have the sign-off by the signer */ + while (1) { + cp = strstr(cp, signed_off_by); + if (!cp) + break; + cp += strlen(signed_off_by); + if ((cp + signoff_len < buf + at) && + !strncmp(cp, signoff, signoff_len) && + isspace(cp[signoff_len])) + return at; /* we already have him */ + } + + strcpy(buf + at, signed_off_by); + at += strlen(signed_off_by); + strcpy(buf + at, signoff); + at += signoff_len; + buf[at++] = '\n'; + buf[at] = 0; + return at; +} + void show_log(struct rev_info *opt, struct log_info *log, const char *sep) { static char this_header[16384]; @@ -20,7 +51,7 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep) int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40; const char *extra; int len; - char *subject = NULL, *after_subject = NULL; + const char *subject = NULL, *extra_headers = opt->extra_headers; opt->loginfo = NULL; if (!opt->verbose_header) { @@ -69,6 +100,7 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep) static char subject_buffer[1024]; static char buffer[1024]; snprintf(subject_buffer, sizeof(subject_buffer) - 1, + "%s" "MIME-Version: 1.0\n" "Content-Type: multipart/mixed;\n" " boundary=\"%s%s\"\n" @@ -79,9 +111,10 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep) "Content-Type: text/plain; " "charset=UTF-8; format=fixed\n" "Content-Transfer-Encoding: 8bit\n\n", + extra_headers ? extra_headers : "", mime_boundary_leader, opt->mime_boundary, mime_boundary_leader, opt->mime_boundary); - after_subject = subject_buffer; + extra_headers = subject_buffer; snprintf(buffer, sizeof(buffer) - 1, "--%s%s\n" @@ -110,7 +143,11 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep) /* * And then the pretty-printed message itself */ - len = pretty_print_commit(opt->commit_format, commit, ~0u, this_header, sizeof(this_header), abbrev, subject, after_subject); + len = pretty_print_commit(opt->commit_format, commit, ~0u, this_header, sizeof(this_header), abbrev, subject, extra_headers); + + if (opt->add_signoff) + len = append_signoff(this_header, sizeof(this_header), len, + opt->add_signoff); printf("%s%s%s", this_header, extra, sep); } diff --git a/revision.h b/revision.h index bdbdd235d8..7d85b0f2e9 100644 --- a/revision.h +++ b/revision.h @@ -60,6 +60,8 @@ struct rev_info { struct log_info *loginfo; int nr, total; const char *mime_boundary; + const char *add_signoff; + const char *extra_headers; /* special limits */ int max_count; |