On Sat, Apr 6, 2013 at 9:32 PM, Junio C Hamano <[email protected]> wrote:
> Felipe Contreras <[email protected]> writes:
>
>> Also, add a new option: 'auto', so if there's more than one patch, the
>> cover letter is generated, otherwise it's not.
>
> Very sensible goal.
>
>> This has the slight disadvantage that a piece of code will always be run
>> even if the user doesn't want a cover letter, and thus waste a few
>> cycles.
>
> I am not sure what overhead you are referring to.
>
> We need to count how many we are emitting with or without the cover
> letter, and count is stored in "total". Even when the user said
> "auto" (which I personally think should become the default in the
> longer term, but that is a separate issue), we shouldn't have to
> spend any extra cost if you moved the code that does anything heavy
> for cover letter generation after we know what that "total" is, no?
>
> I think the reason you did not move the "find the branch for use in
> the cover letter" code down was because it uses the rev->pending
> interface, which you cannot read out of after you count the commits,
> but that logic to use rev->pending predates the introduction of a
> more modern rev->cmdline mechanism, which is already used by the
> find_branch_name() function in the same codepath, and it is not
> clobbered by prepare_revision_walk().
>
> So perhaps by moving that code down after we know what value "total"
> has, and rewriting "what was the positive commit the user gave us"
> logic using rev->cmdline, you do not have to do unnecessary work at
> all.
I did try to do that, but somehow missed a few possibilities that I
see now. Perhaps something like this (after this, it's possible to
move the find_branch_name() code):
diff --git a/builtin/log.c b/builtin/log.c
index ed89c10..32add91 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1061,15 +1061,6 @@ static char *find_branch_name(struct rev_info *rev)
if (0 <= positive) {
ref = rev->cmdline.rev[positive].name;
tip_sha1 = rev->cmdline.rev[positive].item->sha1;
- } else if (!rev->cmdline.nr && rev->pending.nr == 1 &&
- !strcmp(rev->pending.objects[0].name, "HEAD")) {
- /*
- * No actual ref from command line, but "HEAD" from
- * rev->def was added in setup_revisions()
- * e.g. format-patch --cover-letter -12
- */
- ref = "HEAD";
- tip_sha1 = rev->pending.objects[0].item->sha1;
} else {
return NULL;
}
@@ -1299,28 +1290,41 @@ int cmd_format_patch(int argc, const char
**argv, const char *prefix)
}
if (rev.pending.nr == 1) {
+ unsigned char sha1[20];
+ const char *ref;
+ int check_head = 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.
*/
- unsigned char sha1[20];
- const char *ref;
-
rev.pending.objects[0].item->flags |= UNINTERESTING;
add_head_to_pending(&rev);
- ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
- if (ref && !prefixcmp(ref, "refs/heads/"))
- branch_name = xstrdup(ref +
strlen("refs/heads/"));
- else
- branch_name = xstrdup(""); /* no branch */
+ check_head = 1;
}
/*
* Otherwise, it is "format-patch -22 HEAD", and/or
* "format-patch --root HEAD". The user wants
* get_revision() to do the usual traversal.
*/
+
+ if (!strcmp(rev.pending.objects[0].name, "HEAD"))
+ /*
+ * No actual ref from command line, but "HEAD" from
+ * rev->def was added in setup_revisions()
+ * e.g. format-patch --cover-letter -12
+ */
+ check_head = 1;
+
+ if (check_head) {
+ ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
+ if (ref && !prefixcmp(ref, "refs/heads/"))
+ branch_name = xstrdup(ref +
strlen("refs/heads/"));
+ else
+ branch_name = xstrdup(""); /* no branch */
+ }
}
/*
@@ -1329,24 +1333,6 @@ int cmd_format_patch(int argc, const char
**argv, const char *prefix)
*/
rev.show_root_diff = 1;
- /*
- * NEEDSWORK:randomly pick one positive commit to show
- * diffstat; this is often the tip and the command
- * happens to do the right thing in most cases, but a
- * complex command like "--cover-letter a b c ^bottom"
- * picks "c" and shows diffstat between bottom..c
- * which may not match what the series represents at
- * all and totally broken.
- */
- for (i = 0; i < rev.pending.nr; i++) {
- struct object *o = rev.pending.objects[i].item;
- if (!(o->flags & UNINTERESTING))
- head = (struct commit *)o;
- }
- /* There is nothing to show; it is not an error, though. */
- if (!head)
- return 0;
-
if (!branch_name)
branch_name = find_branch_name(&rev);
@@ -1381,6 +1367,16 @@ int cmd_format_patch(int argc, const char
**argv, const char *prefix)
list = xrealloc(list, nr * sizeof(list[0]));
list[nr - 1] = commit;
}
+ /*
+ * NEEDSWORK:randomly pick one positive commit to show
+ * diffstat; this is often the tip and the command
+ * happens to do the right thing in most cases, but a
+ * complex command like "--cover-letter a b c ^bottom"
+ * picks "c" and shows diffstat between bottom..c
+ * which may not match what the series represents at
+ * all and totally broken.
+ */
+ head = list[0];
total = nr;
if (!keep_subject && auto_number && total > 1)
numbered = 1;
--
Felipe Contreras
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html