On Sat, Apr 6, 2013 at 9:32 PM, Junio C Hamano <gits...@pobox.com> wrote:
> Felipe Contreras <felipe.contre...@gmail.com> 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to