From 2d9e4a47d16e9d2100cc88ef6126aa7619be51ed Mon Sep 17 00:00:00 2001 From: "Robin H. Johnson" Date: Wed, 11 Apr 2007 16:58:07 -0700 Subject: Add custom subject prefix support to format-patch (take 3) Add a new option to git-format-patch, entitled --subject-prefix that allows control of the subject prefix '[PATCH]'. Using this option, the text 'PATCH' is replaced with whatever input is provided to the option. This allows easily generating patches like '[PATCH 2.6.21-rc3]' or properly numbered series like '[-mm3 PATCH N/M]'. This patch provides the implementation and documentation. Signed-off-by: Robin H. Johnson Signed-off-by: Junio C Hamano --- builtin-log.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 71df957ea..4a4890aca 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -417,6 +417,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered = 0; int start_number = -1; int keep_subject = 0; + int subject_prefix = 0; int ignore_if_in_upstream = 0; int thread = 0; const char *in_reply_to = NULL; @@ -434,6 +435,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.ignore_merges = 1; rev.diffopt.msg_sep = ""; rev.diffopt.recursive = 1; + rev.subject_prefix = "PATCH"; rev.extra_headers = extra_headers; @@ -509,8 +511,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (i == argc) die("Need a Message-Id for --in-reply-to"); in_reply_to = argv[i]; - } - else if (!prefixcmp(argv[i], "--suffix=")) + } else if (!prefixcmp(argv[i], "--subject-prefix=")) { + subject_prefix = 1; + rev.subject_prefix = argv[i] + 17; + } else if (!prefixcmp(argv[i], "--suffix=")) fmt_patch_suffix = argv[i] + 9; else argv[j++] = argv[i]; @@ -521,6 +525,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) start_number = 1; if (numbered && keep_subject) die ("-n and -k are mutually exclusive."); + if (keep_subject && subject_prefix) + die ("--subject-prefix and -k are mutually exclusive."); argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) -- cgit v1.2.1 From 5d23e133d23bc9e26d6f23a4d136901e18e6ffba Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Apr 2007 17:01:27 -0700 Subject: Refactor patch-id filtering out of git-cherry and git-format-patch. This implements the patch-id computation and recording library, patch-ids.c, and rewrites the get_patch_ids() function used in cherry and format-patch to use it, so that they do not pollute the object namespace. Earlier code threw non-objects into the in-core object database, and hoped for not getting bitten by SHA-1 collisions. While it may be practically Ok, it still was an ugly hack. Signed-off-by: Junio C Hamano --- builtin-log.c | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 4a4890aca..eea96901b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -12,6 +12,7 @@ #include "builtin.h" #include "tag.h" #include "reflog-walk.h" +#include "patch-ids.h" static int default_show_root = 1; @@ -333,25 +334,12 @@ static int reopen_stdout(struct commit *commit, int nr, int keep_subject) } -static int get_patch_id(struct commit *commit, struct diff_options *options, - unsigned char *sha1) -{ - if (commit->parents) - diff_tree_sha1(commit->parents->item->object.sha1, - commit->object.sha1, "", options); - else - diff_root_tree_sha1(commit->object.sha1, "", options); - diffcore_std(options); - return diff_flush_patch_id(options, sha1); -} - -static void get_patch_ids(struct rev_info *rev, struct diff_options *options, const char *prefix) +static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix) { struct rev_info check_rev; struct commit *commit; struct object *o1, *o2; unsigned flags1, flags2; - unsigned char sha1[20]; if (rev->pending.nr != 2) die("Need exactly one range."); @@ -364,10 +352,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options, co if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die("Not a range."); - diff_setup(options); - options->recursive = 1; - if (diff_setup_done(options) < 0) - die("diff_setup_done failed"); + init_patch_ids(ids); /* given a range a..b get all patch ids for b..a */ init_revisions(&check_rev, prefix); @@ -382,8 +367,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options, co if (commit->parents && commit->parents->next) continue; - if (!get_patch_id(commit, options, sha1)) - created_object(sha1, xcalloc(1, sizeof(struct object))); + add_commit_patch_id(commit, ids); } /* reset for next revision walk */ @@ -421,7 +405,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int ignore_if_in_upstream = 0; int thread = 0; const char *in_reply_to = NULL; - struct diff_options patch_id_opts; + struct patch_ids ids; char *add_signoff = NULL; char message_id[1024]; char ref_message_id[1024]; @@ -560,22 +544,19 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (ignore_if_in_upstream) - get_patch_ids(&rev, &patch_id_opts, prefix); + get_patch_ids(&rev, &ids, prefix); if (!use_stdout) realstdout = fdopen(dup(1), "w"); prepare_revision_walk(&rev); while ((commit = get_revision(&rev)) != NULL) { - unsigned char sha1[20]; - /* ignore merges */ if (commit->parents && commit->parents->next) continue; if (ignore_if_in_upstream && - !get_patch_id(commit, &patch_id_opts, sha1) && - lookup_object(sha1)) + has_commit_patch_id(commit, &ids)) continue; nr++; @@ -630,6 +611,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) fclose(stdout); } free(list); + if (ignore_if_in_upstream) + free_patch_ids(&ids); return 0; } @@ -652,7 +635,7 @@ static const char cherry_usage[] = int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; - struct diff_options patch_id_opts; + struct patch_ids ids; struct commit *commit; struct commit_list *list = NULL; const char *upstream; @@ -698,7 +681,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) return 0; } - get_patch_ids(&revs, &patch_id_opts, prefix); + get_patch_ids(&revs, &ids, prefix); if (limit && add_pending_commit(limit, &revs, UNINTERESTING)) die("Unknown commit %s", limit); @@ -714,12 +697,10 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) } while (list) { - unsigned char sha1[20]; char sign = '+'; commit = list->item; - if (!get_patch_id(commit, &patch_id_opts, sha1) && - lookup_object(sha1)) + if (has_commit_patch_id(commit, &ids)) sign = '-'; if (verbose) { @@ -737,5 +718,6 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) list = list->next; } + free_patch_ids(&ids); return 0; } -- cgit v1.2.1 From 2bfe3cec92be4f5e3bfc0e71ed560df4a726c07b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 12 Apr 2007 03:04:05 -0700 Subject: Fix git {log,show,...} --pretty=email An earlier --subject-prefix patch forgot that format-patch is not the only codepath that adds the "[PATCH]" prefix, and broke everybody else in the log family. Signed-off-by: Junio C Hamano --- builtin-log.c | 1 - 1 file changed, 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 4a4890aca..ffc269a12 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -435,7 +435,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.ignore_merges = 1; rev.diffopt.msg_sep = ""; rev.diffopt.recursive = 1; - rev.subject_prefix = "PATCH"; rev.extra_headers = extra_headers; -- cgit v1.2.1 From ca135e7acc06f7d24ead732d2a1a531428da7135 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 16 Apr 2007 16:05:10 -0700 Subject: Add support for "commit name decorations" to log family of commands This adds "--decorate" as a log option, which prints out the ref names of any commits that are shown. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 469949457..38bf52f10 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -13,16 +13,43 @@ #include "tag.h" #include "reflog-walk.h" #include "patch-ids.h" +#include "refs.h" static int default_show_root = 1; /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); +static void add_name_decoration(const char *prefix, const char *name, struct object *obj) +{ + int plen = strlen(prefix); + int nlen = strlen(name); + struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen); + memcpy(res->name, prefix, plen); + memcpy(res->name + plen, name, nlen + 1); + res->next = add_decoration(&name_decoration, obj, res); +} + +static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data) +{ + struct object *obj = parse_object(sha1); + if (!obj) + return 0; + add_name_decoration("", refname, obj); + while (obj->type == OBJ_TAG) { + obj = ((struct tag *)obj)->tagged; + if (!obj) + break; + add_name_decoration("tag: ", refname, obj); + } + return 0; +} + static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; + int decorate = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -39,8 +66,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, git_log_output_encoding = xstrdup(arg); else git_log_output_encoding = ""; - } - else + } else if (!strcmp(arg, "--decorate")) { + if (!decorate) + for_each_ref(add_ref_decoration, NULL); + decorate = 1; + } else die("unrecognized argument: %s", arg); } } -- cgit v1.2.1 From 2dc189a3536a367444a4176684c89b994e93e736 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Mon, 14 May 2007 16:44:51 +0200 Subject: builtin-log.c: Fix typo in comment s/fmt-patch/format-patch/ Signed-off-by: Frank Lichtenheld Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 71df957ea..51294900d 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -439,7 +439,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* * Parse the arguments before setup_revisions(), or something - * like "git fmt-patch -o a123 HEAD^.." may fail; a123 is + * like "git format-patch -o a123 HEAD^.." may fail; a123 is * possibly a valid SHA1. */ for (i = 1, j = 1; i < argc; i++) { -- cgit v1.2.1 From e6ff0f42bb0c63515c8489c1992f37d1d1e8b2f4 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Tue, 5 Jun 2007 15:06:53 -0500 Subject: Add the --numbered-files option to git-format-patch. With this option, git-format-patch will generate simple numbered files as output instead of the default using with the first commit line appended. This simplifies the ability to generate an MH-style drafts folder with each message to be sent. Signed-off-by: Jon Loeliger Signed-off-by: Junio C Hamano --- builtin-log.c | 97 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 41 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 37447123f..212cdfc76 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -298,7 +298,8 @@ static int git_format_config(const char *var, const char *value) static FILE *realstdout = NULL; static const char *output_directory = NULL; -static int reopen_stdout(struct commit *commit, int nr, int keep_subject) +static int reopen_stdout(struct commit *commit, int nr, int keep_subject, + int numbered_files) { char filename[PATH_MAX]; char *sol; @@ -315,53 +316,61 @@ static int reopen_stdout(struct commit *commit, int nr, int keep_subject) filename[len++] = '/'; } - sprintf(filename + len, "%04d", nr); - len = strlen(filename); - - sol = strstr(commit->buffer, "\n\n"); - if (sol) { - int j, space = 1; - - 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; - } - } + if (numbered_files) { + sprintf(filename + len, "%d", nr); + len = strlen(filename); - 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; + } else { + sprintf(filename + len, "%04d", nr); + len = strlen(filename); + + sol = strstr(commit->buffer, "\n\n"); + if (sol) { + int j, space = 1; + + 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; } - filename[len++] = sol[j]; - if (sol[j] == '.') - while (sol[j + 1] == '.') - j++; - } else - space = 1; + } + + 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; } - while (filename[len - 1] == '.' || filename[len - 1] == '-') - len--; - filename[len] = 0; + if (len + suffix_len >= sizeof(filename)) + return error("Patch pathname too long"); + strcpy(filename + len, fmt_patch_suffix); } - if (len + suffix_len >= sizeof(filename)) - return error("Patch pathname too long"); - strcpy(filename + len, fmt_patch_suffix); + fprintf(realstdout, "%s\n", filename); if (freopen(filename, "w", stdout) == NULL) return error("Cannot open patch file %s",filename); - return 0; + return 0; } static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix) @@ -431,6 +440,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered = 0; int start_number = -1; int keep_subject = 0; + int numbered_files = 0; /* _just_ numbers */ int subject_prefix = 0; int ignore_if_in_upstream = 0; int thread = 0; @@ -465,6 +475,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) numbered = 1; else if (!prefixcmp(argv[i], "--start-number=")) start_number = strtol(argv[i] + 15, NULL, 10); + else if (!strcmp(argv[i], "--numbered-files")) + numbered_files = 1; else if (!strcmp(argv[i], "--start-number")) { i++; if (i == argc) @@ -540,6 +552,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die ("-n and -k are mutually exclusive."); if (keep_subject && subject_prefix) die ("--subject-prefix and -k are mutually exclusive."); + if (numbered_files && use_stdout) + die ("--numbered-files and --stdout are mutually exclusive."); argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) @@ -614,7 +628,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.message_id = message_id; } if (!use_stdout) - if (reopen_stdout(commit, rev.nr, keep_subject)) + if (reopen_stdout(commit, rev.nr, keep_subject, + numbered_files)) die("Failed to create output files"); shown = log_tree_commit(&rev, commit); free(commit->buffer); -- cgit v1.2.1 From 66688334375adbc469419692a16857f3cda01a21 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 16 May 2007 07:15:07 -0400 Subject: cmd_log_init: remove parsing of --encoding command line parameter This was moved to the setup_revisions parsing in 7cbcf4d5, so it was never being triggered. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-log.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 212cdfc76..0aede7683 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -60,13 +60,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->always_show_header = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; - if (!prefixcmp(arg, "--encoding=")) { - arg += 11; - if (strcmp(arg, "none")) - git_log_output_encoding = xstrdup(arg); - else - git_log_output_encoding = ""; - } else if (!strcmp(arg, "--decorate")) { + if (!strcmp(arg, "--decorate")) { if (!decorate) for_each_ref(add_ref_decoration, NULL); decorate = 1; -- cgit v1.2.1 From 80583c0ef61cc966c7eee79cf3623a83197e19b8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Jun 2007 00:34:54 -0700 Subject: Lift 16kB limit of log message output Traditionally we had 16kB limit when formatting log messages for output, because it was easier to arrange for the caller to have a reasonably big buffer and pass it down without ever worrying about reallocating. This changes the calling convention of pretty_print_commit() to lift this limit. Instead of the buffer and remaining length, it now takes a pointer to the pointer that points at the allocated buffer, and another pointer to the location that stores the allocated length, and reallocates the buffer as necessary. To support the user format, the error return of interpolate() needed to be changed. It used to return a bool telling "Ok the result fits", or "Sorry, I had to truncate it". Now it returns 0 on success, and returns the size of the buffer it wants in order to fit the whole result. Signed-off-by: Junio C Hamano --- builtin-log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 0aede7683..b9035ab79 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -742,11 +742,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - static char buf[16384]; + char *buf = NULL; + unsigned long buflen = 0; pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - buf, sizeof(buf), 0, NULL, NULL, 0); + &buf, &buflen, 0, NULL, NULL, 0); printf("%c %s %s\n", sign, sha1_to_hex(commit->object.sha1), buf); + free(buf); } else { printf("%c %s\n", sign, -- cgit v1.2.1 From 750f7b668f33c9e8decbdd8141115328992d6fea Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 19 Jun 2007 14:22:46 -0700 Subject: Finally implement "git log --follow" Ok, I've really held off doing this too damn long, because I'm lazy, and I was always hoping that somebody else would do it. But no, people keep asking for it, but nobody actually did anything, so I decided I might as well bite the bullet, and instead of telling people they could add a "--follow" flag to "git log" to do what they want to do, I decided that it looks like I just have to do it for them.. The code wasn't actually that complicated, in that the diffstat for this patch literally says "70 insertions(+), 1 deletions(-)", but I will have to admit that in order to get to this fairly simple patch, you did have to know and understand the internal git diff generation machinery pretty well, and had to really be able to follow how commit generation interacts with generating patches and generating the log. So I suspect that while I was right that it wasn't that hard, I might have been expecting too much of random people - this patch does seem to be firmly in the core "Linus or Junio" territory. To make a long story short: I'm sorry for it taking so long until I just did it. I'm not going to guarantee that this works for everybody, but you really can just look at the patch, and after the appropriate appreciative noises ("Ooh, aah") over how clever I am, you can then just notice that the code itself isn't really that complicated. All the real new code is in the new "try_to_follow_renames()" function. It really isn't rocket science: we notice that the pathname we were looking at went away, so we start a full tree diff and try to see if we can instead make that pathname be a rename or a copy from some other previous pathname. And if we can, we just continue, except we show *that* particular diff, and ever after we use the _previous_ pathname. One thing to look out for: the "rename detection" is considered to be a singular event in the _linear_ "git log" output! That's what people want to do, but I just wanted to point out that this patch is *not* carrying around a "commit,pathname" kind of pair and it's *not* going to be able to notice the file coming from multiple *different* files in earlier history. IOW, if you use "git log --follow", then you get the stupid CVS/SVN kind of "files have single identities" kind of semantics, and git log will just pick the identity based on the normal move/copy heuristics _as_if_ the history could be linearized. Put another way: I think the model is broken, but given the broken model, I think this patch does just about as well as you can do. If you have merges with the same "file" having different filenames over the two branches, git will just end up picking _one_ of the pathnames at the point where the newer one goes away. It never looks at multiple pathnames in parallel. And if you understood all that, you probably didn't need it explained, and if you didn't understand the above blathering, it doesn't really mtter to you. What matters to you is that you can now do git log -p --follow builtin-rev-list.c and it will find the point where the old "rev-list.c" got renamed to "builtin-rev-list.c" and show it as such. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index b9035ab79..073a2a16a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -58,6 +58,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; + if (rev->diffopt.follow_renames) { + rev->always_show_header = 0; + if (rev->diffopt.nr_paths != 1) + usage("git logs can only follow renames on one pathname at a time"); + } for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { -- cgit v1.2.1 From f57882505efe05990102a0d96b37c09baadae03d Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 27 Jun 2007 16:28:53 +0200 Subject: git-log: detect dup and fdopen failure This defines xdup() and xfdopen() in git-compat-util.h to give us error-catching variants of them without cluttering the code too much. Signed-off-by: Jim Meyering Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 073a2a16a..a4186eac8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -589,7 +589,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) get_patch_ids(&rev, &ids, prefix); if (!use_stdout) - realstdout = fdopen(dup(1), "w"); + realstdout = xfdopen(xdup(1), "w"); prepare_revision_walk(&rev); while ((commit = get_revision(&rev)) != NULL) { -- cgit v1.2.1 From dbd21447361364d646f3972738a475a92f711513 Mon Sep 17 00:00:00 2001 From: Adam Roben Date: Sun, 1 Jul 2007 17:48:59 -0700 Subject: format-patch: Add format.subjectprefix config option This change lets you use the format.subjectprefix config option to override the default subject prefix. Signed-off-by: Adam Roben Signed-off-by: Junio C Hamano --- builtin-log.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index a4186eac8..5dc2c1c23 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -265,6 +265,7 @@ static int istitlechar(char c) static char *extra_headers = NULL; static int extra_headers_size = 0; +static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_patch_suffix = ".patch"; static int git_format_config(const char *var, const char *value) @@ -290,6 +291,13 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } + if (!strcmp(var, "format.subjectprefix")) { + if (!value) + die("format.subjectprefix without value"); + fmt_patch_subject_prefix = xstrdup(value); + return 0; + } + return git_log_config(var, value); } @@ -459,6 +467,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diffopt.msg_sep = ""; rev.diffopt.recursive = 1; + rev.subject_prefix = fmt_patch_subject_prefix; rev.extra_headers = extra_headers; /* -- cgit v1.2.1 From d54276f207081e35174c5d742e378cfff6e9843f Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Wed, 4 Jul 2007 12:37:27 +0200 Subject: Handle format.subjectprefix for every command which accepts --pretty Because the --pretty can be given as --pretty=email which historically produced mails with patches. IOW, exactly what git-format-patch does. Signed-off-by: Junio C Hamano --- builtin-log.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5dc2c1c23..13bae3110 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -16,6 +16,7 @@ #include "refs.h" static int default_show_root = 1; +static const char *fmt_patch_subject_prefix = "PATCH"; /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); @@ -55,6 +56,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; rev->show_root_diff = default_show_root; + rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; @@ -94,6 +96,12 @@ static int cmd_log_walk(struct rev_info *rev) static int git_log_config(const char *var, const char *value) { + if (!strcmp(var, "format.subjectprefix")) { + if (!value) + die("format.subjectprefix without value"); + fmt_patch_subject_prefix = xstrdup(value); + return 0; + } if (!strcmp(var, "log.showroot")) { default_show_root = git_config_bool(var, value); return 0; @@ -265,7 +273,6 @@ static int istitlechar(char c) static char *extra_headers = NULL; static int extra_headers_size = 0; -static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_patch_suffix = ".patch"; static int git_format_config(const char *var, const char *value) @@ -291,12 +298,6 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } - if (!strcmp(var, "format.subjectprefix")) { - if (!value) - die("format.subjectprefix without value"); - fmt_patch_subject_prefix = xstrdup(value); - return 0; - } return git_log_config(var, value); } -- cgit v1.2.1 From 170c04383bca07fb5a32227474dfd58f29258d25 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 27 Aug 2007 01:33:49 -0700 Subject: Porcelain level "log" family should recurse when diffing. Most notably, "git log --name-status" stopped at top level directory changes without "-r" option. Signed-off-by: Junio C Hamano --- builtin-log.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 13bae3110..a381c75f3 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -55,6 +55,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; + rev->diffopt.recursive = 1; rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); @@ -116,7 +117,6 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.simplify_history = 0; cmd_log_init(argc, argv, prefix, &rev); if (!rev.diffopt.output_format) @@ -165,7 +165,6 @@ int cmd_show(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.combine_merges = 1; rev.dense_combined_merges = 1; rev.always_show_header = 1; -- cgit v1.2.1 From 8a1d076e21810f5bc7e9ef10d84f7ca9637b89af Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Aug 2007 00:38:48 -0700 Subject: "format-patch --root rev" is the way to show everything. We used to trigger the special case "things not in origin" semantics only when one and only one positive ref is given, and no number (e.g. "git format-patch -4 origin") was specified, and used the general revision range semantics for everything else. This narrows the special case a bit more, by making: git format-patch --root this_version to show everything that leads to the named commit. More importantly, document the two different semantics better. The generic revision range semantics came later and bolted on without being clearly documented. Signed-off-by: Junio C Hamano --- builtin-log.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index a381c75f3..fa81c2592 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -585,12 +585,19 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (rev.pending.nr == 1) { - if (rev.max_count < 0) { + if (rev.max_count < 0 && !rev.show_root_diff) { + /* + * This is traditional behaviour of "git format-patch + * origin" that prepares what the origin side still + * does not have. + */ rev.pending.objects[0].item->flags |= UNINTERESTING; add_head(&rev); } - /* Otherwise, it is "format-patch -22 HEAD", and - * get_revision() would return only the specified count. + /* + * Otherwise, it is "format-patch -22 HEAD", and/or + * "format-patch --root HEAD". The user wants + * get_revision() to do the usual traversal. */ } -- cgit v1.2.1 From 674d1727305211f7ade4ade70440220f74f55162 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 10 Sep 2007 12:35:06 +0200 Subject: Rework pretty_print_commit to use strbufs instead of custom buffers. Also remove the "len" parameter, as: (1) it was used as a max boundary, and every caller used ~0u (2) we check for final NUL no matter what, so it doesn't help for speed. As a result most of the pp_* function takes 3 arguments less, and we need a lot less local variables, this makes the code way more readable, and easier to extend if needed. This patch also fixes some spacing and cosmetic issues. This patch also fixes (as a side effect) a memory leak intoruced in builtin-archive.c at commit df4a394f (fmt was xmalloc'ed and not free'd) Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-log.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fa81c2592..e1d3e7d74 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -763,13 +763,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - char *buf = NULL; - unsigned long buflen = 0; - pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - &buf, &buflen, 0, NULL, NULL, 0); + struct strbuf buf; + strbuf_init(&buf, 0); + pretty_print_commit(CMIT_FMT_ONELINE, commit, + &buf, 0, NULL, NULL, 0); printf("%c %s %s\n", sign, - sha1_to_hex(commit->object.sha1), buf); - free(buf); + sha1_to_hex(commit->object.sha1), buf.buf); + strbuf_release(&buf); } else { printf("%c %s\n", sign, -- cgit v1.2.1 From 8419d2ee9ba8b375186a5c1019df8dfbce610aba Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 13 Sep 2007 22:30:45 -0700 Subject: git-format-patch --in-reply-to: accept with angle brackets This will allow RFC-literate users to say: format-patch --in-reply-to='' without forcing them to strip the surrounding angle brackets like this: format-patch --in-reply-to='message.id@site.name' We accept both forms, and the latter gets necessary < and > around it as before. Signed-off-by: Junio C Hamano --- builtin-log.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fa81c2592..c6cc3aef5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -437,6 +437,34 @@ static void gen_message_id(char *dest, unsigned int length, char *base) (int)(email_end - email_start - 1), email_start + 1); } +static const char *clean_message_id(const char *msg_id) +{ + char ch; + const char *a, *z, *m; + char *n; + size_t len; + + m = msg_id; + while ((ch = *m) && (isspace(ch) || (ch == '<'))) + m++; + a = m; + z = NULL; + while ((ch = *m)) { + if (!isspace(ch) && (ch != '>')) + z = m; + m++; + } + if (!z) + die("insane in-reply-to: %s", msg_id); + if (++z == m) + return a; + len = z - a; + n = xmalloc(len + 1); + memcpy(n, a, len); + n[len] = 0; + return n; +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -625,7 +653,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; - rev.ref_message_id = in_reply_to; + if (in_reply_to) + rev.ref_message_id = clean_message_id(in_reply_to); while (0 <= --nr) { int shown; commit = list[nr]; -- cgit v1.2.1 From 182af8343c307436bb5364309aa6d4d46fa5911d Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 16 Sep 2007 00:32:36 +0200 Subject: Use xmemdupz() in many places. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-log.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 60819d15c..e8b982db7 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -441,8 +441,6 @@ static const char *clean_message_id(const char *msg_id) { char ch; const char *a, *z, *m; - char *n; - size_t len; m = msg_id; while ((ch = *m) && (isspace(ch) || (ch == '<'))) @@ -458,11 +456,7 @@ static const char *clean_message_id(const char *msg_id) die("insane in-reply-to: %s", msg_id); if (++z == m) return a; - len = z - a; - n = xmalloc(len + 1); - memcpy(n, a, len); - n[len] = 0; - return n; + return xmemdupz(a, z - a); } int cmd_format_patch(int argc, const char **argv, const char *prefix) @@ -541,9 +535,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) 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; + add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { rev.mime_boundary = git_version_string; -- cgit v1.2.1 From 4593fb84051d39f65cec81958e91056986e4682f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 31 Oct 2007 14:55:17 -0700 Subject: format-patch -s: add MIME encoding header if signer's name requires so When the body of the commit log message contains a non-ASCII character, format-patch correctly emitted the encoding header to mark the resulting message as such. However, if the original message was fully ASCII, the command line switch "-s" was given to add a new sign-off, and the signer's name was not ASCII only, the resulting message would have contained non-ASCII character but was not marked as such. Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index e8b982db7..8b2bf632c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -787,7 +787,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) struct strbuf buf; strbuf_init(&buf, 0); pretty_print_commit(CMIT_FMT_ONELINE, commit, - &buf, 0, NULL, NULL, 0); + &buf, 0, NULL, NULL, 0, 0); printf("%c %s %s\n", sign, sha1_to_hex(commit->object.sha1), buf.buf); strbuf_release(&buf); -- cgit v1.2.1 From cdcefbc971d8fcdd293750af7571d4c715f86964 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 3 Nov 2007 11:11:10 -0700 Subject: Add "--early-output" log flag for interactive GUI use This adds support for "--early-output[=n]" as a flag to the "git log" family of commands. This allows GUI programs to state that they want to get some output early, in order to be able to show at least something quickly, even if the full output may take longer to generate. If no count is specified, a default count of a hundred commits will be used, although the actual numbr of commits output may be smaller depending on how many commits were actually found in the first tenth of a second (or if *everything* was found before that, in which case no early output will be provided, and only the final list is made available). When the full list is generated, there will be a "Final output:" string prepended to it, regardless of whether any early commits were shown or not, so that the consumer can always know the difference between early output and the final list. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c..4e9d0cb69 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -77,11 +77,78 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } } +static void log_show_early(struct rev_info *revs, struct commit_list *list) +{ + int i = revs->early_output; + + sort_in_topological_order(&list, revs->lifo); + while (list && i) { + struct commit *commit = list->item; + log_tree_commit(revs, commit); + list = list->next; + i--; + } +} + +static void early_output(int signal) +{ + show_early_output = log_show_early; +} + +static void setup_early_output(struct rev_info *rev) +{ + struct sigaction sa; + struct itimerval v; + + /* + * Set up the signal handler, minimally intrusively: + * we only set a single volatile integer word (not + * using sigatomic_t - trying to avoid unnecessary + * system dependencies and headers), and using + * SA_RESTART. + */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = early_output; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGALRM, &sa, NULL); + + /* + * If we can get the whole output in less than a + * tenth of a second, don't even bother doing the + * early-output thing.. + * + * This is a one-time-only trigger. + */ + memset(&v, 0, sizeof(v)); + v.it_value.tv_sec = 0; + v.it_value.tv_usec = 100000; + setitimer(ITIMER_REAL, &v, NULL); +} + +static void finish_early_output(struct rev_info *rev) +{ + signal(SIGALRM, SIG_IGN); + if (rev->shown_one) { + rev->shown_one = 0; + if (rev->commit_format != CMIT_FMT_ONELINE) + putchar(rev->diffopt.line_termination); + } + printf("Final output:\n"); +} + static int cmd_log_walk(struct rev_info *rev) { struct commit *commit; + if (rev->early_output) + setup_early_output(rev); + prepare_revision_walk(rev); + + if (rev->early_output) + finish_early_output(rev); + while ((commit = get_revision(rev)) != NULL) { log_tree_commit(rev, commit); if (!rev->reflog_info) { -- cgit v1.2.1 From 49604a4d62d9055dbfc06472e7ef20d8a6114123 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Sat, 3 Nov 2007 23:38:24 -0400 Subject: format-patch: Add configuration and off switch for --numbered format.numbered is a tri-state variable. Boolean values enable or disable numbering by default and "auto" enables number when outputting more than one patch. --no-numbered (short: -N) will disable numbering. Signed-off-by: Brian Gernhardt Signed-off-by: Junio C Hamano --- builtin-log.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c..c5230106a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -273,6 +273,8 @@ static int istitlechar(char c) static char *extra_headers = NULL; static int extra_headers_size = 0; static const char *fmt_patch_suffix = ".patch"; +static int numbered = 0; +static int auto_number = 0; static int git_format_config(const char *var, const char *value) { @@ -297,6 +299,15 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } + if (!strcmp(var, "format.numbered")) { + if (!strcasecmp(value, "auto")) { + auto_number = 1; + return 0; + } + + numbered = git_config_bool(var, value); + return 0; + } return git_log_config(var, value); } @@ -466,7 +477,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct rev_info rev; int nr = 0, total, i, j; int use_stdout = 0; - int numbered = 0; int start_number = -1; int keep_subject = 0; int numbered_files = 0; /* _just_ numbers */ @@ -503,6 +513,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--numbered")) numbered = 1; + else if (!strcmp(argv[i], "-N") || + !strcmp(argv[i], "--no-numbered")) { + numbered = 0; + auto_number = 0; + } else if (!prefixcmp(argv[i], "--start-number=")) start_number = strtol(argv[i] + 15, NULL, 10); else if (!strcmp(argv[i], "--numbered-files")) @@ -642,6 +657,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) list[nr - 1] = commit; } total = nr; + if (!keep_subject && auto_number && total > 1) + numbered = 1; if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; -- cgit v1.2.1 From 252a7c02354a3e2825cfde3c5053a04acc07be9c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Nov 2007 12:12:05 -0800 Subject: Enhance --early-output format This makes --early-output a bit more advanced, and actually makes it generate multiple "Final output:" headers as it updates things asynchronously. I realize that the "Final output:" line is now illogical, since it's not really final until it also says "done", but It now _always_ generates a "Final output:" header in front of any commit list, and that output header gives you a *guess* at the maximum number of commits available. However, it should be noted that the guess can be completely off: I do a reasonable job estimating it, but it is not meant to be exact. So what happens is that you may get output like this: - at 0.1 seconds: Final output: 2 incomplete .. 2 commits listed .. - half a second later: Final output: 33 incomplete .. 33 commits listed .. - another half a second after that: Final output: 71 incomplete .. 71 commits listed .. - another half second later: Final output: 136 incomplete .. 100 commits listed: we hit the --early-output limit, and .. will only output 100 commits, and after this you'll not .. see an "incomplete" report any more since you got as much .. early output as you asked for! - .. and then finally: Final output: 73106 done .. all the commits .. The above is a real-life scenario on my current kernel tree after having flushed all the caches. Tested with the experimental gitk patch that Paul sent out, and by looking at the actual log output (and verifying that my commit count guesses actually match real life fairly well). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 13 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 4e9d0cb69..981f38872 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -77,17 +77,85 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } } +/* + * This gives a rough estimate for how many commits we + * will print out in the list. + */ +static int estimate_commit_count(struct rev_info *rev, struct commit_list *list) +{ + int n = 0; + + while (list) { + struct commit *commit = list->item; + unsigned int flags = commit->object.flags; + + list = list->next; + if (flags & UNINTERESTING) + continue; + if (rev->prune_fn && rev->dense && !(flags & TREECHANGE)) { + if (commit->parents && !commit->parents->next) + continue; + } + n++; + } + return n; +} + +static void show_early_header(struct rev_info *rev, const char *stage, int nr) +{ + if (rev->shown_one) { + rev->shown_one = 0; + if (rev->commit_format != CMIT_FMT_ONELINE) + putchar(rev->diffopt.line_termination); + } + printf("Final output: %d %s\n", nr, stage); +} + +struct itimerval early_output_timer; + static void log_show_early(struct rev_info *revs, struct commit_list *list) { int i = revs->early_output; + int show_header = 1; sort_in_topological_order(&list, revs->lifo); while (list && i) { struct commit *commit = list->item; - log_tree_commit(revs, commit); + switch (simplify_commit(revs, commit)) { + case commit_show: + if (show_header) { + int n = estimate_commit_count(revs, list); + show_early_header(revs, "incomplete", n); + show_header = 0; + } + log_tree_commit(revs, commit); + i--; + break; + case commit_ignore: + break; + case commit_error: + return; + } list = list->next; - i--; } + + /* Did we already get enough commits for the early output? */ + if (!i) + return; + + /* + * ..if no, then repeat it twice a second until we + * do. + * + * NOTE! We don't use "it_interval", because if the + * reader isn't listening, we want our output to be + * throttled by the writing, and not have the timer + * trigger every second even if we're blocked on a + * reader! + */ + early_output_timer.it_value.tv_sec = 0; + early_output_timer.it_value.tv_usec = 500000; + setitimer(ITIMER_REAL, &early_output_timer, NULL); } static void early_output(int signal) @@ -98,7 +166,6 @@ static void early_output(int signal) static void setup_early_output(struct rev_info *rev) { struct sigaction sa; - struct itimerval v; /* * Set up the signal handler, minimally intrusively: @@ -120,21 +187,16 @@ static void setup_early_output(struct rev_info *rev) * * This is a one-time-only trigger. */ - memset(&v, 0, sizeof(v)); - v.it_value.tv_sec = 0; - v.it_value.tv_usec = 100000; - setitimer(ITIMER_REAL, &v, NULL); + early_output_timer.it_value.tv_sec = 0; + early_output_timer.it_value.tv_usec = 100000; + setitimer(ITIMER_REAL, &early_output_timer, NULL); } static void finish_early_output(struct rev_info *rev) { + int n = estimate_commit_count(rev, rev->commits); signal(SIGALRM, SIG_IGN); - if (rev->shown_one) { - rev->shown_one = 0; - if (rev->commit_format != CMIT_FMT_ONELINE) - putchar(rev->diffopt.line_termination); - } - printf("Final output:\n"); + show_early_header(rev, "done", n); } static int cmd_log_walk(struct rev_info *rev) -- cgit v1.2.1 From 53b2c823f6e862e0c83a4a25bab43e8c32e9c289 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Nov 2007 13:22:34 -0800 Subject: revision walker: mini clean-up This removes the unnecessary indirection of "revs->prune_fn", since that function is always the same one (or NULL), and there is in fact not even an abstraction reason to make it a function (i.e. its not called from some other file and doesn't allow us to keep the function itself static or anything like that). It then just replaces it with a bit that says "prune or not", and if not pruning, every commit gets TREECHANGE. That in turn means that - if (!revs->prune_fn || (flags & TREECHANGE)) - if (revs->prune_fn && !(flags & TREECHANGE)) just become - if (flags & TREECHANGE) - if (!(flags & TREECHANGE)) respectively. Together with adding the "single_parent()" helper function, the "complex" conditional now becomes if (!(flags & TREECHANGE) && rev->dense && single_parent(commit)) continue; Also indirection of "revs->dense" checking is thrown away the same way, because TREECHANGE bit is set appropriately now. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 981f38872..d6845bc7f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -88,15 +88,9 @@ static int estimate_commit_count(struct rev_info *rev, struct commit_list *list) while (list) { struct commit *commit = list->item; unsigned int flags = commit->object.flags; - list = list->next; - if (flags & UNINTERESTING) - continue; - if (rev->prune_fn && rev->dense && !(flags & TREECHANGE)) { - if (commit->parents && !commit->parents->next) - continue; - } - n++; + if ((flags & TREECHANGE) && !(flags & UNINTERESTING)) + n++; } return n; } -- cgit v1.2.1 From 8f67f8aefb1b751073f8b36fae8be8f72eb93f4a Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 10 Nov 2007 20:05:14 +0100 Subject: Make the diff_options bitfields be an unsigned with explicit masks. reverse_diff was a bit-value in disguise, it's merged in the flags now. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-log.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c..b69b0b42f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -55,13 +55,13 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; - rev->diffopt.recursive = 1; + DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; - if (rev->diffopt.follow_renames) { + if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) { rev->always_show_header = 0; if (rev->diffopt.nr_paths != 1) usage("git logs can only follow renames on one pathname at a time"); @@ -185,11 +185,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) struct tag *t = (struct tag *)o; printf("%stag %s%s\n\n", - diff_get_color(rev.diffopt.color_diff, - DIFF_COMMIT), + diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, - diff_get_color(rev.diffopt.color_diff, - DIFF_RESET)); + diff_get_color_opt(&rev.diffopt, DIFF_RESET)); ret = show_object(o->sha1, 1); objects[i].item = (struct object *)t->tagged; i--; @@ -197,11 +195,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) } case OBJ_TREE: printf("%stree %s%s\n\n", - diff_get_color(rev.diffopt.color_diff, - DIFF_COMMIT), + diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), name, - diff_get_color(rev.diffopt.color_diff, - DIFF_RESET)); + diff_get_color_opt(&rev.diffopt, DIFF_RESET)); read_tree_recursive((struct tree *)o, "", 0, 0, NULL, show_tree_object); break; @@ -487,7 +483,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.combine_merges = 0; rev.ignore_merges = 1; rev.diffopt.msg_sep = ""; - rev.diffopt.recursive = 1; + DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; rev.extra_headers = extra_headers; @@ -590,8 +586,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH; - if (!rev.diffopt.text) - rev.diffopt.binary = 1; + if (!DIFF_OPT_TST(&rev.diffopt, TEXT)) + DIFF_OPT_SET(&rev.diffopt, BINARY); if (!output_directory && !use_stdout) output_directory = prefix; @@ -747,7 +743,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) revs.diff = 1; revs.combine_merges = 0; revs.ignore_merges = 1; - revs.diffopt.recursive = 1; + DIFF_OPT_SET(&revs.diffopt, RECURSIVE); if (add_pending_commit(head, &revs, 0)) die("Unknown commit %s", head); -- cgit v1.2.1 From 7dc0fe3be5c949e83e96a1b829be0e72eafffb47 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 12 Nov 2007 23:16:08 -0800 Subject: Fix parent rewriting in --early-output We cannot tell a node that has been checked and found not to be interesting (which does not have the TREECHANGE flag) from a node that hasn't been checked if it is interesting or not, without relying on something else, such as object->parsed. But an object can get the "parsed" flag for other reasons. Which means that "TREECHANGE" has the wrong polarity. This changes the way how the path pruning logic marks an uninteresting commits. From now on, we consider a commit interesting by default, and explicitly mark the ones we decided to prune. The flag is renamed to "TREESAME". Then, this fixes the logic to show the early output with incomplete pruning. It basically says "a commit that has TREESAME set is kind-of-UNINTERESTING", but obviously in a different way than an outright UNINTERESTING commit. Until we parse and examine enough parents to determine if a commit becomes surely "kind-of-UNINTERESTING", we avoid rewriting the ancestry so that later rounds can fix things up. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index d6845bc7f..54ddaad0e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -89,7 +89,7 @@ static int estimate_commit_count(struct rev_info *rev, struct commit_list *list) struct commit *commit = list->item; unsigned int flags = commit->object.flags; list = list->next; - if ((flags & TREECHANGE) && !(flags & UNINTERESTING)) + if (!(flags & (TREESAME | UNINTERESTING))) n++; } return n; -- cgit v1.2.1 From 774751a8bc594a5b56039bbdc43c45e3882dd804 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 8 Dec 2007 17:32:08 -0800 Subject: Re-fix "builtin-commit: fix --signoff" An earlier fix to the said commit was incomplete; it mixed up the meaning of the flag parameter passed to the internal fmt_ident() function, so this corrects it. git_author_info() and git_committer_info() can be told to issue a warning when no usable user information is found, and optionally can be told to error out. Operations that actually use the information to record a new commit or a tag will still error out, but the caller to leave reflog record will just silently use bogus user information. Not warning on misconfigured user information while writing a reflog entry is somewhat debatable, but it is probably nicer to the users to silently let it pass, because the only information you are losing is who checked out the branch. * git_author_info() and git_committer_info() used to take 1 (positive int) to error out with a warning on misconfiguration; this is now signalled with a symbolic constant IDENT_ERROR_ON_NO_NAME. * These functions used to take -1 (negative int) to warn but continue; this is now signalled with a symbolic constant IDENT_WARN_ON_NO_NAME. * fmt_ident() function implements the above error reporting behaviour common to git_author_info() and git_committer_info(). A symbolic constant IDENT_NO_DATE can be or'ed in to the flag parameter to make it return only the "Name ". * fmt_name() is a thin wrapper around fmt_ident() that always passes IDENT_ERROR_ON_NO_NAME and IDENT_NO_DATE. Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index e1f1cf671..b6a11220e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -557,7 +557,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha static void gen_message_id(char *dest, unsigned int length, char *base) { - const char *committer = git_committer_info(-1); + const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME); const char *email_start = strrchr(committer, '<'); const char *email_end = strrchr(committer, '>'); if(!email_start || !email_end || email_start > email_end - 1) @@ -665,7 +665,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) !strcmp(argv[i], "-s")) { const char *committer; const char *endpos; - committer = git_committer_info(1); + committer = git_committer_info(IDENT_ERROR_ON_NO_NAME); endpos = strchr(committer, '>'); if (!endpos) die("bogos committer info %s\n", committer); -- cgit v1.2.1 From 3384a2dfc12f0fecd25ecfd6bfa9ee0d82517bf2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 11 Dec 2007 10:09:04 -0800 Subject: shortlog: default to HEAD when the standard input is a tty Instead of warning the user that it is expecting git log output from the standard input (and waiting for the user to type the log from the keyboard, which is a silly thing to do), default to traverse from HEAD when there is no rev parameter given and the standard input is a tty. This factors out a useful helper "add_head()" from builtin-diff.c to a more appropriate place revision.c while renaming it to more descriptive name add_head_to_pending(), as that is what the function is about. Signed-off-by: Junio C Hamano --- builtin-log.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index e1f1cf671..d375c9dbf 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -18,9 +18,6 @@ static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; -/* this is in builtin-diff.c */ -void add_head(struct rev_info *revs); - static void add_name_decoration(const char *prefix, const char *name, struct object *obj) { int plen = strlen(prefix); @@ -746,7 +743,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * does not have. */ rev.pending.objects[0].item->flags |= UNINTERESTING; - add_head(&rev); + add_head_to_pending(&rev); } /* * Otherwise, it is "format-patch -22 HEAD", and/or -- cgit v1.2.1 From 56122ed87af181c88e3121795c292689ac574f01 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 18 Dec 2007 18:01:33 +0000 Subject: git show : show the tagger For commit objects, the Author is shown, so do the equivalent for tag objects, too. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-log.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index cc3cc9069..dcc9f8179 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -244,7 +244,28 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) return cmd_log_walk(&rev); } -static int show_object(const unsigned char *sha1, int suppress_header) +static void show_tagger(char *buf, int len, struct rev_info *rev) +{ + char *email_end, *p; + unsigned long date; + int tz; + + email_end = memchr(buf, '>', len); + if (!email_end) + return; + p = ++email_end; + while (isspace(*p)) + p++; + date = strtoul(p, &p, 10); + while (isspace(*p)) + p++; + tz = (int)strtol(p, NULL, 10); + printf("Tagger: %.*s\nDate: %s\n", (int)(email_end - buf), buf, + show_date(date, tz, rev->date_mode)); +} + +static int show_object(const unsigned char *sha1, int show_tag_object, + struct rev_info *rev) { unsigned long size; enum object_type type; @@ -254,11 +275,14 @@ static int show_object(const unsigned char *sha1, int suppress_header) if (!buf) return error("Could not read object %s", sha1_to_hex(sha1)); - if (suppress_header) - while (offset < size && buf[offset++] != '\n') { - int new_offset = offset; + if (show_tag_object) + while (offset < size && buf[offset] != '\n') { + int new_offset = offset + 1; while (new_offset < size && buf[new_offset++] != '\n') ; /* do nothing */ + if (!prefixcmp(buf + offset, "tagger ")) + show_tagger(buf + offset + 7, + new_offset - offset - 7, rev); offset = new_offset; } @@ -299,16 +323,16 @@ int cmd_show(int argc, const char **argv, const char *prefix) const char *name = objects[i].name; switch (o->type) { case OBJ_BLOB: - ret = show_object(o->sha1, 0); + ret = show_object(o->sha1, 0, NULL); break; case OBJ_TAG: { struct tag *t = (struct tag *)o; - printf("%stag %s%s\n\n", + printf("%stag %s%s\n", diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); - ret = show_object(o->sha1, 1); + ret = show_object(o->sha1, 1, &rev); objects[i].item = (struct object *)t->tagged; i--; break; -- cgit v1.2.1 From 995c45279e270811f53b7ff8bf44a07ed3457ddc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Feb 2008 10:48:55 -0800 Subject: builtin-log.c: guard config parser from value=NULL format.subjectprefix configuration expects a string value. Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index dcc9f8179..9458428a8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -219,7 +219,7 @@ static int git_log_config(const char *var, const char *value) { if (!strcmp(var, "format.subjectprefix")) { if (!value) - die("format.subjectprefix without value"); + config_error_nonbool(var); fmt_patch_subject_prefix = xstrdup(value); return 0; } -- cgit v1.2.1 From 90f5c1864caf40ac2a0fef6bc771eab3ecc561b6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Feb 2008 13:09:16 -0800 Subject: builtin-log.c: guard config parser from value=NULL format.suffix expects a string value. format.numbered is bool plus "auto" Signed-off-by: Junio C Hamano --- builtin-log.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 9458428a8..99d69f079 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -432,7 +432,7 @@ static int git_format_config(const char *var, const char *value) } if (!strcmp(var, "format.suffix")) { if (!value) - die("format.suffix without value"); + return config_error_nonbool(var); fmt_patch_suffix = xstrdup(value); return 0; } @@ -440,11 +440,10 @@ static int git_format_config(const char *var, const char *value) return 0; } if (!strcmp(var, "format.numbered")) { - if (!strcasecmp(value, "auto")) { + if (value && !strcasecmp(value, "auto")) { auto_number = 1; return 0; } - numbered = git_config_bool(var, value); return 0; } -- cgit v1.2.1 From 3d51e1b5b84bde24f9a19e3cee603f0b57f62001 Mon Sep 17 00:00:00 2001 From: Martin Koegler Date: Mon, 18 Feb 2008 08:31:56 +0100 Subject: check return code of prepare_revision_walk A failure in prepare_revision_walk can be caused by a not parseable object. Signed-off-by: Martin Koegler Signed-off-by: Junio C Hamano --- builtin-log.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 99d69f079..5fea64aba 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -197,7 +197,8 @@ static int cmd_log_walk(struct rev_info *rev) if (rev->early_output) setup_early_output(rev); - prepare_revision_walk(rev); + if (prepare_revision_walk(rev)) + die("revision walk setup failed"); if (rev->early_output) finish_early_output(rev); @@ -556,7 +557,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha o2->flags ^= UNINTERESTING; add_pending_object(&check_rev, o1, "o1"); add_pending_object(&check_rev, o2, "o2"); - prepare_revision_walk(&check_rev); + if (prepare_revision_walk(&check_rev)) + die("revision walk setup failed"); while ((commit = get_revision(&check_rev)) != NULL) { /* ignore merges */ @@ -781,7 +783,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!use_stdout) realstdout = xfdopen(xdup(1), "w"); - prepare_revision_walk(&rev); + if (prepare_revision_walk(&rev)) + die("revision walk setup failed"); while ((commit = get_revision(&rev)) != NULL) { /* ignore merges */ if (commit->parents && commit->parents->next) @@ -923,7 +926,8 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) die("Unknown commit %s", limit); /* reverse the list of commits */ - prepare_revision_walk(&revs); + if (prepare_revision_walk(&revs)) + die("revision walk setup failed"); while ((commit = get_revision(&revs)) != NULL) { /* ignore merges */ if (commit->parents && commit->parents->next) -- cgit v1.2.1 From 6b2f2d9805dd22c6f74957e0d76a1d2921b40c16 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz Date: Mon, 18 Feb 2008 08:26:03 +0100 Subject: Add color.ui variable which globally enables colorization if set Signed-off-by: Matthias Kestenholz Signed-off-by: Junio C Hamano --- builtin-log.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 99d69f079..f2216d318 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -5,6 +5,7 @@ * 2006 Junio Hamano */ #include "cache.h" +#include "color.h" #include "commit.h" #include "diff.h" #include "revision.h" @@ -235,6 +236,10 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.diff = 1; rev.simplify_history = 0; @@ -307,6 +312,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) int i, count, ret = 0; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.diff = 1; rev.combine_merges = 1; @@ -367,6 +376,10 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); init_reflog_walk(&rev.reflog_info); rev.abbrev_commit = 1; @@ -395,6 +408,10 @@ int cmd_log(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.always_show_header = 1; cmd_log_init(argc, argv, prefix, &rev); -- cgit v1.2.1 From e1a37346210da8b165037984e02f750a6a135480 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 18 Feb 2008 22:56:06 -0500 Subject: Improve message-id generation flow control for format-patch Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 99d69f079..4f08ca40a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -575,16 +575,19 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha o2->flags = flags2; } -static void gen_message_id(char *dest, unsigned int length, char *base) +static void gen_message_id(struct rev_info *info, char *base) { const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME); const char *email_start = strrchr(committer, '<'); const char *email_end = strrchr(committer, '>'); - if(!email_start || !email_end || email_start > email_end - 1) + struct strbuf buf; + if (!email_start || !email_end || email_start > email_end - 1) die("Could not extract email from committer identity."); - snprintf(dest, length, "%s.%lu.git.%.*s", base, - (unsigned long) time(NULL), - (int)(email_end - email_start - 1), email_start + 1); + strbuf_init(&buf, 0); + strbuf_addf(&buf, "%s.%lu.git.%.*s", base, + (unsigned long) time(NULL), + (int)(email_end - email_start - 1), email_start + 1); + info->message_id = strbuf_detach(&buf, NULL); } static const char *clean_message_id(const char *msg_id) @@ -625,8 +628,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *in_reply_to = NULL; struct patch_ids ids; char *add_signoff = NULL; - char message_id[1024]; - char ref_message_id[1024]; git_config(git_format_config); init_revisions(&rev, prefix); @@ -809,15 +810,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.nr = total - nr + (start_number - 1); /* Make the second and subsequent mails replies to the first */ if (thread) { - if (nr == (total - 2)) { - strncpy(ref_message_id, message_id, - sizeof(ref_message_id)); - ref_message_id[sizeof(ref_message_id)-1]='\0'; - rev.ref_message_id = ref_message_id; + if (rev.message_id) { + if (rev.ref_message_id) + free(rev.message_id); + else + rev.ref_message_id = rev.message_id; } - gen_message_id(message_id, sizeof(message_id), - sha1_to_hex(commit->object.sha1)); - rev.message_id = message_id; + gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); } if (!use_stdout) if (reopen_stdout(commit, rev.nr, keep_subject, -- cgit v1.2.1 From a5a27c79b7e77e28462b6d089e827391b67d3e5f Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 18 Feb 2008 22:56:13 -0500 Subject: Add a --cover-letter option to format-patch If --cover-letter is provided, generate a cover letter message before the patches, numbered 0. Original patch thanks to Johannes Schindelin Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 232 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 174 insertions(+), 58 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 4f08ca40a..3dc765011 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -14,6 +14,7 @@ #include "reflog-walk.h" #include "patch-ids.h" #include "refs.h" +#include "run-command.h" static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; @@ -452,74 +453,81 @@ static int git_format_config(const char *var, const char *value) } +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 reopen_stdout(struct commit *commit, int nr, int keep_subject, - int numbered_files) +static int reopen_stdout(const char *oneline, int nr, int total) { char filename[PATH_MAX]; - char *sol; int len = 0; int suffix_len = strlen(fmt_patch_suffix) + 1; if (output_directory) { - if (strlen(output_directory) >= + len = snprintf(filename, sizeof(filename), "%s", + output_directory); + if (len >= sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len) return error("name of output directory is too long"); - strlcpy(filename, output_directory, sizeof(filename) - suffix_len); - len = strlen(filename); if (filename[len - 1] != '/') filename[len++] = '/'; } - if (numbered_files) { - sprintf(filename + len, "%d", nr); - len = strlen(filename); - - } else { - sprintf(filename + len, "%04d", nr); - len = strlen(filename); - - sol = strstr(commit->buffer, "\n\n"); - if (sol) { - int j, space = 1; - - 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; - } - if (len + suffix_len >= sizeof(filename)) - return error("Patch pathname too long"); + 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); } @@ -590,6 +598,76 @@ static void gen_message_id(struct rev_info *info, char *base) info->message_id = strbuf_detach(&buf, NULL); } +static void make_cover_letter(struct rev_info *rev, + int use_stdout, int numbered, int numbered_files, + struct commit *origin, struct commit *head) +{ + const char *committer; + const char *origin_sha1, *head_sha1; + const char *argv[7]; + const char *subject_start = NULL; + const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n"; + const char *msg; + const char *extra_headers = rev->extra_headers; + struct strbuf sb; + const char *encoding = "utf-8"; + + 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->total)) + return; + + origin_sha1 = sha1_to_hex(origin ? origin->object.sha1 : null_sha1); + head_sha1 = sha1_to_hex(head->object.sha1); + + log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers); + + committer = git_committer_info(0); + + msg = body; + strbuf_init(&sb, 0); + pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822, + encoding); + pp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers, + encoding, 0); + pp_remainder(CMIT_FMT_EMAIL, &msg, &sb, 0); + printf("%s\n", sb.buf); + + strbuf_release(&sb); + + /* + * We can only do diffstat with a unique reference point, and + * log is a bit tricky, so just skip it. + */ + if (!origin) + return; + + argv[0] = "shortlog"; + argv[1] = head_sha1; + argv[2] = "--not"; + argv[3] = origin_sha1; + argv[4] = "--"; + argv[5] = NULL; + fflush(stdout); + run_command_v_opt(argv, RUN_GIT_CMD); + + argv[0] = "diff"; + argv[1] = "--stat"; + argv[2] = "--summary"; + argv[3] = head_sha1; + argv[4] = "--not"; + argv[5] = origin_sha1; + argv[6] = "--"; + argv[7] = NULL; + fflush(stdout); + run_command_v_opt(argv, RUN_GIT_CMD); + + fflush(stdout); + printf("\n"); +} + static const char *clean_message_id(const char *msg_id) { char ch; @@ -625,6 +703,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int subject_prefix = 0; int ignore_if_in_upstream = 0; int thread = 0; + int cover_letter = 0; + struct commit *origin = NULL, *head = NULL; const char *in_reply_to = NULL; struct patch_ids ids; char *add_signoff = NULL; @@ -724,6 +804,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.subject_prefix = argv[i] + 17; } else if (!prefixcmp(argv[i], "--suffix=")) fmt_patch_suffix = argv[i] + 9; + else if (!strcmp(argv[i], "--cover-letter")) + cover_letter = 1; else argv[j++] = argv[i]; } @@ -775,6 +857,25 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * get_revision() to do the usual traversal. */ } + if (cover_letter) { + /* remember the range */ + int negative_count = 0; + int i; + for (i = 0; i < rev.pending.nr; i++) { + struct object *o = rev.pending.objects[i].item; + if (o->flags & UNINTERESTING) { + origin = (struct commit *)o; + negative_count++; + } else + head = (struct commit *)o; + } + /* Multiple origins don't work for diffstat. */ + if (negative_count > 1) + origin = NULL; + /* We can't generate a cover letter without any patches */ + if (!head) + return 0; + } if (ignore_if_in_upstream) get_patch_ids(&rev, &ids, prefix); @@ -801,16 +902,31 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) numbered = 1; if (numbered) rev.total = total + start_number - 1; - rev.add_signoff = add_signoff; if (in_reply_to) rev.ref_message_id = clean_message_id(in_reply_to); + if (cover_letter) { + if (thread) + gen_message_id(&rev, "cover"); + make_cover_letter(&rev, use_stdout, numbered, numbered_files, + origin, head); + total++; + start_number--; + } + rev.add_signoff = add_signoff; while (0 <= --nr) { int shown; commit = list[nr]; rev.nr = total - nr + (start_number - 1); /* Make the second and subsequent mails replies to the first */ if (thread) { + /* Have we already had a message ID? */ if (rev.message_id) { + /* + * If we've got the ID to be a reply + * to, discard the current ID; + * otherwise, make everything a reply + * to that. + */ if (rev.ref_message_id) free(rev.message_id); else @@ -818,10 +934,10 @@ 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) - if (reopen_stdout(commit, rev.nr, keep_subject, - numbered_files)) - die("Failed to create output files"); + if (!use_stdout && reopen_stdout(numbered_files ? NULL : + get_oneline_for_filename(commit, keep_subject), + rev.nr, rev.total)) + die("Failed to create output files"); shown = log_tree_commit(&rev, commit); free(commit->buffer); commit->buffer = NULL; -- cgit v1.2.1 From 7d22708b254d4ec28cd865dc5489d175ee6d65c2 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Tue, 19 Feb 2008 02:40:31 -0500 Subject: Fix format.headers not ending with a newline Now each value of format.headers will always be treated as a single valid header, and newlines will be inserted between them as needed. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 3dc765011..fe1a2d78e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -425,10 +425,14 @@ static int git_format_config(const char *var, const char *value) if (!value) die("format.headers without value"); len = strlen(value); - extra_headers_size += len + 1; + while (value[len - 1] == '\n') + len--; + extra_headers_size += len + 2; extra_headers = xrealloc(extra_headers, extra_headers_size); - extra_headers[extra_headers_size - len - 1] = 0; + extra_headers[extra_headers_size - len - 2] = 0; strcat(extra_headers, value); + extra_headers[extra_headers_size - 2] = '\n'; + extra_headers[extra_headers_size - 1] = 0; return 0; } if (!strcmp(var, "format.suffix")) { -- cgit v1.2.1 From 3ee79d9f59684778151804c02cc6ad155b30efde Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Tue, 19 Feb 2008 02:40:33 -0500 Subject: Combine To: and Cc: headers RFC 2822 only permits a single To: header and a single Cc: header, so we need to turn multiple values of each of these into a list. This will be particularly significant with a command-line option to add Cc: headers, where the user can't make sure to configure valid header sets in any easy way. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 14 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fe1a2d78e..71ae55b9e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -411,28 +411,47 @@ static int istitlechar(char c) (c >= '0' && c <= '9') || c == '.' || c == '_'; } -static char *extra_headers = NULL; -static int extra_headers_size = 0; static const char *fmt_patch_suffix = ".patch"; static int numbered = 0; static int auto_number = 0; +static char **extra_hdr; +static int extra_hdr_nr; +static int extra_hdr_alloc; + +static char **extra_to; +static int extra_to_nr; +static int extra_to_alloc; + +static char **extra_cc; +static int extra_cc_nr; +static int extra_cc_alloc; + +static void add_header(const char *value) +{ + int len = strlen(value); + while (value[len - 1] == '\n') + len--; + if (!strncasecmp(value, "to: ", 4)) { + ALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc); + extra_to[extra_to_nr++] = xstrndup(value + 4, len - 4); + return; + } + if (!strncasecmp(value, "cc: ", 4)) { + ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc); + extra_cc[extra_cc_nr++] = xstrndup(value + 4, len - 4); + return; + } + ALLOC_GROW(extra_hdr, extra_hdr_nr + 1, extra_hdr_alloc); + extra_hdr[extra_hdr_nr++] = xstrndup(value, len); +} + static int git_format_config(const char *var, const char *value) { if (!strcmp(var, "format.headers")) { - int len; - if (!value) die("format.headers without value"); - len = strlen(value); - while (value[len - 1] == '\n') - len--; - extra_headers_size += len + 2; - extra_headers = xrealloc(extra_headers, extra_headers_size); - extra_headers[extra_headers_size - len - 2] = 0; - strcat(extra_headers, value); - extra_headers[extra_headers_size - 2] = '\n'; - extra_headers[extra_headers_size - 1] = 0; + add_header(value); return 0; } if (!strcmp(var, "format.suffix")) { @@ -712,6 +731,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *in_reply_to = NULL; struct patch_ids ids; char *add_signoff = NULL; + struct strbuf buf; git_config(git_format_config); init_revisions(&rev, prefix); @@ -724,7 +744,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; - rev.extra_headers = extra_headers; /* * Parse the arguments before setup_revisions(), or something @@ -815,6 +834,37 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } argc = j; + strbuf_init(&buf, 0); + + for (i = 0; i < extra_hdr_nr; i++) { + strbuf_addstr(&buf, extra_hdr[i]); + strbuf_addch(&buf, '\n'); + } + + if (extra_to_nr) + strbuf_addstr(&buf, "To: "); + for (i = 0; i < extra_to_nr; i++) { + if (i) + strbuf_addstr(&buf, " "); + strbuf_addstr(&buf, extra_to[i]); + if (i + 1 < extra_to_nr) + strbuf_addch(&buf, ','); + strbuf_addch(&buf, '\n'); + } + + if (extra_cc_nr) + strbuf_addstr(&buf, "Cc: "); + for (i = 0; i < extra_cc_nr; i++) { + if (i) + strbuf_addstr(&buf, " "); + strbuf_addstr(&buf, extra_cc[i]); + if (i + 1 < extra_cc_nr) + strbuf_addch(&buf, ','); + strbuf_addch(&buf, '\n'); + } + + rev.extra_headers = strbuf_detach(&buf, 0); + if (start_number < 0) start_number = 1; if (numbered && keep_subject) -- cgit v1.2.1 From 736cc67dd7f4f8004215e24f876178e6f34c191d Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Tue, 19 Feb 2008 02:40:35 -0500 Subject: Support a --cc= option in format-patch When you have particular reviewers you want to sent particular series to, it's nice to be able to generate the whole series with them as additional recipients, without configuring them into your general headers or adding them by hand afterwards. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 71ae55b9e..0b348eb6b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -771,6 +771,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die("Need a number for --start-number"); start_number = strtol(argv[i], NULL, 10); } + else if (!prefixcmp(argv[i], "--cc=")) { + ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc); + extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5); + } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keep-subject")) { keep_subject = 1; -- cgit v1.2.1 From 2bda2cf4f966ae50d08a32a3839f930c1daac907 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 25 Feb 2008 18:24:17 -0500 Subject: Improve collection of information for format-patch --cover-letter Use the "boundary" feature to find the origin (or find that there are multiple origins), and use the actual list of commits to pass to shortlog. This makes all cover letter include shortlogs, and all cover letters for series with a single boundary commit include diffstats (if there are multiple boundary commits it's unclear what would be meaningful as a diffstat). Note that the single boundary test is empirical, not theoretical; even a -2 limiting condition will give a diffstat if there's only one boundary commit in this particular case. Signed-off-by: Daniel Barkalow --- builtin-log.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 0b348eb6b..3112d96db 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -15,6 +15,7 @@ #include "patch-ids.h" #include "refs.h" #include "run-command.h" +#include "shortlog.h" static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; @@ -621,9 +622,10 @@ static void gen_message_id(struct rev_info *info, char *base) info->message_id = strbuf_detach(&buf, NULL); } -static void make_cover_letter(struct rev_info *rev, - int use_stdout, int numbered, int numbered_files, - struct commit *origin, struct commit *head) +static void make_cover_letter(struct rev_info *rev, int use_stdout, + int numbered, int numbered_files, + struct commit *origin, + int nr, struct commit **list, struct commit *head) { const char *committer; const char *origin_sha1, *head_sha1; @@ -632,7 +634,9 @@ static void make_cover_letter(struct rev_info *rev, const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n"; const char *msg; const char *extra_headers = rev->extra_headers; + struct shortlog log; struct strbuf sb; + int i; const char *encoding = "utf-8"; if (rev->commit_format != CMIT_FMT_EMAIL) @@ -642,7 +646,6 @@ static void make_cover_letter(struct rev_info *rev, NULL : "cover-letter", 0, rev->total)) return; - origin_sha1 = sha1_to_hex(origin ? origin->object.sha1 : null_sha1); head_sha1 = sha1_to_hex(head->object.sha1); log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers); @@ -660,21 +663,19 @@ static void make_cover_letter(struct rev_info *rev, strbuf_release(&sb); + shortlog_init(&log); + for (i = 0; i < nr; i++) + shortlog_add_commit(&log, list[i]); + + shortlog_output(&log); + /* - * We can only do diffstat with a unique reference point, and - * log is a bit tricky, so just skip it. + * We can only do diffstat with a unique reference point */ if (!origin) return; - argv[0] = "shortlog"; - argv[1] = head_sha1; - argv[2] = "--not"; - argv[3] = origin_sha1; - argv[4] = "--"; - argv[5] = NULL; - fflush(stdout); - run_command_v_opt(argv, RUN_GIT_CMD); + origin_sha1 = sha1_to_hex(origin->object.sha1); argv[0] = "diff"; argv[1] = "--stat"; @@ -727,6 +728,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int ignore_if_in_upstream = 0; int thread = 0; int cover_letter = 0; + int boundary_count = 0; struct commit *origin = NULL, *head = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -917,19 +919,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (cover_letter) { /* remember the range */ - int negative_count = 0; int i; for (i = 0; i < rev.pending.nr; i++) { struct object *o = rev.pending.objects[i].item; - if (o->flags & UNINTERESTING) { - origin = (struct commit *)o; - negative_count++; - } else + if (!(o->flags & UNINTERESTING)) head = (struct commit *)o; } - /* Multiple origins don't work for diffstat. */ - if (negative_count > 1) - origin = NULL; /* We can't generate a cover letter without any patches */ if (!head) return 0; @@ -941,8 +936,17 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!use_stdout) realstdout = xfdopen(xdup(1), "w"); - prepare_revision_walk(&rev); + if (prepare_revision_walk(&rev)) + die("revision walk setup failed"); + rev.boundary = 1; while ((commit = get_revision(&rev)) != NULL) { + if (commit->object.flags & BOUNDARY) { + fprintf(stderr, "Boundary %s\n", sha1_to_hex(commit->object.sha1)); + boundary_count++; + origin = (boundary_count == 1) ? commit : NULL; + continue; + } + /* ignore merges */ if (commit->parents && commit->parents->next) continue; @@ -966,7 +970,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (thread) gen_message_id(&rev, "cover"); make_cover_letter(&rev, use_stdout, numbered, numbered_files, - origin, head); + origin, nr, list, head); total++; start_number--; } -- cgit v1.2.1 From 42be5cc61202014d4f1df61f9791067191f9393d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 27 Feb 2008 22:08:57 -0800 Subject: format-patch: remove a leftover debugging message Signed-off-by: Junio C Hamano --- builtin-log.c | 1 - 1 file changed, 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 3209ea5c6..836b61ec5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -960,7 +960,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.boundary = 1; while ((commit = get_revision(&rev)) != NULL) { if (commit->object.flags & BOUNDARY) { - fprintf(stderr, "Boundary %s\n", sha1_to_hex(commit->object.sha1)); boundary_count++; origin = (boundary_count == 1) ? commit : NULL; continue; -- cgit v1.2.1 From 39fe578bdcc318308bc5d75efa04bd4bfc3a4f23 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Thu, 28 Feb 2008 12:14:13 -0500 Subject: Use diff_tree() directly in making cover letter Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-log.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 836b61ec5..bbadbc0de 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -647,8 +647,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, int nr, struct commit **list, struct commit *head) { const char *committer; - const char *origin_sha1, *head_sha1; - const char *argv[7]; + char *head_sha1; const char *subject_start = NULL; const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n"; const char *msg; @@ -657,6 +656,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, struct strbuf sb; int i; const char *encoding = "utf-8"; + struct diff_options opts; if (rev->commit_format != CMIT_FMT_EMAIL) die("Cover letter needs email format"); @@ -694,20 +694,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, if (!origin) return; - origin_sha1 = sha1_to_hex(origin->object.sha1); + diff_setup(&opts); + opts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; - argv[0] = "diff"; - argv[1] = "--stat"; - argv[2] = "--summary"; - argv[3] = head_sha1; - argv[4] = "--not"; - argv[5] = origin_sha1; - argv[6] = "--"; - argv[7] = NULL; - fflush(stdout); - run_command_v_opt(argv, RUN_GIT_CMD); + diff_setup_done(&opts); + + diff_tree_sha1(origin->tree->object.sha1, + head->tree->object.sha1, + "", &opts); + diffcore_std(&opts); + diff_flush(&opts); - fflush(stdout); printf("\n"); } -- cgit v1.2.1 From 5d02294c776c46f0d454470c66c16fe9f08fad3d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 2 Mar 2008 15:53:04 +0000 Subject: format-patch: use the diff options for the cover letter, too Earlier, when you called "git format-patch --cover-letter -M", the diffstat in the cover letter would not inherit the "-M". Now it does. While at it, add a few "|| break" statements in the test's loops; otherwise, breakages inside the loops would not be caught. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index bbadbc0de..fd9b3ae95 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -694,8 +694,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, if (!origin) return; - diff_setup(&opts); - opts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; + memcpy(&opts, &rev->diffopt, sizeof(opts)); + opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; diff_setup_done(&opts); -- cgit v1.2.1 From 859c4fbef589841585f8f21cc567b7016681df7a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 2 Mar 2008 15:53:39 +0000 Subject: format-patch: wrap cover-letter's shortlog sensibly Earlier, overly-long onelines would not be wrapped at all, and indented with 6 spaces. Instead, we now wrap around at 72 characters, with a first-line indent of 2 spaces, and the rest with 4 spaces. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fd9b3ae95..fe8fc6f22 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -683,6 +683,10 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, strbuf_release(&sb); shortlog_init(&log); + log.wrap_lines = 1; + log.wrap = 72; + log.in1 = 2; + log.in2 = 4; for (i = 0; i < nr; i++) shortlog_add_commit(&log, list[i]); -- cgit v1.2.1 From 94c22a5e7b4247d7d6453272c4425d81071d2689 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Sun, 2 Mar 2008 17:05:53 +0800 Subject: log/show/whatchanged: introduce format.pretty configuration When running log/show/whatchanged from the command line, the user may want to use a preferred format without having to pass --pretty= option every time from the command line. This teaches these three commands to honor a new configuration variable, format.pretty. The --pretty option given from the command line will override the configured format. The earlier patch fixed the in-tree callers that run these commands for purposes other than showing the output directly to the end user (the only other in-tree caller is "git bisect visualize", whose output directly goes to the end user and should be affected by this patch). Similar fixes will be needed for end-user scripts that parse the output from these commands and expect them to be in the default pretty format. Signed-off-by: Denis Cheng Signed-off-by: Junio C Hamano --- builtin-log.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fe8fc6f22..d983cbc7b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -20,6 +20,7 @@ static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; +static const char *fmt_pretty; static void add_name_decoration(const char *prefix, const char *name, struct object *obj) { @@ -54,6 +55,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; + if (fmt_pretty) + rev->commit_format = get_commit_format(fmt_pretty); rev->verbose_header = 1; DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; @@ -221,6 +224,8 @@ static int cmd_log_walk(struct rev_info *rev) static int git_log_config(const char *var, const char *value) { + if (!strcmp(var, "format.pretty")) + return git_config_string(&fmt_pretty, var, value); if (!strcmp(var, "format.subjectprefix")) { if (!value) config_error_nonbool(var); -- cgit v1.2.1 From 4da45bef56e1547eb6525015ada0fdfc01d8295b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 7 Apr 2008 17:11:34 -0700 Subject: log: teach "terminator" vs "separator" mode to "--pretty=format" This attached patch introduces a single bit "use_terminator" in "struct rev_info", which is normally false (i.e. most formats use separator semantics) but by flipping it to true, you can ask for terminator semantics just like oneline format does. The function get_commit_format(), which is what parses "--pretty=" option, now takes a pointer to "struct rev_info" and updates its commit_format and use_terminator fields. It used to return the value of type "enum cmit_fmt", but all the callers assigned it to rev->commit_format. There are only two cases the code turns use_terminator on. Obviously, the traditional oneline format (--pretty=oneline) is one of them, and the new case is --pretty=tformat:... that acts like --pretty=format:... but flips the bit on. With this, "--pretty=tformat:%H %s" acts like --pretty=oneline. Signed-off-by: Junio C Hamano --- builtin-log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5c00725f0..1670d0b33 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -56,7 +56,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; if (fmt_pretty) - rev->commit_format = get_commit_format(fmt_pretty); + get_commit_format(fmt_pretty, rev); rev->verbose_header = 1; DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; @@ -400,6 +400,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) * allow us to set a different default. */ rev.commit_format = CMIT_FMT_ONELINE; + rev.use_terminator = 1; rev.always_show_header = 1; /* -- cgit v1.2.1 From fe8928e6e802f8519e133f085783fb664f1a0d6b Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Sat, 26 Apr 2008 23:19:06 +0200 Subject: git-format-patch: add a new format.cc configuration variable Some projects prefer to always CC patches to a given mailing list. In these cases, it's handy to configure that address once. Signed-off-by: Miklos Vajna Signed-off-by: Junio C Hamano --- builtin-log.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 1670d0b33..d7907c942 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -485,6 +485,13 @@ static int git_format_config(const char *var, const char *value) fmt_patch_suffix = xstrdup(value); return 0; } + if (!strcmp(var, "format.cc")) { + if (!value) + return config_error_nonbool(var); + ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc); + extra_cc[extra_cc_nr++] = xstrdup(value); + return 0; + } if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } -- cgit v1.2.1 From 028656552bc758b192027c25a1143f1c6ca66d64 Mon Sep 17 00:00:00 2001 From: Adam Simpkins Date: Tue, 29 Apr 2008 01:32:59 -0700 Subject: Remove dead code: show_log() sep argument and diff_options.msg_sep These variables were made unnecessary by commit 3969cf7db1a13a78f3b7a36d8c1084bbe0a53459. Signed-off-by: Adam Simpkins Signed-off-by: Junio C Hamano --- builtin-log.c | 1 - 1 file changed, 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 1670d0b33..256bbac93 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -770,7 +770,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diff = 1; rev.combine_merges = 0; rev.ignore_merges = 1; - rev.diffopt.msg_sep = ""; DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; -- cgit v1.2.1 From 37c22a4bf801403f71a5e9674d8e314ce575945e Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Fri, 9 May 2008 19:55:43 -0300 Subject: git-format-patch: add --no-binary to omit binary changes in the patch. Add a new option --no-binary to git-format-patch so that no binary changes are included in the generated patches, only notices that those files changed. This generate patches that cannot be applied, but still is useful for generating mails for code review purposes. See also: commit e47f306d4bf964def1a0b29e8f7cea419471dffd, where --binary option was turned on by default. Signed-off-by: Caio Marcelo de Oliveira Filho Signed-off-by: Junio C Hamano --- builtin-log.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 256bbac93..80a01f8d4 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -757,6 +757,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int thread = 0; int cover_letter = 0; int boundary_count = 0; + int no_binary_diff = 0; struct commit *origin = NULL, *head = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -862,6 +863,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) fmt_patch_suffix = argv[i] + 9; else if (!strcmp(argv[i], "--cover-letter")) cover_letter = 1; + else if (!strcmp(argv[i], "--no-binary")) + no_binary_diff = 1; else argv[j++] = argv[i]; } @@ -914,7 +917,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH; - if (!DIFF_OPT_TST(&rev.diffopt, TEXT)) + if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff) DIFF_OPT_SET(&rev.diffopt, BINARY); if (!output_directory && !use_stdout) -- cgit v1.2.1 From ef90d6d4208a5130185b04f06e5f90a5f9959fe3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 14 May 2008 18:46:53 +0100 Subject: Provide git_config with a callback-data parameter git_config() only had a function parameter, but no callback data parameter. This assumes that all callback functions only modify global variables. With this patch, every callback gets a void * parameter, and it is hoped that this will help the libification effort. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-log.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 80a01f8d4..addc7098c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -222,7 +222,7 @@ static int cmd_log_walk(struct rev_info *rev) return 0; } -static int git_log_config(const char *var, const char *value) +static int git_log_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.pretty")) return git_config_string(&fmt_pretty, var, value); @@ -236,14 +236,14 @@ static int git_log_config(const char *var, const char *value) default_show_root = git_config_bool(var, value); return 0; } - return git_diff_ui_config(var, value); + return git_diff_ui_config(var, value, cb); } int cmd_whatchanged(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -319,7 +319,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) struct object_array_entry *objects; int i, count, ret = 0; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -383,7 +383,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -416,7 +416,7 @@ int cmd_log(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -471,7 +471,7 @@ static void add_header(const char *value) extra_hdr[extra_hdr_nr++] = xstrndup(value, len); } -static int git_format_config(const char *var, const char *value) +static int git_format_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.headers")) { if (!value) @@ -497,7 +497,7 @@ static int git_format_config(const char *var, const char *value) return 0; } - return git_log_config(var, value); + return git_log_config(var, value, cb); } @@ -764,7 +764,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) char *add_signoff = NULL; struct strbuf buf; - git_config(git_format_config); + git_config(git_format_config, NULL); init_revisions(&rev, prefix); rev.commit_format = CMIT_FMT_EMAIL; rev.verbose_header = 1; -- cgit v1.2.1 From dd0ffd5b31a672db90d8b775988d55829e6f5f9f Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Thu, 22 May 2008 18:24:07 +0300 Subject: Add log.date config variable log.date config variable sets the default date-time mode for the log command. Setting log.date value is similar to using git log's --date option. Signed-off-by: Heikki Orsila Signed-off-by: Junio C Hamano --- builtin-log.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 9d046b2e0..543855b7a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -18,6 +18,9 @@ #include "run-command.h" #include "shortlog.h" +/* Set a default date-time format for git log ("log.date" config variable) */ +static const char *default_date_mode = NULL; + static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; @@ -61,7 +64,12 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; + + if (default_date_mode) + rev->date_mode = parse_date_format(default_date_mode); + argc = setup_revisions(argc, argv, rev, "HEAD"); + if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) { @@ -232,6 +240,8 @@ static int git_log_config(const char *var, const char *value) fmt_patch_subject_prefix = xstrdup(value); return 0; } + if (!strcmp(var, "log.date")) + return git_config_string(&default_date_mode, var, value); if (!strcmp(var, "log.showroot")) { default_show_root = git_config_bool(var, value); return 0; -- cgit v1.2.1 From 4f3dcc2753ef6c244622334cef94a72682fcd850 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Tue, 1 Jul 2008 11:47:04 +0200 Subject: Fix 'git show' on signed tag of signed tag of commit The cmd_show loop resolves tags by showing them, then pointing the object to the 'tagged' member. However, this object is not fully initialized; it only contains the SHA1. (This resulted in a segfault if there were two levels of tags.) We apply parse_object to get a full object. Noticed by Kalle Olavi Niemitalo on IRC. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 9817d6fbe..9979e37f3 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -360,7 +360,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); ret = show_object(o->sha1, 1, &rev); - objects[i].item = (struct object *)t->tagged; + objects[i].item = parse_object(t->tagged->sha1); i--; break; } -- cgit v1.2.1 From 70cff3ac16e842e465f304e7af3b588840899dc9 Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Sat, 5 Jul 2008 01:24:41 -0400 Subject: builtin-log.c: Use 'git_config_string' to get 'format.subjectprefix' and 'format.suffix' Signed-off-by: Brian Hetro Signed-off-by: Junio C Hamano --- builtin-log.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 9979e37f3..430d87661 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -234,12 +234,8 @@ static int git_log_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.pretty")) return git_config_string(&fmt_pretty, var, value); - if (!strcmp(var, "format.subjectprefix")) { - if (!value) - config_error_nonbool(var); - fmt_patch_subject_prefix = xstrdup(value); - return 0; - } + if (!strcmp(var, "format.subjectprefix")) + return git_config_string(&fmt_patch_subject_prefix, var, value); if (!strcmp(var, "log.date")) return git_config_string(&default_date_mode, var, value); if (!strcmp(var, "log.showroot")) { @@ -489,12 +485,8 @@ static int git_format_config(const char *var, const char *value, void *cb) add_header(value); return 0; } - if (!strcmp(var, "format.suffix")) { - if (!value) - return config_error_nonbool(var); - fmt_patch_suffix = xstrdup(value); - return 0; - } + if (!strcmp(var, "format.suffix")) + return git_config_string(&fmt_patch_suffix, var, value); if (!strcmp(var, "format.cc")) { if (!value) return config_error_nonbool(var); -- cgit v1.2.1 From 1b1dd23f2d6a707b7077cdf6bc6d4055bd0bfb7d Mon Sep 17 00:00:00 2001 From: Stephan Beyer Date: Sun, 13 Jul 2008 15:36:15 +0200 Subject: Make usage strings dash-less When you misuse a git command, you are shown the usage string. But this is currently shown in the dashed form. So if you just copy what you see, it will not work, when the dashed form is no longer supported. This patch makes git commands show the dash-less version. For shell scripts that do not specify OPTIONS_SPEC, git-sh-setup.sh generates a dash-less usage string now. Signed-off-by: Stephan Beyer Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 430d87661..cb3b33a4f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1082,7 +1082,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) } static const char cherry_usage[] = -"git-cherry [-v] [] []"; +"git cherry [-v] [] []"; int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; -- cgit v1.2.1 From 671f0707212c929533dc6ec9e032faee328e4602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Mon, 14 Jul 2008 21:22:12 +0200 Subject: add context pointer to read_tree_recursive() Add a pointer parameter to read_tree_recursive(), which is passed to the callback function. This allows callers of read_tree_recursive() to share data with the callback without resorting to global variables. All current callers pass NULL. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 430d87661..617aa67f2 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -313,7 +313,7 @@ static int show_object(const unsigned char *sha1, int show_tag_object, static int show_tree_object(const unsigned char *sha1, const char *base, int baselen, - const char *pathname, unsigned mode, int stage) + const char *pathname, unsigned mode, int stage, void *context) { printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); return 0; @@ -366,7 +366,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) name, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); read_tree_recursive((struct tree *)o, "", 0, 0, NULL, - show_tree_object); + show_tree_object, NULL); break; case OBJ_COMMIT: rev.pending.nr = rev.pending.alloc = 0; -- cgit v1.2.1 From 036d17feda327c509c712dd1054a12d067166667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Valdemar=20M=C3=B8rch?= Date: Mon, 11 Aug 2008 08:46:24 +0200 Subject: Teach git log --check to return an appropriate exit code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Valdemar Mørch Signed-off-by: Junio C Hamano --- builtin-log.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index f4975cf35..ae7154054 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -217,6 +217,11 @@ static int cmd_log_walk(struct rev_info *rev) if (rev->early_output) finish_early_output(rev); + /* + * For --check, the exit code is based on CHECK_FAILED being + * accumulated in rev->diffopt, so be careful to retain that state + * information if replacing rev->diffopt in this loop + */ while ((commit = get_revision(rev)) != NULL) { log_tree_commit(rev, commit); if (!rev->reflog_info) { @@ -227,6 +232,10 @@ static int cmd_log_walk(struct rev_info *rev) free_commit_list(commit->parents); commit->parents = NULL; } + if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && + DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) { + return 02; + } return 0; } -- cgit v1.2.1 From 84102a338df08a365ed0336304322adc05bc1581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Valdemar=20M=C3=B8rch?= Date: Mon, 11 Aug 2008 08:46:25 +0200 Subject: Teach git log --exit-code to return an appropriate exit code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Valdemar Mørch 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 ae7154054..3a7957483 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -218,9 +218,9 @@ static int cmd_log_walk(struct rev_info *rev) finish_early_output(rev); /* - * For --check, the exit code is based on CHECK_FAILED being - * accumulated in rev->diffopt, so be careful to retain that state - * information if replacing rev->diffopt in this loop + * For --check and --exit-code, the exit code is based on CHECK_FAILED + * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to + * retain that state information if replacing rev->diffopt in this loop */ while ((commit = get_revision(rev)) != NULL) { log_tree_commit(rev, commit); @@ -236,7 +236,7 @@ static int cmd_log_walk(struct rev_info *rev) DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) { return 02; } - return 0; + return diff_result_code(&rev->diffopt, 0); } static int git_log_config(const char *var, const char *value, void *cb) -- cgit v1.2.1 From c8c4450e1949055cb57e32425b125f45f3481742 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Tue, 19 Aug 2008 20:42:04 +0200 Subject: git format-patch: avoid underrun when format.headers is empty or all NLs * builtin-log.c (add_header): Avoid a buffer underrun when format.headers is empty or all newlines. Reproduce with this: git config format.headers '' && git format-patch -1 Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index f4975cf35..911fd6599 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -461,7 +461,7 @@ static int extra_cc_alloc; static void add_header(const char *value) { int len = strlen(value); - while (value[len - 1] == '\n') + while (len && value[len - 1] == '\n') len--; if (!strncasecmp(value, "to: ", 4)) { ALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc); -- cgit v1.2.1 From 68daa64df2363f848d818dda9fc414511d9330da Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 24 Aug 2008 22:10:29 -0400 Subject: format-patch: use default diff format even with patch options Previously, running "git format-patch -U5" would cause the low-level diff machinery to change the diff output format from "not specified" to "patch". This meant that format-patch thought we explicitly specified a diff output format, and would not use the default format. The resulting message lacked both the diffstat and the summary, as well as the separating "---". Now format-patch explicitly checks for this condition and uses the default. That means that "git format-patch -p" will now have the "-p" ignored. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 9204ffd76..1d3c5cbf5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -932,7 +932,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (argc > 1) die ("unrecognized argument: %s", argv[1]); - if (!rev.diffopt.output_format) + if (!rev.diffopt.output_format + || rev.diffopt.output_format == DIFF_FORMAT_PATCH) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH; if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff) -- cgit v1.2.1 From 5e9bf11c1a3052f01f86d7eb28ae4c5b8d9c7495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 4 Sep 2008 23:38:08 +0200 Subject: log: add load_ref_decorations() Move the loading of all ref names for decoration into its own function. A static variable prevents loading twice, because it's quite expensive. We can do it this way because we currently never unload decorations. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin-log.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 1d3c5cbf5..0f164620b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -50,6 +50,15 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in return 0; } +void load_ref_decorations(void) +{ + static int loaded; + if (!loaded) { + loaded = 1; + for_each_ref(add_ref_decoration, NULL); + } +} + static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { @@ -80,8 +89,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { - if (!decorate) - for_each_ref(add_ref_decoration, NULL); + load_ref_decorations(); decorate = 1; } else die("unrecognized argument: %s", arg); -- cgit v1.2.1 From cab4feb67db64d3d201145d9748b33d148f96185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 4 Sep 2008 23:39:21 +0200 Subject: move load_ref_decorations() to log-tree.c and export it log-tree.c is the ideal place for load_ref_decorations() and its helper functions to live in, because the variable name_decoration they're operating on is already located there, so move them thither. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin-log.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 0f164620b..081e660f6 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -14,7 +14,6 @@ #include "tag.h" #include "reflog-walk.h" #include "patch-ids.h" -#include "refs.h" #include "run-command.h" #include "shortlog.h" @@ -25,40 +24,6 @@ static int default_show_root = 1; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; -static void add_name_decoration(const char *prefix, const char *name, struct object *obj) -{ - int plen = strlen(prefix); - int nlen = strlen(name); - struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen); - memcpy(res->name, prefix, plen); - memcpy(res->name + plen, name, nlen + 1); - res->next = add_decoration(&name_decoration, obj, res); -} - -static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data) -{ - struct object *obj = parse_object(sha1); - if (!obj) - return 0; - add_name_decoration("", refname, obj); - while (obj->type == OBJ_TAG) { - obj = ((struct tag *)obj)->tagged; - if (!obj) - break; - add_name_decoration("tag: ", refname, obj); - } - return 0; -} - -void load_ref_decorations(void) -{ - static int loaded; - if (!loaded) { - loaded = 1; - for_each_ref(add_ref_decoration, NULL); - } -} - static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { -- cgit v1.2.1 From 597faa00fdf69491c331f748fc62453726354629 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 19 Sep 2008 15:42:30 +0200 Subject: Typo "bogos" in format-patch error message. Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 911fd6599..2efe59373 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -835,7 +835,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) committer = git_committer_info(IDENT_ERROR_ON_NO_NAME); endpos = strchr(committer, '>'); if (!endpos) - die("bogos committer info %s\n", committer); + die("bogus committer info %s\n", committer); add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { -- cgit v1.2.1 From f285a2d7ed6548666989406de8f0e7233eb84368 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 9 Oct 2008 14:12:12 -0500 Subject: Replace calls to strbuf_init(&foo, 0) with STRBUF_INIT initializer Many call sites use strbuf_init(&foo, 0) to initialize local strbuf variable "foo" which has not been accessed since its declaration. These can be replaced with a static initialization using the STRBUF_INIT macro which is just as readable, saves a function call, and takes up fewer lines. Signed-off-by: Brandon Casey Signed-off-by: Shawn O. Pearce --- builtin-log.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index fc5e4da82..794821f6b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -628,10 +628,9 @@ static void gen_message_id(struct rev_info *info, char *base) const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME); const char *email_start = strrchr(committer, '<'); const char *email_end = strrchr(committer, '>'); - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; if (!email_start || !email_end || email_start > email_end - 1) die("Could not extract email from committer identity."); - strbuf_init(&buf, 0); strbuf_addf(&buf, "%s.%lu.git.%.*s", base, (unsigned long) time(NULL), (int)(email_end - email_start - 1), email_start + 1); @@ -650,7 +649,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, const char *msg; const char *extra_headers = rev->extra_headers; struct shortlog log; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; int i; const char *encoding = "utf-8"; struct diff_options opts; @@ -671,7 +670,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, committer = git_committer_info(0); msg = body; - strbuf_init(&sb, 0); pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822, encoding); pp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers, @@ -753,7 +751,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *in_reply_to = NULL; struct patch_ids ids; char *add_signoff = NULL; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; git_config(git_format_config, NULL); init_revisions(&rev, prefix); @@ -861,8 +859,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } argc = j; - strbuf_init(&buf, 0); - for (i = 0; i < extra_hdr_nr; i++) { strbuf_addstr(&buf, extra_hdr[i]); strbuf_addch(&buf, '\n'); @@ -1139,8 +1135,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; pretty_print_commit(CMIT_FMT_ONELINE, commit, &buf, 0, NULL, NULL, 0, 0); printf("%c %s %s\n", sign, -- cgit v1.2.1 From a567fdcb016e8e882ec0a1e044c9caac8f70e693 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Thu, 2 Oct 2008 16:55:39 -0400 Subject: format-patch: autonumber by default format-patch is most commonly used for multiple patches at once when sending a patchset, in which case we want to number the patches; on the other hand, single patches are not usually expected to be numbered. In other words, the typical behavior expected from format-patch is the one obtained by enabling autonumber, so we set it to be the default. Users that want to disable numbering for a particular patchset can do so with the existing -N command-line switch. Users that want to change the default behavior can use the format.numbering config key. Signed-off-by: Brian Gernhardt Test-updates-by: Jeff King Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 794821f6b..a0944f70a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -426,7 +426,7 @@ static int istitlechar(char c) static const char *fmt_patch_suffix = ".patch"; static int numbered = 0; -static int auto_number = 0; +static int auto_number = 1; static char **extra_hdr; static int extra_hdr_nr; @@ -485,6 +485,7 @@ static int git_format_config(const char *var, const char *value, void *cb) return 0; } numbered = git_config_bool(var, value); + auto_number = auto_number && numbered; return 0; } -- cgit v1.2.1 From c7534ef4a12bb44806d522fc8e3961e390f9169b Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 26 Oct 2008 00:45:55 -0400 Subject: userdiff: require explicitly allowing textconv Diffs that have been produced with textconv almost certainly cannot be applied, so we want to be careful not to generate them in things like format-patch. This introduces a new diff options, ALLOW_TEXTCONV, which controls this behavior. It is off by default, but is explicitly turned on for the "log" family of commands, as well as the "diff" porcelain (but not diff-* plumbing). Because both text conversion and external diffing are controlled by these diff options, we can get rid of the "plumbing versus porcelain" distinction when reading the config. This was an attempt to control the same thing, but suffered from being too coarse-grained. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-log.c | 1 + 1 file changed, 1 insertion(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index a0944f70a..75d698f0c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -59,6 +59,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } else die("unrecognized argument: %s", arg); } + DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); } /* -- cgit v1.2.1 From 0f3a290b89b89bb5375cf5019b067e4a99f02620 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 27 Oct 2008 12:51:59 -0700 Subject: Add a 'source' decorator for commits We already support decorating commits by tags or branches that point to them, but especially when we are looking at multiple branches together, we sometimes want to see _how_ we reached a particular commit. We can abuse the '->util' field in the commit to keep track of that as we walk the commit lists, and get a reasonably useful view into which branch or tag first reaches that commit. Of course, if the commit is reachable through multiple sources (which is common), our particular choice of "first" reachable is entirely random and depends on the particular path we happened to follow. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index a0944f70a..176cbce30 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -56,6 +56,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, if (!strcmp(arg, "--decorate")) { load_ref_decorations(); decorate = 1; + } else if (!strcmp(arg, "--source")) { + rev->show_source = 1; } else die("unrecognized argument: %s", arg); } -- cgit v1.2.1 From d467a525da28b28a0d8e16a42e121ab638fa7347 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 3 Nov 2008 11:23:57 -0800 Subject: Make '--decorate' set an explicit 'show_decorations' flag We will want to add decorations without necessarily showing them, so add an explicit revisions info flag as to whether we're showing decorations or not. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 176cbce30..82ea07b1b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -28,7 +28,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; - int decorate = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -55,7 +54,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { load_ref_decorations(); - decorate = 1; + rev->show_decorations = 1; } else if (!strcmp(arg, "--source")) { rev->show_source = 1; } else -- cgit v1.2.1 From 5ec11af61d907311e4e1b21e10009b06dc2cf74a Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 7 Dec 2008 21:54:17 -0500 Subject: reorder ALLOW_TEXTCONV option setting Right now for the diff porcelain and the log family, we call: init_revisions(); setup_revisions(); DIFF_OPT_SET(ALLOW_TEXTCONV); However, that means textconv will _always_ be on, instead of being a default that can be manipulated with setup_revisions. Instead, we want: init_revisions(); DIFF_OPT_SET(ALLOW_TEXTCONV); setup_revisions(); which is what this patch does. We'll go ahead and move the callsite in wt-status, also; even though the user can't pass any options here, it is a cleanup that will help avoid any surprise later if the setup_revisions line is changed. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index b16471737..840daf907 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -37,6 +37,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; + DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); if (default_date_mode) rev->date_mode = parse_date_format(default_date_mode); @@ -60,7 +61,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } else die("unrecognized argument: %s", arg); } - DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); } /* -- cgit v1.2.1 From d2dadfe890b5da6f65fe061a414b6ec67c5efe9c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 15 Dec 2008 00:36:56 -0800 Subject: git-show: do not segfault when showing a bad tag When a tag points at a bad or nonexistent object, we should diagnose the breakage and exit. An earlier commit 4f3dcc2 (Fix 'git show' on signed tag of signed tag of commit, 2008-07-01) lost this check and made it segfault instead; not good. This fixes it. Signed-off-by: Junio C Hamano --- builtin-log.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 2efe59373..db71e0da7 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -356,7 +356,13 @@ int cmd_show(int argc, const char **argv, const char *prefix) t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); ret = show_object(o->sha1, 1, &rev); - objects[i].item = parse_object(t->tagged->sha1); + if (ret) + break; + o = parse_object(t->tagged->sha1); + if (!o) + ret = error("Could not read object %s", + sha1_to_hex(t->tagged->sha1)); + objects[i].item = o; i--; break; } -- cgit v1.2.1 From f29680221124d05581dd2db52a4e7f0fa15fa929 Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Mon, 29 Dec 2008 18:45:20 +0100 Subject: git-cherry: make parameter optional The upstream branch now defaults to the first tracked remote branch, which is set by the configuration variables branch..remote and branch..merge of the current branch. Without such a remote branch, the command "git cherry [-v]" fails with usage output as before and an additional message. Signed-off-by: Markus Heidelberg Signed-off-by: Junio C Hamano --- builtin-log.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 99d1137b0..243f8573e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -16,6 +16,7 @@ #include "patch-ids.h" #include "run-command.h" #include "shortlog.h" +#include "remote.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -1070,13 +1071,14 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) } static const char cherry_usage[] = -"git cherry [-v] [] []"; +"git cherry [-v] [] [] []"; int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; struct patch_ids ids; struct commit *commit; struct commit_list *list = NULL; + struct branch *current_branch; const char *upstream; const char *head = "HEAD"; const char *limit = NULL; @@ -1099,7 +1101,17 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) upstream = argv[1]; break; default: - usage(cherry_usage); + current_branch = branch_get(NULL); + if (!current_branch || !current_branch->merge + || !current_branch->merge[0] + || !current_branch->merge[0]->dst) { + fprintf(stderr, "Could not find a tracked" + " remote branch, please" + " specify manually.\n"); + usage(cherry_usage); + } + + upstream = current_branch->merge[0]->dst; } init_revisions(&revs, prefix); -- cgit v1.2.1 From ea718e65fab17297a8a9dbebf63ae99096e9537a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 2 Jan 2009 19:08:43 +0100 Subject: show : reuse pp_user_info() instead of duplicating code We used to extract the tagger information "by hand" in "git show ", but the function pp_user_info() already does that. Even better: it respects the commit_format and date_format specified by the user. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-log.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 99d1137b0..bc4e1e965 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -249,22 +249,13 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) static void show_tagger(char *buf, int len, struct rev_info *rev) { - char *email_end, *p; - unsigned long date; - int tz; + struct strbuf out = STRBUF_INIT; - email_end = memchr(buf, '>', len); - if (!email_end) - return; - p = ++email_end; - while (isspace(*p)) - p++; - date = strtoul(p, &p, 10); - while (isspace(*p)) - p++; - tz = (int)strtol(p, NULL, 10); - printf("Tagger: %.*s\nDate: %s\n", (int)(email_end - buf), buf, - show_date(date, tz, rev->date_mode)); + pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode, + git_log_output_encoding ? + git_log_output_encoding: git_commit_encoding); + printf("%s\n", out.buf); + strbuf_release(&out); } static int show_object(const unsigned char *sha1, int show_tag_object, -- cgit v1.2.1 From 3bc52d7a95676bcdeeb61c372b44358daf817baa Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Thu, 1 Jan 2009 22:56:29 +0100 Subject: Documentation: clarify which parameters are optional to git-cherry An earlier parameter is only optional when all of the later parameters are omitted. Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 243f8573e..7e9616e5e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1071,7 +1071,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) } static const char cherry_usage[] = -"git cherry [-v] [] [] []"; +"git cherry [-v] [ [ []]]"; int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; -- cgit v1.2.1 From d75307084da5f89329de190bb9b4a3196cec1d0e Mon Sep 17 00:00:00 2001 From: Alexander Potashev Date: Sun, 4 Jan 2009 21:38:41 +0300 Subject: remove trailing LF in die() messages LF at the end of format strings given to die() is redundant because die already adds one on its own. Signed-off-by: Alexander Potashev Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index bc4e1e965..4a02ee987 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -815,7 +815,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) committer = git_committer_info(IDENT_ERROR_ON_NO_NAME); endpos = strchr(committer, '>'); if (!endpos) - die("bogus committer info %s\n", committer); + die("bogus committer info %s", committer); add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { -- cgit v1.2.1 From 68c2ec7f43c4dc16833ff58af76ab20e9cdfad17 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Jan 2009 12:41:33 -0800 Subject: format-patch: show patch text for the root commit Even without --root specified, if the range given on the command line happens to include a root commit, we should include its patch text in the output. This fix deliberately ignores log.showroot configuration variable because "format-patch" and "log -p" can and should behave differently in this case, as the former is about exporting a part of your history in a form that is replayable elsewhere and just giving the commit log message without the patch text does not make any sense for that purpose. Noticed and fix originally attempted by Nathan W. Panike; credit goes to Alexander Potashev for injecting sanity to my initial (broken) fix that used the value from log.showroot configuration, which was misguided. Signed-off-by: Junio C Hamano --- builtin-log.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index db71e0da7..5e302906f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -962,6 +962,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * get_revision() to do the usual traversal. */ } + + /* + * We cannot move this anywhere earlier because we do want to + * know if --root was given explicitly from the comand line. + */ + rev.show_root_diff = 1; + if (cover_letter) { /* remember the range */ int i; -- cgit v1.2.1 From 9800a754f931d05c2d26da9c1b188ae2c2b80eb4 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 12 Jan 2009 15:18:02 -0800 Subject: Teach format-patch to handle output directory relative to cwd Without any explicit -o parameter, we correctly avoided putting the resulting patch output to the toplevel. We should do the same when the user gave a relative pathname to be consistent with this case. Noticed by Cesar Eduardo Barros. Signed-off-by: Junio C Hamano --- builtin-log.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index db71e0da7..16a0f11c5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -568,6 +568,7 @@ static const char *get_oneline_for_filename(struct commit *commit, static FILE *realstdout = NULL; static const char *output_directory = NULL; +static int outdir_offset; static int reopen_stdout(const char *oneline, int nr, int total) { @@ -594,7 +595,7 @@ static int reopen_stdout(const char *oneline, int nr, int total) strcpy(filename + len, fmt_patch_suffix); } - fprintf(realstdout, "%s\n", filename); + fprintf(realstdout, "%s\n", filename + outdir_offset); if (freopen(filename, "w", stdout) == NULL) return error("Cannot open patch file %s",filename); @@ -757,6 +758,27 @@ static const char *clean_message_id(const char *msg_id) return xmemdupz(a, z - a); } +static const char *set_outdir(const char *prefix, const char *output_directory) +{ + if (output_directory && is_absolute_path(output_directory)) + return output_directory; + + if (!prefix || !*prefix) { + if (output_directory) + return output_directory; + /* The user did not explicitly ask for "./" */ + outdir_offset = 2; + return "./"; + } + + outdir_offset = strlen(prefix); + if (!output_directory) + return prefix; + + return xstrdup(prefix_filename(prefix, outdir_offset, + output_directory)); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -935,8 +957,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff) DIFF_OPT_SET(&rev.diffopt, BINARY); - if (!output_directory && !use_stdout) - output_directory = prefix; + if (!use_stdout) + output_directory = set_outdir(prefix, output_directory); if (output_directory) { if (use_stdout) -- cgit v1.2.1 From 0db5260bd033cc357186cc13fe23be9635ad69e7 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 12 Feb 2009 09:51:55 -0600 Subject: Enable setting attach as the default in .gitconfig for git-format-patch. Signed-off-by: Jeremy White Signed-off-by: Junio C Hamano --- builtin-log.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 2ae39afcc..854902881 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -428,6 +428,8 @@ static const char *fmt_patch_suffix = ".patch"; static int numbered = 0; static int auto_number = 1; +static char *default_attach = NULL; + static char **extra_hdr; static int extra_hdr_nr; static int extra_hdr_alloc; @@ -488,6 +490,14 @@ static int git_format_config(const char *var, const char *value, void *cb) auto_number = auto_number && numbered; return 0; } + if (!strcmp(var, "format.attach")) { + if (value && *value) + default_attach = xstrdup(value); + else + default_attach = xstrdup(git_version_string); + return 0; + } + return git_log_config(var, value, cb); } @@ -787,6 +797,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.subject_prefix = fmt_patch_subject_prefix; + if (default_attach) { + rev.mime_boundary = default_attach; + rev.no_inline = 1; + } + /* * Parse the arguments before setup_revisions(), or something * like "git format-patch -o a123 HEAD^.." may fail; a123 is @@ -849,6 +864,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.mime_boundary = argv[i] + 9; rev.no_inline = 1; } + else if (!strcmp(argv[i], "--no-attach")) { + rev.mime_boundary = NULL; + rev.no_inline = 0; + } else if (!strcmp(argv[i], "--inline")) { rev.mime_boundary = git_version_string; rev.no_inline = 0; -- cgit v1.2.1 From b079c50e03a812f5c8197b8f38e0a5fe6dd31321 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:31 +0100 Subject: format-patch: track several references Currently, format-patch can only track a single reference (the In-Reply-To:) for each mail. To ensure proper threading, we should list all known references for every mail. Change the rev_info.ref_message_id field to a string_list, so that we can append references at will, and change the output formatting routines to print all of them in the References: header. The last entry in the list is implicitly assumed to be the In-Reply-To:, which gives output consistent with RFC 2822: The "References:" field will contain the contents of the parent's "References:" field (if any) followed by the contents of the parent's "Message-ID:" field (if any). Note that this is just preparatory work; nothing uses it yet, so all "References:" fields in the output are still only one deep. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 2ae39afcc..59671139b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -17,6 +17,7 @@ #include "run-command.h" #include "shortlog.h" #include "remote.h" +#include "string-list.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -1011,8 +1012,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) numbered = 1; if (numbered) rev.total = total + start_number - 1; - if (in_reply_to) - rev.ref_message_id = clean_message_id(in_reply_to); + if (in_reply_to || thread || cover_letter) + rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); + if (in_reply_to) { + const char *msgid = clean_message_id(in_reply_to); + string_list_append(msgid, rev.ref_message_ids); + } if (cover_letter) { if (thread) gen_message_id(&rev, "cover"); @@ -1036,10 +1041,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * otherwise, make everything a reply * to that. */ - if (rev.ref_message_id) + if (rev.ref_message_ids->nr > 0) free(rev.message_id); else - rev.ref_message_id = rev.message_id; + string_list_append(rev.message_id, + rev.ref_message_ids); } gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); } -- cgit v1.2.1 From 2175c10d5ad2769936f5bf5bcca5ea32715a7307 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:32 +0100 Subject: format-patch: thread as reply to cover letter even with in-reply-to Currently, format-patch --thread --cover-letter --in-reply-to $parent makes all mails, including the cover letter, a reply to $parent. However, we would want the reader to consider the cover letter above all the patches. This changes the semantics so that only the cover letter is a reply to $parent, while all the patches are formatted as replies to the cover letter. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 59671139b..1df38e17a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1036,12 +1036,22 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Have we already had a message ID? */ if (rev.message_id) { /* - * If we've got the ID to be a reply - * to, discard the current ID; - * otherwise, make everything a reply - * to that. + * Without --cover-letter and + * --in-reply-to, make every mail a + * reply to the one before. + * + * With --in-reply-to but no + * --cover-letter, make every mail a + * reply to the . + * + * With --cover-letter, make every + * mail but the cover letter a reply + * to the cover letter. The cover + * letter is a reply to the + * --in-reply-to, if specified. */ - if (rev.ref_message_ids->nr > 0) + if (rev.ref_message_ids->nr > 0 + && (!cover_letter || rev.nr > 1)) free(rev.message_id); else string_list_append(rev.message_id, -- cgit v1.2.1 From 30984ed2e92651962c6b8bdacf1f84da75d1da95 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:33 +0100 Subject: format-patch: support deep threading For deep threading mode, i.e., the mode that gives a thread structured like + [PATCH 0/n] Cover letter `-+ [PATCH 1/n] First patch `-+ [PATCH 2/n] Second patch `-+ ... we currently have to use 'git send-email --thread' (the default). On the other hand, format-patch also has a --thread option which gives shallow mode, i.e., + [PATCH 0/n] Cover letter |-+ [PATCH 1/n] First patch |-+ [PATCH 2/n] Second patch ... To reduce the confusion resulting from having two indentically named features in different tools giving different results, let format-patch take an optional argument '--thread=deep' that gives the same output as 'send-mail --thread'. With no argument, or 'shallow', behave as before. Also add a configuration variable format.thread with the same semantics. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 1df38e17a..6bf04e8af 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -460,6 +460,10 @@ static void add_header(const char *value) extra_hdr[extra_hdr_nr++] = xstrndup(value, len); } +#define THREAD_SHALLOW 1 +#define THREAD_DEEP 2 +static int thread = 0; + static int git_format_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.headers")) { @@ -489,6 +493,18 @@ static int git_format_config(const char *var, const char *value, void *cb) auto_number = auto_number && numbered; return 0; } + if (!strcmp(var, "format.thread")) { + if (value && !strcasecmp(value, "deep")) { + thread = THREAD_DEEP; + return 0; + } + if (value && !strcasecmp(value, "shallow")) { + thread = THREAD_SHALLOW; + return 0; + } + thread = git_config_bool(var, value) && THREAD_SHALLOW; + return 0; + } return git_log_config(var, value, cb); } @@ -767,7 +783,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered_files = 0; /* _just_ numbers */ int subject_prefix = 0; int ignore_if_in_upstream = 0; - int thread = 0; int cover_letter = 0; int boundary_count = 0; int no_binary_diff = 0; @@ -860,8 +875,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } else if (!strcmp(argv[i], "--ignore-if-in-upstream")) ignore_if_in_upstream = 1; - else if (!strcmp(argv[i], "--thread")) - thread = 1; + else if (!strcmp(argv[i], "--thread") + || !strcmp(argv[i], "--thread=shallow")) + thread = THREAD_SHALLOW; + else if (!strcmp(argv[i], "--thread=deep")) + thread = THREAD_DEEP; + else if (!strcmp(argv[i], "--no-thread")) + thread = 0; else if (!prefixcmp(argv[i], "--in-reply-to=")) in_reply_to = argv[i] + 14; else if (!strcmp(argv[i], "--in-reply-to")) { @@ -1036,6 +1056,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Have we already had a message ID? */ if (rev.message_id) { /* + * For deep threading: make every mail + * a reply to the previous one, no + * matter what other options are set. + * + * For shallow threading: + * * Without --cover-letter and * --in-reply-to, make every mail a * reply to the one before. @@ -1050,7 +1076,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * letter is a reply to the * --in-reply-to, if specified. */ - if (rev.ref_message_ids->nr > 0 + if (thread == THREAD_SHALLOW + && rev.ref_message_ids->nr > 0 && (!cover_letter || rev.nr > 1)) free(rev.message_id); else -- cgit v1.2.1 From ec2956df592338ccd789428e9232fe6b709dc2be Mon Sep 17 00:00:00 2001 From: Nate Case Date: Wed, 18 Mar 2009 12:00:45 -0500 Subject: format-patch: Respect --quiet option Hide the patch filename output from 'git format-patch' when --quiet is used. The man pages suggested that this should have already worked. Signed-off-by: Nate Case Signed-off-by: Junio C Hamano --- builtin-log.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 8684fcdb6..8af55d287 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -573,7 +573,7 @@ static FILE *realstdout = NULL; static const char *output_directory = NULL; static int outdir_offset; -static int reopen_stdout(const char *oneline, int nr, int total) +static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev) { char filename[PATH_MAX]; int len = 0; @@ -598,7 +598,9 @@ static int reopen_stdout(const char *oneline, int nr, int total) strcpy(filename + len, fmt_patch_suffix); } - fprintf(realstdout, "%s\n", filename + outdir_offset); + if (!DIFF_OPT_TST(&rev->diffopt, QUIET)) + fprintf(realstdout, "%s\n", filename + outdir_offset); + if (freopen(filename, "w", stdout) == NULL) return error("Cannot open patch file %s",filename); @@ -687,7 +689,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, die("Cover letter needs email format"); if (!use_stdout && reopen_stdout(numbered_files ? - NULL : "cover-letter", 0, rev->total)) + NULL : "cover-letter", 0, rev)) return; head_sha1 = sha1_to_hex(head->object.sha1); @@ -1106,7 +1108,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (!use_stdout && reopen_stdout(numbered_files ? NULL : get_oneline_for_filename(commit, keep_subject), - rev.nr, rev.total)) + rev.nr, &rev)) die("Failed to create output files"); shown = log_tree_commit(&rev, commit); free(commit->buffer); -- cgit v1.2.1 From b60df87a6b39b3e9fc2fe81585a8bc55a502dcd3 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 21 Mar 2009 21:32:43 -0700 Subject: format-patch: --numbered-files and --stdout aren't mutually exclusive For example: git format-patch --numbered-files --stdout --attach HEAD~~ will create two messages with files 1 and 2 attached respectively. Without --attach/--inline but with --stdout, --numbered-files option can be simply ignored, because we are not creating any file ourselves. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 2ae39afcc..0f0adf2ba 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -917,8 +917,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die ("-n and -k are mutually exclusive."); if (keep_subject && subject_prefix) die ("--subject-prefix and -k are mutually exclusive."); - if (numbered_files && use_stdout) - die ("--numbered-files and --stdout are mutually exclusive."); argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) -- cgit v1.2.1 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 c7a577259..193de3ff2 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 193de3ff2..6a27ce695 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 6a27ce695..4f438db4c 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 4f438db4c..3e3cbc11f 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 From d7d9c2d04962b5aec34ec891d82dd74262306c56 Mon Sep 17 00:00:00 2001 From: Michael Hendricks Date: Thu, 26 Mar 2009 10:51:05 -0600 Subject: format-patch: add arbitrary email headers format-patch supports the format.headers configuration for adding arbitrary email headers to the patches it outputs. This patch adds support for an --add-header argument which makes the same feature available from the command line. This is useful when the content of custom email headers must change from branch to branch. This patch has been sponsored by Grant Street Group Signed-off-by: Michael Hendricks Signed-off-by: Junio C Hamano --- builtin-log.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index c7a577259..27bc0dce2 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -918,6 +918,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) 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]; } -- cgit v1.2.1 From 1d1876e9300c56f399ea2976c5831674cd9818b1 Mon Sep 17 00:00:00 2001 From: Heiko Voigt Date: Wed, 1 Apr 2009 19:51:54 +0200 Subject: Add configuration variable for sign-off to format-patch If you regularly create patches which require a Signed-off: line you may want to make it your default to add that line. It also helps you not to forget to add the -s/--signoff switch. Signed-off-by: Heiko Voigt Signed-off-by: Junio C Hamano --- builtin-log.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 27bc0dce2..eb2c0541b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -465,6 +465,7 @@ static void add_header(const char *value) #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) { @@ -514,6 +515,10 @@ 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); } @@ -865,13 +870,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } 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; @@ -925,6 +924,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } 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'); -- cgit v1.2.1 From ca6b91d29b7ea937b71f62bf00ba7750f3e594ce Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sat, 9 May 2009 10:12:01 +0200 Subject: format-patch let -k override a config-specified format.numbered Let a command-line --keep-subject (-k) override a config-specified format.numbered (--numbered (-n)), rather than provoking the "-n and -k are mutually exclusive" failure. * t4021-format-patch-numbered.sh: Test for the above Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- builtin-log.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5eaec5d24..f10cfebdb 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -755,6 +755,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int cover_letter = 0; int boundary_count = 0; int no_binary_diff = 0; + int numbered_cmdline_opt = 0; struct commit *origin = NULL, *head = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -786,8 +787,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!strcmp(argv[i], "--stdout")) use_stdout = 1; else if (!strcmp(argv[i], "-n") || - !strcmp(argv[i], "--numbered")) + !strcmp(argv[i], "--numbered")) { numbered = 1; + numbered_cmdline_opt = 1; + } else if (!strcmp(argv[i], "-N") || !strcmp(argv[i], "--no-numbered")) { numbered = 0; @@ -918,6 +921,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (start_number < 0) start_number = 1; + + /* + * If numbered is set solely due to format.numbered in config, + * and it would conflict with --keep-subject (-k) from the + * command line, reset "numbered". + */ + if (numbered && keep_subject && !numbered_cmdline_opt) + numbered = 0; + if (numbered && keep_subject) die ("-n and -k are mutually exclusive."); if (keep_subject && subject_prefix) -- cgit v1.2.1 From fff02ee666021b67b2272ce4445f7c1f5b26b77c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 16 May 2009 02:24:46 -0700 Subject: format-patch: migrate to parse-options API Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 255 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 97 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5eaec5d24..442cc87cc 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -18,6 +18,7 @@ #include "shortlog.h" #include "remote.h" #include "string-list.h" +#include "parse-options.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -740,17 +741,117 @@ static const char *set_outdir(const char *prefix, const char *output_directory) output_directory)); } +static const char * const builtin_format_patch_usage[] = { + "git format-patch [options] [ | ]", + NULL +}; + +static int keep_subject = 0; + +static int keep_callback(const struct option *opt, const char *arg, int unset) +{ + ((struct rev_info *)opt->value)->total = -1; + keep_subject = 1; + return 0; +} + +static int subject_prefix = 0; + +static int subject_prefix_callback(const struct option *opt, const char *arg, + int unset) +{ + subject_prefix = 1; + ((struct rev_info *)opt->value)->subject_prefix = arg; + return 0; +} + +static int numbered_callback(const struct option *opt, const char *arg, + int unset) +{ + *(int *)opt->value = unset ? 0 : 1; + if (unset) + auto_number = 0; + return 0; +} + +static int no_numbered_callback(const struct option *opt, const char *arg, + int unset) +{ + return numbered_callback(opt, arg, 1); +} + +static int output_directory_callback(const struct option *opt, const char *arg, + int unset) +{ + const char **dir = (const char **)opt->value; + if (*dir) + die("Two output directories?"); + *dir = arg; + return 0; +} + +static int thread_callback(const struct option *opt, const char *arg, int unset) +{ + int *thread = (int *)opt->value; + if (unset) + *thread = 0; + else if (!arg || !strcmp(arg, "shallow")) + *thread = THREAD_SHALLOW; + else if (!strcmp(arg, "deep")) + *thread = THREAD_DEEP; + else + return 1; + return 0; +} + +static int attach_callback(const struct option *opt, const char *arg, int unset) +{ + struct rev_info *rev = (struct rev_info *)opt->value; + if (unset) + rev->mime_boundary = NULL; + else if (arg) + rev->mime_boundary = arg; + else + rev->mime_boundary = git_version_string; + rev->no_inline = unset ? 0 : 1; + return 0; +} + +static int inline_callback(const struct option *opt, const char *arg, int unset) +{ + struct rev_info *rev = (struct rev_info *)opt->value; + if (unset) + rev->mime_boundary = NULL; + else if (arg) + rev->mime_boundary = arg; + else + rev->mime_boundary = git_version_string; + rev->no_inline = 0; + return 0; +} + +static int header_callback(const struct option *opt, const char *arg, int unset) +{ + add_header(arg); + return 0; +} + +static int cc_callback(const struct option *opt, const char *arg, int unset) +{ + ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc); + extra_cc[extra_cc_nr++] = xstrdup(arg); + return 0; +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; struct commit **list = NULL; struct rev_info rev; - int nr = 0, total, i, j; + int nr = 0, total, i; int use_stdout = 0; int start_number = -1; - int keep_subject = 0; int numbered_files = 0; /* _just_ numbers */ - int subject_prefix = 0; int ignore_if_in_upstream = 0; int cover_letter = 0; int boundary_count = 0; @@ -760,6 +861,57 @@ 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; + const struct option builtin_format_patch_options[] = { + { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, + "use [PATCH n/m] even with a single patch", + PARSE_OPT_NOARG, numbered_callback }, + { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL, + "use [PATCH] even with multiple patches", + PARSE_OPT_NOARG, no_numbered_callback }, + OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"), + OPT_BOOLEAN(0, "stdout", &use_stdout, + "print patches to standard out"), + OPT_BOOLEAN(0, "cover-letter", &cover_letter, + "generate a cover letter"), + OPT_BOOLEAN(0, "numbered-files", &numbered_files, + "use simple number sequence for output file names"), + OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx", + "use instead of '.patch'"), + OPT_INTEGER(0, "start-number", &start_number, + "start numbering patches at instead of 1"), + { OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix", + "Use [] instead of [PATCH]", + PARSE_OPT_NONEG, subject_prefix_callback }, + { OPTION_CALLBACK, 'o', "output-directory", &output_directory, + "dir", "store resulting files in ", + PARSE_OPT_NONEG, output_directory_callback }, + { OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL, + "don't strip/add [PATCH]", + PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback }, + OPT_BOOLEAN(0, "no-binary", &no_binary_diff, + "don't output binary diffs"), + OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream, + "don't include a patch matching a commit upstream"), + OPT_GROUP("Messaging"), + { OPTION_CALLBACK, 0, "add-header", NULL, "header", + "add email header", PARSE_OPT_NONEG, + header_callback }, + { OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header", + PARSE_OPT_NONEG, cc_callback }, + OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id", + "make first mail a reply to "), + { OPTION_CALLBACK, 0, "attach", &rev, "boundary", + "attach the patch", PARSE_OPT_OPTARG, + attach_callback }, + { OPTION_CALLBACK, 0, "inline", &rev, "boundary", + "inline the patch", + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, + inline_callback }, + { OPTION_CALLBACK, 0, "thread", &thread, "style", + "enable message threading, styles: shallow, deep", + PARSE_OPT_OPTARG, thread_callback }, + OPT_END() + }; git_config(git_format_config, NULL); init_revisions(&rev, prefix); @@ -782,100 +934,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * like "git format-patch -o a123 HEAD^.." may fail; a123 is * possibly a valid SHA1. */ - for (i = 1, j = 1; i < argc; i++) { - if (!strcmp(argv[i], "--stdout")) - use_stdout = 1; - else if (!strcmp(argv[i], "-n") || - !strcmp(argv[i], "--numbered")) - numbered = 1; - else if (!strcmp(argv[i], "-N") || - !strcmp(argv[i], "--no-numbered")) { - numbered = 0; - auto_number = 0; - } - else if (!prefixcmp(argv[i], "--start-number=")) - start_number = strtol(argv[i] + 15, NULL, 10); - else if (!strcmp(argv[i], "--numbered-files")) - numbered_files = 1; - else if (!strcmp(argv[i], "--start-number")) { - i++; - if (i == argc) - die("Need a number for --start-number"); - start_number = strtol(argv[i], NULL, 10); - } - else if (!prefixcmp(argv[i], "--cc=")) { - ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc); - extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5); - } - else if (!strcmp(argv[i], "-k") || - !strcmp(argv[i], "--keep-subject")) { - keep_subject = 1; - rev.total = -1; - } - else if (!strcmp(argv[i], "--output-directory") || - !strcmp(argv[i], "-o")) { - i++; - if (argc <= i) - die("Which directory?"); - if (output_directory) - die("Two output directories?"); - output_directory = argv[i]; - } - else if (!strcmp(argv[i], "--signoff") || - !strcmp(argv[i], "-s")) { - do_signoff = 1; - } - else if (!strcmp(argv[i], "--attach")) { - rev.mime_boundary = git_version_string; - rev.no_inline = 1; - } - else if (!prefixcmp(argv[i], "--attach=")) { - rev.mime_boundary = argv[i] + 9; - rev.no_inline = 1; - } - else if (!strcmp(argv[i], "--no-attach")) { - rev.mime_boundary = NULL; - rev.no_inline = 0; - } - else if (!strcmp(argv[i], "--inline")) { - rev.mime_boundary = git_version_string; - rev.no_inline = 0; - } - else if (!prefixcmp(argv[i], "--inline=")) { - rev.mime_boundary = argv[i] + 9; - rev.no_inline = 0; - } - else if (!strcmp(argv[i], "--ignore-if-in-upstream")) - ignore_if_in_upstream = 1; - else if (!strcmp(argv[i], "--thread") - || !strcmp(argv[i], "--thread=shallow")) - thread = THREAD_SHALLOW; - else if (!strcmp(argv[i], "--thread=deep")) - thread = THREAD_DEEP; - else if (!strcmp(argv[i], "--no-thread")) - thread = 0; - else if (!prefixcmp(argv[i], "--in-reply-to=")) - in_reply_to = argv[i] + 14; - else if (!strcmp(argv[i], "--in-reply-to")) { - i++; - if (i == argc) - die("Need a Message-Id for --in-reply-to"); - in_reply_to = argv[i]; - } else if (!prefixcmp(argv[i], "--subject-prefix=")) { - subject_prefix = 1; - rev.subject_prefix = argv[i] + 17; - } else if (!prefixcmp(argv[i], "--suffix=")) - fmt_patch_suffix = argv[i] + 9; - else if (!strcmp(argv[i], "--cover-letter")) - 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; + argc = parse_options(argc, argv, builtin_format_patch_options, + builtin_format_patch_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN); if (do_signoff) { const char *committer; -- cgit v1.2.1 From 330db18c0277dcfcf322bb61c688acfb5ddf3867 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 18 May 2009 18:44:39 -0500 Subject: Use 'UTF-8' rather than 'utf-8' everywhere for backward compatibility Some ancient platforms (Solaris 7, IRIX 6.5) do not understand 'utf-8', but all tested implementations understand 'UTF-8'. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5eaec5d24..58db9592c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -619,7 +619,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, struct shortlog log; struct strbuf sb = STRBUF_INIT; int i; - const char *encoding = "utf-8"; + const char *encoding = "UTF-8"; struct diff_options opts; int need_8bit_cte = 0; struct commit *commit = NULL; -- cgit v1.2.1 From 377829201783b8a648e07af6ce7d747e0f45dc19 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 23 May 2009 11:53:12 -0700 Subject: parse-opts: prepare for OPT_FILENAME To give OPT_FILENAME the prefix, we pass the prefix to parse_options() which passes the prefix to parse_options_start() which sets the prefix member of parse_opts_ctx accordingly. If there isn't a prefix in the calling context, passing NULL will suffice. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 5d39565e9..ea8dbc869 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -936,7 +936,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * like "git format-patch -o a123 HEAD^.." may fail; a123 is * possibly a valid SHA1. */ - argc = parse_options(argc, argv, builtin_format_patch_options, + argc = parse_options(argc, argv, prefix, builtin_format_patch_options, builtin_format_patch_usage, PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN); -- cgit v1.2.1 From 2af202be3d2f128c6974290cabe13179c6462196 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 18 Jun 2009 10:28:43 -0700 Subject: Fix various sparse warnings in the git source code There are a few remaining ones, but this fixes the trivial ones. It boils down to two main issues that sparse complains about: - warning: Using plain integer as NULL pointer Sparse doesn't like you using '0' instead of 'NULL'. For various good reasons, not the least of which is just the visual confusion. A NULL pointer is not an integer, and that whole "0 works as NULL" is a historical accident and not very pretty. A few of these remain: zlib is a total mess, and Z_NULL is just a 0. I didn't touch those. - warning: symbol 'xyz' was not declared. Should it be static? Sparse wants to see declarations for any functions you export. A lack of a declaration tends to mean that you should either add one, or you should mark the function 'static' to show that it's in file scope. A few of these remain: I only did the ones that should obviously just be made static. That 'wt_status_submodule_summary' one is debatable. It has a few related flags (like 'wt_status_use_color') which _are_ declared, and are used by builtin-commit.c. So maybe we'd like to export it at some point, but it's not declared now, and not used outside of that file, so 'static' it is in this patch. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 0d3405055..44f9a27da 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -94,7 +94,7 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr) printf("Final output: %d %s\n", nr, stage); } -struct itimerval early_output_timer; +static struct itimerval early_output_timer; static void log_show_early(struct rev_info *revs, struct commit_list *list) { @@ -977,7 +977,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) strbuf_addch(&buf, '\n'); } - rev.extra_headers = strbuf_detach(&buf, 0); + rev.extra_headers = strbuf_detach(&buf, NULL); if (start_number < 0) start_number = 1; -- cgit v1.2.1 From 0721c314a5c8fddc877140ab5a333c42c62f780d Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 27 Jun 2009 17:58:47 +0200 Subject: Use die_errno() instead of die() when checking syscalls Lots of die() calls did not actually report the kind of error, which can leave the user confused as to the real problem. Use die_errno() where we check a system/library call that sets errno on failure, or one of the following that wrap such calls: Function Passes on error from -------- -------------------- odb_pack_keep open read_ancestry fopen read_in_full xread strbuf_read xread strbuf_read_file open or strbuf_read_file strbuf_readlink readlink write_in_full xwrite Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 0d3405055..750957cfa 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1013,8 +1013,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (use_stdout) die("standard output, or directory, which one?"); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) - die("Could not create directory %s", - output_directory); + die_errno("Could not create directory '%s'", + output_directory); } if (rev.pending.nr == 1) { -- cgit v1.2.1