Commit graph

7 commits

Author SHA1 Message Date
Junio C Hamano 6bf4f1b4c9 format-patch: generate MIME header as needed even when there is format.header
Earlier, the callchain from pretty_print_commit() down to pp_title_line()
had an unwarranted assumption that the presense of "after_subject"
parameter, means the caller has already output MIME headers for
attachments.  The parameter's primary purpose is to give extra header
lines the caller wants to place after pp_title_line() generates the
"Subject: " line.

This assumption does not hold when the user used the format.header
configuration variable to pass extra headers, and caused a message with
non-ASCII character to lack proper MIME headers (e.g.  8-bit CTE header).
The earlier logic also failed to suppress duplicated MIME headers when
"format-patch -s --attach" is asked for and the signer's name demanded
8-bit clean transport.

This patch fixes the logic by introducing a separate need_8bit_cte
parameter passed down the callchain.  This can have one of these values:

 -1 : we've already done MIME crap and we do not want to add extra header
      to say this is 8bit in pp_title_line();

  0 : we haven't done MIME and we have not seen anything that is 8bit yet;

  1 : we haven't done MIME and we have seen something that is 8bit;
      pp_title_line() must add MIME header.

It adds two tests by Jeff King who independently diagnosed this issue.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-03-15 00:06:06 -07:00
Junio C Hamano f7ab5c7937 custom pretty format: tolerate empty e-mail address
When e-mail address is empty (e.g. "A U Thor <>"), --pretty=format
misparsed the commit header and did not pick up the date field correctly.

Noticed by Marco, fixed slightly differently with additional sanity
check and with a test.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-01-06 18:41:43 -08:00
René Scharfe 7ed0988adc Make "--pretty=format" parser a bit more careful.
When a commit message that does not have a terminating LF is
read in and the memory that was allocated to read it happens to
have a LF immediately after that, the code was not careful and
went past the terminating NUL.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-12-26 17:52:32 -08:00
René Scharfe b9c6232138 --format=pretty: avoid calculating expensive expansions twice
As Jeff King remarked, format strings with duplicate placeholders can
be slow to expand, because each instance is calculated anew.

This patch makes use of the fact that format_commit_message() and its
helper functions only ever add stuff to the end of the strbuf.  For
certain expensive placeholders, store the offset and length of their
expansion with the strbuf at the first occurrence.  Later they
expansion result can simply be copied from there -- no malloc() or
strdup() required.

These certain placeholders are the abbreviated commit, tree and
parent hashes, as the search for a unique abbreviated hash is quite
costly.  Here are the times for next (best of three runs):

$ time git log --pretty=format:%h >/dev/null

real    0m0.611s
user    0m0.404s
sys     0m0.204s

$ time git log --pretty=format:%h%h%h%h >/dev/null

real    0m1.206s
user    0m0.744s
sys     0m0.452s

And here those with this patch (and the previous two); the speedup
of the single placeholder case is just noise:

$ time git log --pretty=format:%h >/dev/null

real    0m0.608s
user    0m0.416s
sys     0m0.192s

$ time git log --pretty=format:%h%h%h%h >/dev/null

real    0m0.639s
user    0m0.488s
sys     0m0.140s

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-11 02:04:46 -08:00
René Scharfe f29d59586c --pretty=format: parse commit message only once
As Jeff King pointed out, some placeholder expansions are related to
each other: the steps to calculate one go most of the way towards
calculating the other, too.

This patch makes format_commit_message() parse the commit message
only once, remembering the position of each item.  This speeds up
handling of format strings containing multiple placeholders from the
set %s, %a*, %c*, %e, %b.

Here are the timings for the git version in next.  The first one is
to estimate the overhead of the caching, the second one is taken
from http://svn.tue.mpg.de/tentakel/trunk/tentakel/Makefile as an
example of a format string found in the wild.  The times are the
fastest of three consecutive runs in each case:

$ time git log --pretty=format:%e >/dev/null

real    0m0.381s
user    0m0.340s
sys     0m0.024s

$ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null

real    0m0.623s
user    0m0.556s
sys     0m0.052s

And here the times with this patch:

$ time git log --pretty=format:%e >/dev/null

real    0m0.385s
user    0m0.332s
sys     0m0.040s

$ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null

real    0m0.563s
user    0m0.504s
sys     0m0.048s

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-11 02:04:46 -08:00
René Scharfe cde75e59e1 --pretty=format: on-demand format expansion
Some of the --pretty=format placeholders expansions are expensive to
calculate.  This is made worse by the current code's use of
interpolate(), which requires _all_ placeholders are to be prepared
up front.

One way to speed this up is to check which placeholders are present
in the format string and to prepare only the expansions that are
needed.  That still leaves the allocation overhead of interpolate().

Another way is to use a callback based approach together with the
strbuf library to keep allocations to a minimum and avoid string
copies.  That's what this patch does.  It introduces a new strbuf
function, strbuf_expand().

The function takes a format string, list of placeholder strings,
a user supplied function 'fn', and an opaque pointer 'context'
to tell 'fn' what thingy to operate on.

The function 'fn' is expected to accept a strbuf, a parsed
placeholder string and the 'context' pointer, and append the
interpolated value for the 'context' thingy, according to the
format specified by the placeholder.

Thanks to Pierre Habouzit for his suggestion to use strchrnul() and
the code surrounding its callsite.  And thanks to Junio for most of
this commit message. :)

Here my measurements of most of Paul Mackerras' test cases that
highlighted the performance problem (best of three runs):

(master)
$ time git log --pretty=oneline >/dev/null

real    0m0.390s
user    0m0.340s
sys     0m0.040s

(master)
$ time git log --pretty=raw >/dev/null

real    0m0.434s
user    0m0.408s
sys     0m0.016s

(master)
$ time git log --pretty="format:%H {%P} %ct" >/dev/null

real    0m1.347s
user    0m0.080s
sys     0m1.256s

(interp_find_active -- Dscho)
$ time ./git log --pretty="format:%H {%P} %ct" >/dev/null

real    0m0.694s
user    0m0.020s
sys     0m0.672s

(strbuf_expand -- this patch)
$ time ./git log --pretty="format:%H {%P} %ct" >/dev/null

real    0m0.395s
user    0m0.352s
sys     0m0.028s

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-09 01:30:07 -08:00
Johannes Schindelin 93fc05eb9e Split off the pretty print stuff into its own file
The file commit.c got quite large, but it does not have to be: the
code concerning pretty printing is pretty well contained.  In fact,
this commit just splits it off into pretty.c, leaving commit.c with
just 672 lines.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-05 11:52:14 -08:00