2006-04-09 10:11:11 +02:00
|
|
|
#include "cache.h"
|
2017-06-14 20:07:36 +02:00
|
|
|
#include "config.h"
|
2006-04-09 10:11:11 +02:00
|
|
|
#include "diff.h"
|
|
|
|
#include "commit.h"
|
2008-09-04 23:39:21 +02:00
|
|
|
#include "tag.h"
|
2008-05-04 12:36:54 +02:00
|
|
|
#include "graph.h"
|
2006-04-09 10:11:11 +02:00
|
|
|
#include "log-tree.h"
|
2007-01-11 11:47:48 +01:00
|
|
|
#include "reflog-walk.h"
|
2008-09-04 23:39:21 +02:00
|
|
|
#include "refs.h"
|
2009-02-19 22:26:31 +01:00
|
|
|
#include "string-list.h"
|
2010-06-19 03:37:35 +02:00
|
|
|
#include "color.h"
|
2011-10-19 00:53:23 +02:00
|
|
|
#include "gpg-interface.h"
|
2013-02-12 11:17:39 +01:00
|
|
|
#include "sequencer.h"
|
Implement line-history search (git log -L)
This is a rewrite of much of Bo's work, mainly in an effort to split
it into smaller, easier to understand routines.
The algorithm is built around the struct range_set, which encodes a
series of line ranges as intervals [a,b). This is used in two
contexts:
* A set of lines we are tracking (which will change as we dig through
history).
* To encode diffs, as pairs of ranges.
The main routine is range_set_map_across_diff(). It processes the
diff between a commit C and some parent P. It determines which diff
hunks are relevant to the ranges tracked in C, and computes the new
ranges for P.
The algorithm is then simply to process history in topological order
from newest to oldest, computing ranges and (partial) diffs. At
branch points, we need to merge the ranges we are watching. We will
find that many commits do not affect the chosen ranges, and mark them
TREESAME (in addition to those already filtered by pathspec limiting).
Another pass of history simplification then gets rid of such commits.
This is wired as an extra filtering pass in the log machinery. This
currently only reduces code duplication, but should allow for other
simplifications and options to be used.
Finally, we hook a diff printer into the output chain. Ideally we
would wire directly into the diff logic, to optionally use features
like word diff. However, that will require some major reworking of
the diff chain, so we completely replace the output with our own diff
for now.
As this was a GSoC project, and has quite some history by now, many
people have helped. In no particular order, thanks go to
Jakub Narebski <jnareb@gmail.com>
Jens Lehmann <Jens.Lehmann@web.de>
Jonathan Nieder <jrnieder@gmail.com>
Junio C Hamano <gitster@pobox.com>
Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Will Palmer <wmpalmer@gmail.com>
Apologies to everyone I forgot.
Signed-off-by: Bo Yang <struggleyb.nku@gmail.com>
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-28 17:47:32 +01:00
|
|
|
#include "line-log.h"
|
2006-04-09 10:11:11 +02:00
|
|
|
|
2014-08-26 12:23:54 +02:00
|
|
|
static struct decoration name_decoration = { "object names" };
|
log: decorate HEAD with branch name under --decorate=full, too
The previous step to teach "log --decorate" to show "HEAD -> master"
instead of "HEAD, master" when showing the commit at the tip of the
'master' branch, when the 'master' branch is checked out, did not
work for "log --decorate=full".
The commands in the "log" family prepare commit decorations for all
refs upfront, and the actual string used in a decoration depends on
how load_ref_decorations() is called very early in the process. By
default, "git log --decorate" stores names with common prefixes such
as "refs/heads" stripped; "git log --decorate=full" stores the full
refnames.
When the current_pointed_by_HEAD() function has to decide if "HEAD"
points at the branch a decoration describes, however, what was
passed to load_ref_decorations() to decide to strip (or keep) such a
common prefix is long lost. This makes it impossible to reliably
tell if a decoration that stores "refs/heads/master", for example,
is the 'master' branch (under "--decorate" with prefix omitted) or
'refs/heads/master' branch (under "--decorate=full").
Keep what was passed to load_ref_decorations() in a global next to
the global variable name_decoration, and use that to decide how to
match what was read from "HEAD" and what is in a decoration.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-13 19:25:18 +02:00
|
|
|
static int decoration_loaded;
|
|
|
|
static int decoration_flags;
|
2010-06-19 03:37:34 +02:00
|
|
|
|
2010-06-19 03:37:35 +02:00
|
|
|
static char decoration_colors[][COLOR_MAXLEN] = {
|
|
|
|
GIT_COLOR_RESET,
|
|
|
|
GIT_COLOR_BOLD_GREEN, /* REF_LOCAL */
|
|
|
|
GIT_COLOR_BOLD_RED, /* REF_REMOTE */
|
|
|
|
GIT_COLOR_BOLD_YELLOW, /* REF_TAG */
|
|
|
|
GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */
|
|
|
|
GIT_COLOR_BOLD_CYAN, /* REF_HEAD */
|
2011-08-18 14:29:37 +02:00
|
|
|
GIT_COLOR_BOLD_BLUE, /* GRAFTED */
|
2010-06-19 03:37:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
|
|
|
|
{
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 07:04:23 +02:00
|
|
|
if (want_color(decorate_use_color))
|
2010-06-19 03:37:35 +02:00
|
|
|
return decoration_colors[ix];
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2010-06-24 02:21:16 +02:00
|
|
|
static int parse_decorate_color_slot(const char *slot)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We're comparing with 'ignore-case' on
|
|
|
|
* (because config.c sets them all tolower),
|
|
|
|
* but let's match the letters in the literal
|
|
|
|
* string values here with how they are
|
|
|
|
* documented in Documentation/config.txt, for
|
|
|
|
* consistency.
|
|
|
|
*
|
|
|
|
* We love being consistent, don't we?
|
|
|
|
*/
|
|
|
|
if (!strcasecmp(slot, "branch"))
|
|
|
|
return DECORATION_REF_LOCAL;
|
|
|
|
if (!strcasecmp(slot, "remoteBranch"))
|
|
|
|
return DECORATION_REF_REMOTE;
|
|
|
|
if (!strcasecmp(slot, "tag"))
|
|
|
|
return DECORATION_REF_TAG;
|
|
|
|
if (!strcasecmp(slot, "stash"))
|
|
|
|
return DECORATION_REF_STASH;
|
|
|
|
if (!strcasecmp(slot, "HEAD"))
|
|
|
|
return DECORATION_REF_HEAD;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-10-07 21:16:57 +02:00
|
|
|
int parse_decorate_color_config(const char *var, const char *slot_name, const char *value)
|
2010-06-24 02:21:16 +02:00
|
|
|
{
|
2014-10-07 21:16:57 +02:00
|
|
|
int slot = parse_decorate_color_slot(slot_name);
|
2010-06-24 02:21:16 +02:00
|
|
|
if (slot < 0)
|
|
|
|
return 0;
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
2014-10-07 21:33:09 +02:00
|
|
|
return color_parse(value, decoration_colors[slot]);
|
2010-06-24 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
2010-06-19 03:37:35 +02:00
|
|
|
/*
|
|
|
|
* log-tree.c uses DIFF_OPT_TST for determining whether to use color
|
|
|
|
* for showing the commit sha1, use the same check for --decorate
|
|
|
|
*/
|
|
|
|
#define decorate_get_color_opt(o, ix) \
|
2011-08-18 07:03:12 +02:00
|
|
|
decorate_get_color((o)->use_color, ix)
|
2010-06-19 03:37:35 +02:00
|
|
|
|
2014-08-26 12:23:36 +02:00
|
|
|
void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
|
2008-09-04 23:39:21 +02:00
|
|
|
{
|
2016-02-22 23:44:32 +01:00
|
|
|
struct name_decoration *res;
|
|
|
|
FLEX_ALLOC_STR(res, name, name);
|
2010-06-19 03:37:34 +02:00
|
|
|
res->type = type;
|
2008-09-04 23:39:21 +02:00
|
|
|
res->next = add_decoration(&name_decoration, obj, res);
|
|
|
|
}
|
|
|
|
|
2014-08-26 12:23:54 +02:00
|
|
|
const struct name_decoration *get_name_decoration(const struct object *obj)
|
|
|
|
{
|
|
|
|
return lookup_decoration(&name_decoration, obj);
|
|
|
|
}
|
|
|
|
|
2015-05-25 20:38:57 +02:00
|
|
|
static int add_ref_decoration(const char *refname, const struct object_id *oid,
|
|
|
|
int flags, void *cb_data)
|
2008-09-04 23:39:21 +02:00
|
|
|
{
|
2011-08-19 14:43:50 +02:00
|
|
|
struct object *obj;
|
2010-06-19 03:37:34 +02:00
|
|
|
enum decoration_type type = DECORATION_NONE;
|
log: add option to choose which refs to decorate
When `log --decorate` is used, git will decorate commits with all
available refs. While in most cases this may give the desired effect,
under some conditions it can lead to excessively verbose output.
Introduce two command line options, `--decorate-refs=<pattern>` and
`--decorate-refs-exclude=<pattern>` to allow the user to select which
refs are used in decoration.
When "--decorate-refs=<pattern>" is given, only the refs that match the
pattern are used in decoration. The refs that match the pattern when
"--decorate-refs-exclude=<pattern>" is given, are never used in
decoration.
These options follow the same convention for mixing negative and
positive patterns across the system, assuming that the inclusive default
is to match all refs available.
(1) if there is no positive pattern given, pretend as if an
inclusive default positive pattern was given;
(2) for each candidate, reject it if it matches no positive
pattern, or if it matches any one of the negative patterns.
The rules for what is considered a match are slightly different from the
rules used elsewhere.
Commands like `log --glob` assume a trailing '/*' when glob chars are
not present in the pattern. This makes it difficult to specify a single
ref. On the other hand, commands like `describe --match --all` allow
specifying exact refs, but do not have the convenience of allowing
"shorthand refs" like 'refs/heads' or 'heads' to refer to
'refs/heads/*'.
The commands introduced in this patch consider a match if:
(a) the pattern contains globs chars,
and regular pattern matching returns a match.
(b) the pattern does not contain glob chars,
and ref '<pattern>' exists, or if ref exists under '<pattern>/'
This allows both behaviours (allowing single refs and shorthand refs)
yet remaining compatible with existent commands.
Helped-by: Kevin Daudt <me@ikke.info>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 22:33:41 +01:00
|
|
|
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
|
2011-08-19 14:43:50 +02:00
|
|
|
|
log: add option to choose which refs to decorate
When `log --decorate` is used, git will decorate commits with all
available refs. While in most cases this may give the desired effect,
under some conditions it can lead to excessively verbose output.
Introduce two command line options, `--decorate-refs=<pattern>` and
`--decorate-refs-exclude=<pattern>` to allow the user to select which
refs are used in decoration.
When "--decorate-refs=<pattern>" is given, only the refs that match the
pattern are used in decoration. The refs that match the pattern when
"--decorate-refs-exclude=<pattern>" is given, are never used in
decoration.
These options follow the same convention for mixing negative and
positive patterns across the system, assuming that the inclusive default
is to match all refs available.
(1) if there is no positive pattern given, pretend as if an
inclusive default positive pattern was given;
(2) for each candidate, reject it if it matches no positive
pattern, or if it matches any one of the negative patterns.
The rules for what is considered a match are slightly different from the
rules used elsewhere.
Commands like `log --glob` assume a trailing '/*' when glob chars are
not present in the pattern. This makes it difficult to specify a single
ref. On the other hand, commands like `describe --match --all` allow
specifying exact refs, but do not have the convenience of allowing
"shorthand refs" like 'refs/heads' or 'heads' to refer to
'refs/heads/*'.
The commands introduced in this patch consider a match if:
(a) the pattern contains globs chars,
and regular pattern matching returns a match.
(b) the pattern does not contain glob chars,
and ref '<pattern>' exists, or if ref exists under '<pattern>/'
This allows both behaviours (allowing single refs and shorthand refs)
yet remaining compatible with existent commands.
Helped-by: Kevin Daudt <me@ikke.info>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 22:33:41 +01:00
|
|
|
if (filter && !ref_filter_match(refname,
|
|
|
|
filter->include_ref_pattern,
|
|
|
|
filter->exclude_ref_pattern))
|
|
|
|
return 0;
|
2015-05-13 21:40:35 +02:00
|
|
|
|
2015-06-11 23:34:59 +02:00
|
|
|
if (starts_with(refname, git_replace_ref_base)) {
|
2015-05-25 20:38:58 +02:00
|
|
|
struct object_id original_oid;
|
2014-02-18 12:24:55 +01:00
|
|
|
if (!check_replace_refs)
|
2011-08-25 17:09:30 +02:00
|
|
|
return 0;
|
2015-08-03 20:01:10 +02:00
|
|
|
if (get_oid_hex(refname + strlen(git_replace_ref_base),
|
|
|
|
&original_oid)) {
|
2011-08-19 14:43:50 +02:00
|
|
|
warning("invalid replace ref %s", refname);
|
|
|
|
return 0;
|
|
|
|
}
|
object: convert parse_object* to take struct object_id
Make parse_object, parse_object_or_die, and parse_object_buffer take a
pointer to struct object_id. Remove the temporary variables inserted
earlier, since they are no longer necessary. Transform all of the
callers using the following semantic patch:
@@
expression E1;
@@
- parse_object(E1.hash)
+ parse_object(&E1)
@@
expression E1;
@@
- parse_object(E1->hash)
+ parse_object(E1)
@@
expression E1, E2;
@@
- parse_object_or_die(E1.hash, E2)
+ parse_object_or_die(&E1, E2)
@@
expression E1, E2;
@@
- parse_object_or_die(E1->hash, E2)
+ parse_object_or_die(E1, E2)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1.hash, E2, E3, E4, E5)
+ parse_object_buffer(&E1, E2, E3, E4, E5)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1->hash, E2, E3, E4, E5)
+ parse_object_buffer(E1, E2, E3, E4, E5)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-07 00:10:38 +02:00
|
|
|
obj = parse_object(&original_oid);
|
2011-08-19 14:43:50 +02:00
|
|
|
if (obj)
|
|
|
|
add_name_decoration(DECORATION_GRAFTED, "replaced", obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
object: convert parse_object* to take struct object_id
Make parse_object, parse_object_or_die, and parse_object_buffer take a
pointer to struct object_id. Remove the temporary variables inserted
earlier, since they are no longer necessary. Transform all of the
callers using the following semantic patch:
@@
expression E1;
@@
- parse_object(E1.hash)
+ parse_object(&E1)
@@
expression E1;
@@
- parse_object(E1->hash)
+ parse_object(E1)
@@
expression E1, E2;
@@
- parse_object_or_die(E1.hash, E2)
+ parse_object_or_die(&E1, E2)
@@
expression E1, E2;
@@
- parse_object_or_die(E1->hash, E2)
+ parse_object_or_die(E1, E2)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1.hash, E2, E3, E4, E5)
+ parse_object_buffer(&E1, E2, E3, E4, E5)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1->hash, E2, E3, E4, E5)
+ parse_object_buffer(E1, E2, E3, E4, E5)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-07 00:10:38 +02:00
|
|
|
obj = parse_object(oid);
|
2008-09-04 23:39:21 +02:00
|
|
|
if (!obj)
|
|
|
|
return 0;
|
2010-06-19 03:37:34 +02:00
|
|
|
|
2013-11-30 21:55:40 +01:00
|
|
|
if (starts_with(refname, "refs/heads/"))
|
2010-06-19 03:37:34 +02:00
|
|
|
type = DECORATION_REF_LOCAL;
|
2013-11-30 21:55:40 +01:00
|
|
|
else if (starts_with(refname, "refs/remotes/"))
|
2010-06-19 03:37:34 +02:00
|
|
|
type = DECORATION_REF_REMOTE;
|
2013-11-30 21:55:40 +01:00
|
|
|
else if (starts_with(refname, "refs/tags/"))
|
2010-06-19 03:37:34 +02:00
|
|
|
type = DECORATION_REF_TAG;
|
2012-01-05 13:39:40 +01:00
|
|
|
else if (!strcmp(refname, "refs/stash"))
|
2010-06-19 03:37:34 +02:00
|
|
|
type = DECORATION_REF_STASH;
|
2012-01-05 13:39:40 +01:00
|
|
|
else if (!strcmp(refname, "HEAD"))
|
2010-06-19 03:37:34 +02:00
|
|
|
type = DECORATION_REF_HEAD;
|
|
|
|
|
|
|
|
add_name_decoration(type, refname, obj);
|
2008-09-04 23:39:21 +02:00
|
|
|
while (obj->type == OBJ_TAG) {
|
|
|
|
obj = ((struct tag *)obj)->tagged;
|
|
|
|
if (!obj)
|
|
|
|
break;
|
2013-12-17 05:28:21 +01:00
|
|
|
if (!obj->parsed)
|
object: convert parse_object* to take struct object_id
Make parse_object, parse_object_or_die, and parse_object_buffer take a
pointer to struct object_id. Remove the temporary variables inserted
earlier, since they are no longer necessary. Transform all of the
callers using the following semantic patch:
@@
expression E1;
@@
- parse_object(E1.hash)
+ parse_object(&E1)
@@
expression E1;
@@
- parse_object(E1->hash)
+ parse_object(E1)
@@
expression E1, E2;
@@
- parse_object_or_die(E1.hash, E2)
+ parse_object_or_die(&E1, E2)
@@
expression E1, E2;
@@
- parse_object_or_die(E1->hash, E2)
+ parse_object_or_die(E1, E2)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1.hash, E2, E3, E4, E5)
+ parse_object_buffer(&E1, E2, E3, E4, E5)
@@
expression E1, E2, E3, E4, E5;
@@
- parse_object_buffer(E1->hash, E2, E3, E4, E5)
+ parse_object_buffer(E1, E2, E3, E4, E5)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-07 00:10:38 +02:00
|
|
|
parse_object(&obj->oid);
|
2010-06-19 03:37:34 +02:00
|
|
|
add_name_decoration(DECORATION_REF_TAG, refname, obj);
|
2008-09-04 23:39:21 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-18 14:29:37 +02:00
|
|
|
static int add_graft_decoration(const struct commit_graft *graft, void *cb_data)
|
|
|
|
{
|
Convert lookup_commit* to struct object_id
Convert lookup_commit, lookup_commit_or_die,
lookup_commit_reference, and lookup_commit_reference_gently to take
struct object_id arguments.
Introduce a temporary in parse_object buffer in order to convert this
function. This is required since in order to convert parse_object and
parse_object_buffer, lookup_commit_reference_gently and
lookup_commit_or_die would need to be converted. Not introducing a
temporary would therefore require that lookup_commit_or_die take a
struct object_id *, but lookup_commit would take unsigned char *,
leaving a confusing and hard-to-use interface.
parse_object_buffer will lose this temporary in a later patch.
This commit was created with manual changes to commit.c, commit.h, and
object.c, plus the following semantic patch:
@@
expression E1, E2;
@@
- lookup_commit_reference_gently(E1.hash, E2)
+ lookup_commit_reference_gently(&E1, E2)
@@
expression E1, E2;
@@
- lookup_commit_reference_gently(E1->hash, E2)
+ lookup_commit_reference_gently(E1, E2)
@@
expression E1;
@@
- lookup_commit_reference(E1.hash)
+ lookup_commit_reference(&E1)
@@
expression E1;
@@
- lookup_commit_reference(E1->hash)
+ lookup_commit_reference(E1)
@@
expression E1;
@@
- lookup_commit(E1.hash)
+ lookup_commit(&E1)
@@
expression E1;
@@
- lookup_commit(E1->hash)
+ lookup_commit(E1)
@@
expression E1, E2;
@@
- lookup_commit_or_die(E1.hash, E2)
+ lookup_commit_or_die(&E1, E2)
@@
expression E1, E2;
@@
- lookup_commit_or_die(E1->hash, E2)
+ lookup_commit_or_die(E1, E2)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-07 00:10:10 +02:00
|
|
|
struct commit *commit = lookup_commit(&graft->oid);
|
2011-08-18 14:29:37 +02:00
|
|
|
if (!commit)
|
|
|
|
return 0;
|
|
|
|
add_name_decoration(DECORATION_GRAFTED, "grafted", &commit->object);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
log: add option to choose which refs to decorate
When `log --decorate` is used, git will decorate commits with all
available refs. While in most cases this may give the desired effect,
under some conditions it can lead to excessively verbose output.
Introduce two command line options, `--decorate-refs=<pattern>` and
`--decorate-refs-exclude=<pattern>` to allow the user to select which
refs are used in decoration.
When "--decorate-refs=<pattern>" is given, only the refs that match the
pattern are used in decoration. The refs that match the pattern when
"--decorate-refs-exclude=<pattern>" is given, are never used in
decoration.
These options follow the same convention for mixing negative and
positive patterns across the system, assuming that the inclusive default
is to match all refs available.
(1) if there is no positive pattern given, pretend as if an
inclusive default positive pattern was given;
(2) for each candidate, reject it if it matches no positive
pattern, or if it matches any one of the negative patterns.
The rules for what is considered a match are slightly different from the
rules used elsewhere.
Commands like `log --glob` assume a trailing '/*' when glob chars are
not present in the pattern. This makes it difficult to specify a single
ref. On the other hand, commands like `describe --match --all` allow
specifying exact refs, but do not have the convenience of allowing
"shorthand refs" like 'refs/heads' or 'heads' to refer to
'refs/heads/*'.
The commands introduced in this patch consider a match if:
(a) the pattern contains globs chars,
and regular pattern matching returns a match.
(b) the pattern does not contain glob chars,
and ref '<pattern>' exists, or if ref exists under '<pattern>/'
This allows both behaviours (allowing single refs and shorthand refs)
yet remaining compatible with existent commands.
Helped-by: Kevin Daudt <me@ikke.info>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 22:33:41 +01:00
|
|
|
void load_ref_decorations(struct decoration_filter *filter, int flags)
|
2008-09-04 23:39:21 +02:00
|
|
|
{
|
log: decorate HEAD with branch name under --decorate=full, too
The previous step to teach "log --decorate" to show "HEAD -> master"
instead of "HEAD, master" when showing the commit at the tip of the
'master' branch, when the 'master' branch is checked out, did not
work for "log --decorate=full".
The commands in the "log" family prepare commit decorations for all
refs upfront, and the actual string used in a decoration depends on
how load_ref_decorations() is called very early in the process. By
default, "git log --decorate" stores names with common prefixes such
as "refs/heads" stripped; "git log --decorate=full" stores the full
refnames.
When the current_pointed_by_HEAD() function has to decide if "HEAD"
points at the branch a decoration describes, however, what was
passed to load_ref_decorations() to decide to strip (or keep) such a
common prefix is long lost. This makes it impossible to reliably
tell if a decoration that stores "refs/heads/master", for example,
is the 'master' branch (under "--decorate" with prefix omitted) or
'refs/heads/master' branch (under "--decorate=full").
Keep what was passed to load_ref_decorations() in a global next to
the global variable name_decoration, and use that to decide how to
match what was read from "HEAD" and what is in a decoration.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-13 19:25:18 +02:00
|
|
|
if (!decoration_loaded) {
|
log: add option to choose which refs to decorate
When `log --decorate` is used, git will decorate commits with all
available refs. While in most cases this may give the desired effect,
under some conditions it can lead to excessively verbose output.
Introduce two command line options, `--decorate-refs=<pattern>` and
`--decorate-refs-exclude=<pattern>` to allow the user to select which
refs are used in decoration.
When "--decorate-refs=<pattern>" is given, only the refs that match the
pattern are used in decoration. The refs that match the pattern when
"--decorate-refs-exclude=<pattern>" is given, are never used in
decoration.
These options follow the same convention for mixing negative and
positive patterns across the system, assuming that the inclusive default
is to match all refs available.
(1) if there is no positive pattern given, pretend as if an
inclusive default positive pattern was given;
(2) for each candidate, reject it if it matches no positive
pattern, or if it matches any one of the negative patterns.
The rules for what is considered a match are slightly different from the
rules used elsewhere.
Commands like `log --glob` assume a trailing '/*' when glob chars are
not present in the pattern. This makes it difficult to specify a single
ref. On the other hand, commands like `describe --match --all` allow
specifying exact refs, but do not have the convenience of allowing
"shorthand refs" like 'refs/heads' or 'heads' to refer to
'refs/heads/*'.
The commands introduced in this patch consider a match if:
(a) the pattern contains globs chars,
and regular pattern matching returns a match.
(b) the pattern does not contain glob chars,
and ref '<pattern>' exists, or if ref exists under '<pattern>/'
This allows both behaviours (allowing single refs and shorthand refs)
yet remaining compatible with existent commands.
Helped-by: Kevin Daudt <me@ikke.info>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 22:33:41 +01:00
|
|
|
if (filter) {
|
|
|
|
struct string_list_item *item;
|
|
|
|
for_each_string_list_item(item, filter->exclude_ref_pattern) {
|
|
|
|
normalize_glob_ref(item, NULL, item->string);
|
|
|
|
}
|
|
|
|
for_each_string_list_item(item, filter->include_ref_pattern) {
|
|
|
|
normalize_glob_ref(item, NULL, item->string);
|
|
|
|
}
|
|
|
|
}
|
log: decorate HEAD with branch name under --decorate=full, too
The previous step to teach "log --decorate" to show "HEAD -> master"
instead of "HEAD, master" when showing the commit at the tip of the
'master' branch, when the 'master' branch is checked out, did not
work for "log --decorate=full".
The commands in the "log" family prepare commit decorations for all
refs upfront, and the actual string used in a decoration depends on
how load_ref_decorations() is called very early in the process. By
default, "git log --decorate" stores names with common prefixes such
as "refs/heads" stripped; "git log --decorate=full" stores the full
refnames.
When the current_pointed_by_HEAD() function has to decide if "HEAD"
points at the branch a decoration describes, however, what was
passed to load_ref_decorations() to decide to strip (or keep) such a
common prefix is long lost. This makes it impossible to reliably
tell if a decoration that stores "refs/heads/master", for example,
is the 'master' branch (under "--decorate" with prefix omitted) or
'refs/heads/master' branch (under "--decorate=full").
Keep what was passed to load_ref_decorations() in a global next to
the global variable name_decoration, and use that to decide how to
match what was read from "HEAD" and what is in a decoration.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-13 19:25:18 +02:00
|
|
|
decoration_loaded = 1;
|
|
|
|
decoration_flags = flags;
|
log: add option to choose which refs to decorate
When `log --decorate` is used, git will decorate commits with all
available refs. While in most cases this may give the desired effect,
under some conditions it can lead to excessively verbose output.
Introduce two command line options, `--decorate-refs=<pattern>` and
`--decorate-refs-exclude=<pattern>` to allow the user to select which
refs are used in decoration.
When "--decorate-refs=<pattern>" is given, only the refs that match the
pattern are used in decoration. The refs that match the pattern when
"--decorate-refs-exclude=<pattern>" is given, are never used in
decoration.
These options follow the same convention for mixing negative and
positive patterns across the system, assuming that the inclusive default
is to match all refs available.
(1) if there is no positive pattern given, pretend as if an
inclusive default positive pattern was given;
(2) for each candidate, reject it if it matches no positive
pattern, or if it matches any one of the negative patterns.
The rules for what is considered a match are slightly different from the
rules used elsewhere.
Commands like `log --glob` assume a trailing '/*' when glob chars are
not present in the pattern. This makes it difficult to specify a single
ref. On the other hand, commands like `describe --match --all` allow
specifying exact refs, but do not have the convenience of allowing
"shorthand refs" like 'refs/heads' or 'heads' to refer to
'refs/heads/*'.
The commands introduced in this patch consider a match if:
(a) the pattern contains globs chars,
and regular pattern matching returns a match.
(b) the pattern does not contain glob chars,
and ref '<pattern>' exists, or if ref exists under '<pattern>/'
This allows both behaviours (allowing single refs and shorthand refs)
yet remaining compatible with existent commands.
Helped-by: Kevin Daudt <me@ikke.info>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 22:33:41 +01:00
|
|
|
for_each_ref(add_ref_decoration, filter);
|
|
|
|
head_ref(add_ref_decoration, filter);
|
|
|
|
for_each_commit_graft(add_graft_decoration, filter);
|
2008-09-04 23:39:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-22 17:01:32 +02:00
|
|
|
static void show_parents(struct commit *commit, int abbrev, FILE *file)
|
2006-05-03 16:59:00 +02:00
|
|
|
{
|
|
|
|
struct commit_list *p;
|
|
|
|
for (p = commit->parents; p ; p = p->next) {
|
|
|
|
struct commit *parent = p->item;
|
2018-03-12 03:27:30 +01:00
|
|
|
fprintf(file, " %s", find_unique_abbrev(&parent->object.oid, abbrev));
|
2006-05-03 16:59:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-04 16:02:03 +02:00
|
|
|
static void show_children(struct rev_info *opt, struct commit *commit, int abbrev)
|
|
|
|
{
|
|
|
|
struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
|
|
|
|
for ( ; p; p = p->next) {
|
2018-03-12 03:27:30 +01:00
|
|
|
fprintf(opt->diffopt.file, " %s", find_unique_abbrev(&p->item->object.oid, abbrev));
|
2011-10-04 16:02:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 14:53:21 +01:00
|
|
|
/*
|
|
|
|
* Do we have HEAD in the output, and also the branch it points at?
|
|
|
|
* If so, find that decoration entry for that current branch.
|
|
|
|
*/
|
|
|
|
static const struct name_decoration *current_pointed_by_HEAD(const struct name_decoration *decoration)
|
|
|
|
{
|
|
|
|
const struct name_decoration *list, *head = NULL;
|
|
|
|
const char *branch_name = NULL;
|
|
|
|
int rru_flags;
|
|
|
|
|
|
|
|
/* First find HEAD */
|
|
|
|
for (list = decoration; list; list = list->next)
|
|
|
|
if (list->type == DECORATION_REF_HEAD) {
|
|
|
|
head = list;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!head)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Now resolve and find the matching current branch */
|
2017-09-23 11:45:04 +02:00
|
|
|
branch_name = resolve_ref_unsafe("HEAD", 0, NULL, &rru_flags);
|
2017-10-19 19:49:01 +02:00
|
|
|
if (!branch_name || !(rru_flags & REF_ISSYMREF))
|
2015-03-10 14:53:21 +01:00
|
|
|
return NULL;
|
log: decorate HEAD with branch name under --decorate=full, too
The previous step to teach "log --decorate" to show "HEAD -> master"
instead of "HEAD, master" when showing the commit at the tip of the
'master' branch, when the 'master' branch is checked out, did not
work for "log --decorate=full".
The commands in the "log" family prepare commit decorations for all
refs upfront, and the actual string used in a decoration depends on
how load_ref_decorations() is called very early in the process. By
default, "git log --decorate" stores names with common prefixes such
as "refs/heads" stripped; "git log --decorate=full" stores the full
refnames.
When the current_pointed_by_HEAD() function has to decide if "HEAD"
points at the branch a decoration describes, however, what was
passed to load_ref_decorations() to decide to strip (or keep) such a
common prefix is long lost. This makes it impossible to reliably
tell if a decoration that stores "refs/heads/master", for example,
is the 'master' branch (under "--decorate" with prefix omitted) or
'refs/heads/master' branch (under "--decorate=full").
Keep what was passed to load_ref_decorations() in a global next to
the global variable name_decoration, and use that to decide how to
match what was read from "HEAD" and what is in a decoration.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-13 19:25:18 +02:00
|
|
|
|
2015-05-13 21:40:35 +02:00
|
|
|
if (!starts_with(branch_name, "refs/"))
|
2015-03-10 14:53:21 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* OK, do we have that ref in the list? */
|
|
|
|
for (list = decoration; list; list = list->next)
|
|
|
|
if ((list->type == DECORATION_REF_LOCAL) &&
|
|
|
|
!strcmp(branch_name, list->name)) {
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-13 21:40:35 +02:00
|
|
|
static void show_name(struct strbuf *sb, const struct name_decoration *decoration)
|
|
|
|
{
|
|
|
|
if (decoration_flags == DECORATE_SHORT_REFS)
|
|
|
|
strbuf_addstr(sb, prettify_refname(decoration->name));
|
|
|
|
else
|
|
|
|
strbuf_addstr(sb, decoration->name);
|
|
|
|
}
|
|
|
|
|
2013-04-19 01:08:43 +02:00
|
|
|
/*
|
2014-09-18 22:53:53 +02:00
|
|
|
* The caller makes sure there is no funny color before calling.
|
|
|
|
* format_decorations_extended makes sure the same after return.
|
2013-04-19 01:08:43 +02:00
|
|
|
*/
|
2014-09-18 22:53:53 +02:00
|
|
|
void format_decorations_extended(struct strbuf *sb,
|
2013-04-19 01:08:43 +02:00
|
|
|
const struct commit *commit,
|
2014-09-18 22:53:53 +02:00
|
|
|
int use_color,
|
|
|
|
const char *prefix,
|
|
|
|
const char *separator,
|
|
|
|
const char *suffix)
|
2007-04-17 01:05:10 +02:00
|
|
|
{
|
2014-08-26 12:23:54 +02:00
|
|
|
const struct name_decoration *decoration;
|
2015-03-10 14:53:21 +01:00
|
|
|
const struct name_decoration *current_and_HEAD;
|
2010-06-19 03:37:35 +02:00
|
|
|
const char *color_commit =
|
2013-04-19 01:08:43 +02:00
|
|
|
diff_get_color(use_color, DIFF_COMMIT);
|
2010-06-19 03:37:35 +02:00
|
|
|
const char *color_reset =
|
2013-04-19 01:08:43 +02:00
|
|
|
decorate_get_color(use_color, DECORATION_NONE);
|
2007-04-17 01:05:10 +02:00
|
|
|
|
2014-08-26 12:23:54 +02:00
|
|
|
decoration = get_name_decoration(&commit->object);
|
2007-04-17 01:05:10 +02:00
|
|
|
if (!decoration)
|
|
|
|
return;
|
2015-03-10 14:53:21 +01:00
|
|
|
|
|
|
|
current_and_HEAD = current_pointed_by_HEAD(decoration);
|
2007-04-17 01:05:10 +02:00
|
|
|
while (decoration) {
|
2015-03-10 14:53:21 +01:00
|
|
|
/*
|
|
|
|
* When both current and HEAD are there, only
|
|
|
|
* show HEAD->current where HEAD would have
|
|
|
|
* appeared, skipping the entry for current.
|
|
|
|
*/
|
|
|
|
if (decoration != current_and_HEAD) {
|
|
|
|
strbuf_addstr(sb, color_commit);
|
|
|
|
strbuf_addstr(sb, prefix);
|
|
|
|
strbuf_addstr(sb, color_reset);
|
|
|
|
strbuf_addstr(sb, decorate_get_color(use_color, decoration->type));
|
|
|
|
if (decoration->type == DECORATION_REF_TAG)
|
|
|
|
strbuf_addstr(sb, "tag: ");
|
|
|
|
|
2015-05-13 21:40:35 +02:00
|
|
|
show_name(sb, decoration);
|
2015-03-10 14:53:21 +01:00
|
|
|
|
|
|
|
if (current_and_HEAD &&
|
|
|
|
decoration->type == DECORATION_REF_HEAD) {
|
|
|
|
strbuf_addstr(sb, " -> ");
|
|
|
|
strbuf_addstr(sb, color_reset);
|
|
|
|
strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type));
|
2015-05-13 21:40:35 +02:00
|
|
|
show_name(sb, current_and_HEAD);
|
2015-03-10 14:53:21 +01:00
|
|
|
}
|
|
|
|
strbuf_addstr(sb, color_reset);
|
|
|
|
|
|
|
|
prefix = separator;
|
|
|
|
}
|
2007-04-17 01:05:10 +02:00
|
|
|
decoration = decoration->next;
|
|
|
|
}
|
2013-04-19 01:08:43 +02:00
|
|
|
strbuf_addstr(sb, color_commit);
|
2014-09-18 22:53:53 +02:00
|
|
|
strbuf_addstr(sb, suffix);
|
2013-04-19 01:08:43 +02:00
|
|
|
strbuf_addstr(sb, color_reset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_decorations(struct rev_info *opt, struct commit *commit)
|
|
|
|
{
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
|
2018-05-19 07:28:24 +02:00
|
|
|
if (opt->sources) {
|
|
|
|
char **slot = revision_sources_peek(opt->sources, commit);
|
|
|
|
|
|
|
|
if (slot && *slot)
|
|
|
|
fprintf(opt->diffopt.file, "\t%s", *slot);
|
|
|
|
}
|
2013-04-19 01:08:43 +02:00
|
|
|
if (!opt->show_decorations)
|
|
|
|
return;
|
|
|
|
format_decorations(&sb, commit, opt->diffopt.use_color);
|
2016-06-22 17:01:32 +02:00
|
|
|
fputs(sb.buf, opt->diffopt.file);
|
2013-04-19 01:08:43 +02:00
|
|
|
strbuf_release(&sb);
|
2007-04-17 01:05:10 +02:00
|
|
|
}
|
|
|
|
|
2007-02-09 01:43:54 +01:00
|
|
|
static unsigned int digits_in_number(unsigned int number)
|
|
|
|
{
|
|
|
|
unsigned int i = 10, result = 1;
|
|
|
|
while (i <= number) {
|
|
|
|
i *= 10;
|
|
|
|
result++;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-12-22 07:06:01 +01:00
|
|
|
void fmt_output_subject(struct strbuf *filename,
|
|
|
|
const char *subject,
|
2012-12-22 08:26:16 +01:00
|
|
|
struct rev_info *info)
|
2009-03-23 03:14:04 +01:00
|
|
|
{
|
2012-12-22 08:26:16 +01:00
|
|
|
const char *suffix = info->patch_suffix;
|
|
|
|
int nr = info->nr;
|
2012-12-22 07:06:01 +01:00
|
|
|
int start_len = filename->len;
|
|
|
|
int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1);
|
|
|
|
|
2012-12-22 09:21:23 +01:00
|
|
|
if (0 < info->reroll_count)
|
|
|
|
strbuf_addf(filename, "v%d-", info->reroll_count);
|
2012-12-22 07:06:01 +01:00
|
|
|
strbuf_addf(filename, "%04d-%s", nr, subject);
|
|
|
|
|
|
|
|
if (max_len < filename->len)
|
|
|
|
strbuf_setlen(filename, max_len);
|
|
|
|
strbuf_addstr(filename, suffix);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fmt_output_commit(struct strbuf *filename,
|
|
|
|
struct commit *commit,
|
|
|
|
struct rev_info *info)
|
|
|
|
{
|
|
|
|
struct pretty_print_context ctx = {0};
|
|
|
|
struct strbuf subject = STRBUF_INIT;
|
|
|
|
|
|
|
|
format_commit_message(commit, "%f", &subject, &ctx);
|
|
|
|
fmt_output_subject(filename, subject.buf, info);
|
|
|
|
strbuf_release(&subject);
|
2009-03-23 03:14:04 +01:00
|
|
|
}
|
|
|
|
|
2017-03-01 12:36:38 +01:00
|
|
|
void fmt_output_email_subject(struct strbuf *sb, struct rev_info *opt)
|
|
|
|
{
|
|
|
|
if (opt->total > 0) {
|
|
|
|
strbuf_addf(sb, "Subject: [%s%s%0*d/%d] ",
|
|
|
|
opt->subject_prefix,
|
|
|
|
*opt->subject_prefix ? " " : "",
|
|
|
|
digits_in_number(opt->total),
|
|
|
|
opt->nr, opt->total);
|
|
|
|
} else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) {
|
|
|
|
strbuf_addf(sb, "Subject: [%s] ",
|
|
|
|
opt->subject_prefix);
|
|
|
|
} else {
|
|
|
|
strbuf_addstr(sb, "Subject: ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-23 03:14:05 +01:00
|
|
|
void log_write_email_headers(struct rev_info *opt, struct commit *commit,
|
2008-03-15 08:09:20 +01:00
|
|
|
const char **extra_headers_p,
|
2018-05-02 04:20:52 +02:00
|
|
|
int *need_8bit_cte_p,
|
|
|
|
int maybe_multipart)
|
2008-02-19 04:56:08 +01:00
|
|
|
{
|
|
|
|
const char *extra_headers = opt->extra_headers;
|
2015-12-15 02:52:04 +01:00
|
|
|
const char *name = oid_to_hex(opt->zero_commit ?
|
|
|
|
&null_oid : &commit->object.oid);
|
2008-03-15 08:09:20 +01:00
|
|
|
|
|
|
|
*need_8bit_cte_p = 0; /* unknown */
|
2008-02-19 04:56:08 +01:00
|
|
|
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "From %s Mon Sep 17 00:00:00 2001\n", name);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
|
|
|
if (opt->message_id) {
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "Message-Id: <%s>\n", opt->message_id);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
|
|
|
}
|
2009-02-19 22:26:31 +01:00
|
|
|
if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) {
|
|
|
|
int i, n;
|
|
|
|
n = opt->ref_message_ids->nr;
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string);
|
2009-02-19 22:26:31 +01:00
|
|
|
for (i = 0; i < n; i++)
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "%s<%s>\n", (i > 0 ? "\t" : "References: "),
|
2009-02-19 22:26:31 +01:00
|
|
|
opt->ref_message_ids->items[i].string);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
|
|
|
}
|
2018-05-02 04:20:52 +02:00
|
|
|
if (opt->mime_boundary && maybe_multipart) {
|
log_write_email_headers: use strbufs
When we write a MIME attachment, we write the mime headers
into fixed-size buffers. These are likely to be big enough
in practice, but technically the input could be arbitrarily
large (e.g., if the caller provided a lot of content in the
extra_headers string), in which case we'd quietly truncate
it and generate bogus output. Let's convert these buffers to
strbufs.
The memory ownership here is a bit funny. The original fixed
buffers were static, and we merely pass out pointers to them
to be used by the caller (and in one case, we even just
stuff our value into the opt->diffopt.stat_sep value).
Ideally we'd actually pass back heap buffers, and the caller
would be responsible for freeing them.
This patch punts on that cleanup for now, and instead just
marks the strbufs as static. That means we keep ownership in
this function, making it not a complete leak. This also
takes us one step closer to fixing it in the long term
(since we can eventually use strbuf_detach() to hand
ownership to the caller, once it's ready).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-19 03:57:44 +02:00
|
|
|
static struct strbuf subject_buffer = STRBUF_INIT;
|
|
|
|
static struct strbuf buffer = STRBUF_INIT;
|
2009-03-23 03:14:05 +01:00
|
|
|
struct strbuf filename = STRBUF_INIT;
|
2008-03-15 08:09:20 +01:00
|
|
|
*need_8bit_cte_p = -1; /* NEVER */
|
log_write_email_headers: use strbufs
When we write a MIME attachment, we write the mime headers
into fixed-size buffers. These are likely to be big enough
in practice, but technically the input could be arbitrarily
large (e.g., if the caller provided a lot of content in the
extra_headers string), in which case we'd quietly truncate
it and generate bogus output. Let's convert these buffers to
strbufs.
The memory ownership here is a bit funny. The original fixed
buffers were static, and we merely pass out pointers to them
to be used by the caller (and in one case, we even just
stuff our value into the opt->diffopt.stat_sep value).
Ideally we'd actually pass back heap buffers, and the caller
would be responsible for freeing them.
This patch punts on that cleanup for now, and instead just
marks the strbufs as static. That means we keep ownership in
this function, making it not a complete leak. This also
takes us one step closer to fixing it in the long term
(since we can eventually use strbuf_detach() to hand
ownership to the caller, once it's ready).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-19 03:57:44 +02:00
|
|
|
|
|
|
|
strbuf_reset(&subject_buffer);
|
|
|
|
strbuf_reset(&buffer);
|
|
|
|
|
|
|
|
strbuf_addf(&subject_buffer,
|
2008-02-19 04:56:08 +01:00
|
|
|
"%s"
|
|
|
|
"MIME-Version: 1.0\n"
|
|
|
|
"Content-Type: multipart/mixed;"
|
|
|
|
" boundary=\"%s%s\"\n"
|
|
|
|
"\n"
|
|
|
|
"This is a multi-part message in MIME "
|
|
|
|
"format.\n"
|
|
|
|
"--%s%s\n"
|
|
|
|
"Content-Type: text/plain; "
|
|
|
|
"charset=UTF-8; format=fixed\n"
|
|
|
|
"Content-Transfer-Encoding: 8bit\n\n",
|
|
|
|
extra_headers ? extra_headers : "",
|
|
|
|
mime_boundary_leader, opt->mime_boundary,
|
|
|
|
mime_boundary_leader, opt->mime_boundary);
|
log_write_email_headers: use strbufs
When we write a MIME attachment, we write the mime headers
into fixed-size buffers. These are likely to be big enough
in practice, but technically the input could be arbitrarily
large (e.g., if the caller provided a lot of content in the
extra_headers string), in which case we'd quietly truncate
it and generate bogus output. Let's convert these buffers to
strbufs.
The memory ownership here is a bit funny. The original fixed
buffers were static, and we merely pass out pointers to them
to be used by the caller (and in one case, we even just
stuff our value into the opt->diffopt.stat_sep value).
Ideally we'd actually pass back heap buffers, and the caller
would be responsible for freeing them.
This patch punts on that cleanup for now, and instead just
marks the strbufs as static. That means we keep ownership in
this function, making it not a complete leak. This also
takes us one step closer to fixing it in the long term
(since we can eventually use strbuf_detach() to hand
ownership to the caller, once it's ready).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-19 03:57:44 +02:00
|
|
|
extra_headers = subject_buffer.buf;
|
2008-02-19 04:56:08 +01:00
|
|
|
|
2012-12-22 06:39:37 +01:00
|
|
|
if (opt->numbered_files)
|
|
|
|
strbuf_addf(&filename, "%d", opt->nr);
|
|
|
|
else
|
2012-12-22 07:06:01 +01:00
|
|
|
fmt_output_commit(&filename, commit, opt);
|
log_write_email_headers: use strbufs
When we write a MIME attachment, we write the mime headers
into fixed-size buffers. These are likely to be big enough
in practice, but technically the input could be arbitrarily
large (e.g., if the caller provided a lot of content in the
extra_headers string), in which case we'd quietly truncate
it and generate bogus output. Let's convert these buffers to
strbufs.
The memory ownership here is a bit funny. The original fixed
buffers were static, and we merely pass out pointers to them
to be used by the caller (and in one case, we even just
stuff our value into the opt->diffopt.stat_sep value).
Ideally we'd actually pass back heap buffers, and the caller
would be responsible for freeing them.
This patch punts on that cleanup for now, and instead just
marks the strbufs as static. That means we keep ownership in
this function, making it not a complete leak. This also
takes us one step closer to fixing it in the long term
(since we can eventually use strbuf_detach() to hand
ownership to the caller, once it's ready).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-19 03:57:44 +02:00
|
|
|
strbuf_addf(&buffer,
|
2008-07-30 07:49:33 +02:00
|
|
|
"\n--%s%s\n"
|
2008-02-19 04:56:08 +01:00
|
|
|
"Content-Type: text/x-patch;"
|
2009-03-23 03:14:05 +01:00
|
|
|
" name=\"%s\"\n"
|
2008-02-19 04:56:08 +01:00
|
|
|
"Content-Transfer-Encoding: 8bit\n"
|
|
|
|
"Content-Disposition: %s;"
|
2009-03-23 03:14:05 +01:00
|
|
|
" filename=\"%s\"\n\n",
|
2008-02-19 04:56:08 +01:00
|
|
|
mime_boundary_leader, opt->mime_boundary,
|
2009-03-23 03:14:05 +01:00
|
|
|
filename.buf,
|
2008-02-19 04:56:08 +01:00
|
|
|
opt->no_inline ? "attachment" : "inline",
|
2009-03-23 03:14:05 +01:00
|
|
|
filename.buf);
|
log_write_email_headers: use strbufs
When we write a MIME attachment, we write the mime headers
into fixed-size buffers. These are likely to be big enough
in practice, but technically the input could be arbitrarily
large (e.g., if the caller provided a lot of content in the
extra_headers string), in which case we'd quietly truncate
it and generate bogus output. Let's convert these buffers to
strbufs.
The memory ownership here is a bit funny. The original fixed
buffers were static, and we merely pass out pointers to them
to be used by the caller (and in one case, we even just
stuff our value into the opt->diffopt.stat_sep value).
Ideally we'd actually pass back heap buffers, and the caller
would be responsible for freeing them.
This patch punts on that cleanup for now, and instead just
marks the strbufs as static. That means we keep ownership in
this function, making it not a complete leak. This also
takes us one step closer to fixing it in the long term
(since we can eventually use strbuf_detach() to hand
ownership to the caller, once it's ready).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-19 03:57:44 +02:00
|
|
|
opt->diffopt.stat_sep = buffer.buf;
|
2009-03-23 03:14:05 +01:00
|
|
|
strbuf_release(&filename);
|
2008-02-19 04:56:08 +01:00
|
|
|
}
|
|
|
|
*extra_headers_p = extra_headers;
|
|
|
|
}
|
|
|
|
|
2012-01-04 22:48:45 +01:00
|
|
|
static void show_sig_lines(struct rev_info *opt, int status, const char *bol)
|
|
|
|
{
|
|
|
|
const char *color, *reset, *eol;
|
|
|
|
|
|
|
|
color = diff_get_color_opt(&opt->diffopt,
|
|
|
|
status ? DIFF_WHITESPACE : DIFF_FRAGINFO);
|
|
|
|
reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);
|
|
|
|
while (*bol) {
|
|
|
|
eol = strchrnul(bol, '\n');
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
|
2012-01-04 22:48:45 +01:00
|
|
|
*eol ? "\n" : "");
|
2014-07-09 04:10:21 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
2012-01-04 22:48:45 +01:00
|
|
|
bol = (*eol) ? (eol + 1) : eol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-19 00:53:23 +02:00
|
|
|
static void show_signature(struct rev_info *opt, struct commit *commit)
|
|
|
|
{
|
|
|
|
struct strbuf payload = STRBUF_INIT;
|
|
|
|
struct strbuf signature = STRBUF_INIT;
|
|
|
|
struct strbuf gpg_output = STRBUF_INIT;
|
|
|
|
int status;
|
|
|
|
|
reuse cached commit buffer when parsing signatures
When we call show_signature or show_mergetag, we read the
commit object fresh via read_sha1_file and reparse its
headers. However, in most cases we already have the object
data available, attached to the "struct commit". This is
partially laziness in dealing with the memory allocation
issues, but partially defensive programming, in that we
would always want to verify a clean version of the buffer
(not one that might have been munged by other users of the
commit).
However, we do not currently ever munge the commit buffer,
and not using the already-available buffer carries a fairly
big performance penalty when we are looking at a large
number of commits. Here are timings on linux.git:
[baseline, no signatures]
$ time git log >/dev/null
real 0m4.902s
user 0m4.784s
sys 0m0.120s
[before]
$ time git log --show-signature >/dev/null
real 0m14.735s
user 0m9.964s
sys 0m0.944s
[after]
$ time git log --show-signature >/dev/null
real 0m9.981s
user 0m5.260s
sys 0m0.936s
Note that our user CPU time drops almost in half, close to
the non-signature case, but we do still spend more
wall-clock and system time, presumably from dealing with
gpg.
An alternative to this is to note that most commits do not
have signatures (less than 1% in this repo), yet we pay the
re-parsing cost for every commit just to find out if it has
a mergetag or signature. If we checked that when parsing the
commit initially, we could avoid re-examining most commits
later on. Even if we did pursue that direction, however,
this would still speed up the cases where we _do_ have
signatures. So it's probably worth doing either way.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-13 08:32:11 +02:00
|
|
|
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
2011-10-19 00:53:23 +02:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
status = verify_signed_buffer(payload.buf, payload.len,
|
|
|
|
signature.buf, signature.len,
|
2013-02-14 17:04:44 +01:00
|
|
|
&gpg_output, NULL);
|
2011-10-19 00:53:23 +02:00
|
|
|
if (status && !gpg_output.len)
|
|
|
|
strbuf_addstr(&gpg_output, "No signature\n");
|
|
|
|
|
2012-01-04 22:48:45 +01:00
|
|
|
show_sig_lines(opt, status, gpg_output.buf);
|
2011-10-19 00:53:23 +02:00
|
|
|
|
|
|
|
out:
|
|
|
|
strbuf_release(&gpg_output);
|
|
|
|
strbuf_release(&payload);
|
|
|
|
strbuf_release(&signature);
|
|
|
|
}
|
|
|
|
|
2017-05-07 00:10:18 +02:00
|
|
|
static int which_parent(const struct object_id *oid, const struct commit *commit)
|
2012-01-04 22:51:28 +01:00
|
|
|
{
|
|
|
|
int nth;
|
|
|
|
const struct commit_list *parent;
|
|
|
|
|
|
|
|
for (nth = 0, parent = commit->parents; parent; parent = parent->next) {
|
2017-05-07 00:10:18 +02:00
|
|
|
if (!oidcmp(&parent->item->object.oid, oid))
|
2012-01-04 22:51:28 +01:00
|
|
|
return nth;
|
|
|
|
nth++;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-05 01:23:12 +01:00
|
|
|
static int is_common_merge(const struct commit *commit)
|
|
|
|
{
|
|
|
|
return (commit->parents
|
|
|
|
&& commit->parents->next
|
|
|
|
&& !commit->parents->next->next);
|
|
|
|
}
|
|
|
|
|
2018-04-25 11:54:04 +02:00
|
|
|
static int show_one_mergetag(struct commit *commit,
|
|
|
|
struct commit_extra_header *extra,
|
|
|
|
void *data)
|
2012-01-04 22:51:28 +01:00
|
|
|
{
|
2014-07-07 08:35:37 +02:00
|
|
|
struct rev_info *opt = (struct rev_info *)data;
|
2017-05-07 00:10:18 +02:00
|
|
|
struct object_id oid;
|
2012-01-04 22:51:28 +01:00
|
|
|
struct tag *tag;
|
|
|
|
struct strbuf verify_message;
|
|
|
|
int status, nth;
|
|
|
|
size_t payload_size, gpg_message_offset;
|
|
|
|
|
2018-03-06 23:54:07 +01:00
|
|
|
hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid);
|
2017-05-07 00:10:19 +02:00
|
|
|
tag = lookup_tag(&oid);
|
2012-01-04 22:51:28 +01:00
|
|
|
if (!tag)
|
2018-04-25 11:54:04 +02:00
|
|
|
return -1; /* error message already given */
|
2012-01-04 22:51:28 +01:00
|
|
|
|
|
|
|
strbuf_init(&verify_message, 256);
|
|
|
|
if (parse_tag_buffer(tag, extra->value, extra->len))
|
|
|
|
strbuf_addstr(&verify_message, "malformed mergetag\n");
|
2012-01-05 01:23:12 +01:00
|
|
|
else if (is_common_merge(commit) &&
|
2015-11-10 03:22:28 +01:00
|
|
|
!oidcmp(&tag->tagged->oid,
|
|
|
|
&commit->parents->next->item->object.oid))
|
2012-01-05 01:23:12 +01:00
|
|
|
strbuf_addf(&verify_message,
|
|
|
|
"merged tag '%s'\n", tag->tag);
|
2017-05-07 00:10:18 +02:00
|
|
|
else if ((nth = which_parent(&tag->tagged->oid, commit)) < 0)
|
2012-01-04 22:51:28 +01:00
|
|
|
strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
|
2015-11-10 03:22:29 +01:00
|
|
|
tag->tag, tag->tagged->oid.hash);
|
2012-01-04 22:51:28 +01:00
|
|
|
else
|
|
|
|
strbuf_addf(&verify_message,
|
|
|
|
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
|
|
|
|
gpg_message_offset = verify_message.len;
|
|
|
|
|
|
|
|
payload_size = parse_signature(extra->value, extra->len);
|
2013-02-14 17:04:43 +01:00
|
|
|
status = -1;
|
2014-06-27 15:18:36 +02:00
|
|
|
if (extra->len > payload_size) {
|
|
|
|
/* could have a good signature */
|
|
|
|
if (!verify_signed_buffer(extra->value, payload_size,
|
|
|
|
extra->value + payload_size,
|
|
|
|
extra->len - payload_size,
|
|
|
|
&verify_message, NULL))
|
|
|
|
status = 0; /* good */
|
|
|
|
else if (verify_message.len <= gpg_message_offset)
|
|
|
|
strbuf_addstr(&verify_message, "No signature\n");
|
|
|
|
/* otherwise we couldn't verify, which is shown as bad */
|
|
|
|
}
|
2012-01-04 22:51:28 +01:00
|
|
|
|
|
|
|
show_sig_lines(opt, status, verify_message.buf);
|
|
|
|
strbuf_release(&verify_message);
|
2018-04-25 11:54:04 +02:00
|
|
|
return 0;
|
2012-01-04 22:51:28 +01:00
|
|
|
}
|
|
|
|
|
2018-04-25 11:54:04 +02:00
|
|
|
static int show_mergetag(struct rev_info *opt, struct commit *commit)
|
2012-01-04 22:51:28 +01:00
|
|
|
{
|
2018-04-25 11:54:04 +02:00
|
|
|
return for_each_mergetag(show_one_mergetag, commit, opt);
|
2012-01-04 22:51:28 +01:00
|
|
|
}
|
|
|
|
|
2008-04-29 10:32:59 +02:00
|
|
|
void show_log(struct rev_info *opt)
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
{
|
2008-10-09 21:12:12 +02:00
|
|
|
struct strbuf msgbuf = STRBUF_INIT;
|
2006-06-25 12:54:14 +02:00
|
|
|
struct log_info *log = opt->loginfo;
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
struct commit *commit = log->commit, *parent = log->parent;
|
2017-05-07 00:10:18 +02:00
|
|
|
int abbrev_commit = opt->abbrev_commit ? opt->abbrev : GIT_SHA1_HEXSZ;
|
2009-10-19 17:48:08 +02:00
|
|
|
const char *extra_headers = opt->extra_headers;
|
|
|
|
struct pretty_print_context ctx = {0};
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
|
|
|
opt->loginfo = NULL;
|
|
|
|
if (!opt->verbose_header) {
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_commit(opt->graph);
|
|
|
|
|
2011-03-07 13:31:39 +01:00
|
|
|
if (!opt->graph)
|
2011-03-10 15:45:03 +01:00
|
|
|
put_revision_mark(opt, commit);
|
2018-03-12 03:27:30 +01:00
|
|
|
fputs(find_unique_abbrev(&commit->object.oid, abbrev_commit), opt->diffopt.file);
|
2008-05-04 12:36:52 +02:00
|
|
|
if (opt->print_parents)
|
2016-06-22 17:01:32 +02:00
|
|
|
show_parents(commit, abbrev_commit, opt->diffopt.file);
|
2011-10-04 16:02:03 +02:00
|
|
|
if (opt->children.name)
|
|
|
|
show_children(opt, commit, abbrev_commit);
|
2008-10-27 20:51:59 +01:00
|
|
|
show_decorations(opt, commit);
|
2008-05-04 12:36:54 +02:00
|
|
|
if (opt->graph && !graph_is_commit_finished(opt->graph)) {
|
2016-06-22 17:01:32 +02:00
|
|
|
putc('\n', opt->diffopt.file);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_remainder(opt->graph);
|
|
|
|
}
|
2016-06-22 17:01:32 +02:00
|
|
|
putc(opt->diffopt.line_termination, opt->diffopt.file);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-07-01 09:26:28 +02:00
|
|
|
* If use_terminator is set, we already handled any record termination
|
|
|
|
* at the end of the last record.
|
2008-04-29 10:32:59 +02:00
|
|
|
* Otherwise, add a diffopt.line_termination character before all
|
|
|
|
* entries but the first. (IOW, as a separator between entries)
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
*/
|
2008-05-04 12:36:54 +02:00
|
|
|
if (opt->shown_one && !opt->use_terminator) {
|
|
|
|
/*
|
|
|
|
* If entries are separated by a newline, the output
|
|
|
|
* should look human-readable. If the last entry ended
|
|
|
|
* with a newline, print the graph output before this
|
|
|
|
* newline. Otherwise it will end up as a completely blank
|
|
|
|
* line and will look like a gap in the graph.
|
|
|
|
*
|
|
|
|
* If the entry separator is not a newline, the output is
|
|
|
|
* primarily intended for programmatic consumption, and we
|
|
|
|
* never want the extra graph output before the entry
|
|
|
|
* separator.
|
|
|
|
*/
|
|
|
|
if (opt->diffopt.line_termination == '\n' &&
|
|
|
|
!opt->missing_newline)
|
|
|
|
graph_show_padding(opt->graph);
|
2016-06-22 17:01:32 +02:00
|
|
|
putc(opt->diffopt.line_termination, opt->diffopt.file);
|
2008-05-04 12:36:54 +02:00
|
|
|
}
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
opt->shown_one = 1;
|
|
|
|
|
2008-05-04 12:36:54 +02:00
|
|
|
/*
|
|
|
|
* If the history graph was requested,
|
|
|
|
* print the graph, up to this commit's line
|
|
|
|
*/
|
|
|
|
graph_show_commit(opt->graph);
|
|
|
|
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
/*
|
|
|
|
* Print header line of header..
|
|
|
|
*/
|
2006-04-19 01:45:27 +02:00
|
|
|
|
2016-06-05 06:46:39 +02:00
|
|
|
if (cmit_fmt_is_mail(opt->commit_format)) {
|
2017-03-01 12:37:07 +01:00
|
|
|
log_write_email_headers(opt, commit, &extra_headers,
|
2018-05-02 04:20:52 +02:00
|
|
|
&ctx.need_8bit_cte, 1);
|
2017-03-01 12:37:07 +01:00
|
|
|
ctx.rev = opt;
|
|
|
|
ctx.print_email_subject = 1;
|
2007-02-23 01:35:03 +01:00
|
|
|
} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
|
2016-06-22 17:01:32 +02:00
|
|
|
fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), opt->diffopt.file);
|
2006-12-17 00:31:25 +01:00
|
|
|
if (opt->commit_format != CMIT_FMT_ONELINE)
|
2016-06-22 17:01:32 +02:00
|
|
|
fputs("commit ", opt->diffopt.file);
|
2008-05-25 09:07:21 +02:00
|
|
|
|
2011-03-07 13:31:39 +01:00
|
|
|
if (!opt->graph)
|
2011-03-10 15:45:03 +01:00
|
|
|
put_revision_mark(opt, commit);
|
2018-03-12 03:27:30 +01:00
|
|
|
fputs(find_unique_abbrev(&commit->object.oid,
|
|
|
|
abbrev_commit),
|
2016-06-22 17:01:32 +02:00
|
|
|
opt->diffopt.file);
|
2008-05-04 12:36:52 +02:00
|
|
|
if (opt->print_parents)
|
2016-06-22 17:01:32 +02:00
|
|
|
show_parents(commit, abbrev_commit, opt->diffopt.file);
|
2011-10-04 16:02:03 +02:00
|
|
|
if (opt->children.name)
|
|
|
|
show_children(opt, commit, abbrev_commit);
|
2006-05-24 21:19:47 +02:00
|
|
|
if (parent)
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, " (from %s)",
|
2018-03-12 03:27:30 +01:00
|
|
|
find_unique_abbrev(&parent->object.oid, abbrev_commit));
|
2016-06-22 17:01:32 +02:00
|
|
|
fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file);
|
2008-10-27 20:51:59 +01:00
|
|
|
show_decorations(opt, commit);
|
2008-05-04 12:36:54 +02:00
|
|
|
if (opt->commit_format == CMIT_FMT_ONELINE) {
|
2016-06-22 17:01:32 +02:00
|
|
|
putc(' ', opt->diffopt.file);
|
2008-05-04 12:36:54 +02:00
|
|
|
} else {
|
2016-06-22 17:01:32 +02:00
|
|
|
putc('\n', opt->diffopt.file);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
|
|
|
}
|
2007-01-28 04:40:36 +01:00
|
|
|
if (opt->reflog_info) {
|
2008-05-04 12:36:54 +02:00
|
|
|
/*
|
|
|
|
* setup_revisions() ensures that opt->reflog_info
|
|
|
|
* and opt->graph cannot both be set,
|
|
|
|
* so we don't need to worry about printing the
|
|
|
|
* graph info here.
|
|
|
|
*/
|
2007-01-20 09:51:41 +01:00
|
|
|
show_reflog_message(opt->reflog_info,
|
2012-05-07 23:11:32 +02:00
|
|
|
opt->commit_format == CMIT_FMT_ONELINE,
|
convert "enum date_mode" into a struct
In preparation for adding date modes that may carry extra
information beyond the mode itself, this patch converts the
date_mode enum into a struct.
Most of the conversion is fairly straightforward; we pass
the struct as a pointer and dereference the type field where
necessary. Locations that declare a date_mode can use a "{}"
constructor. However, the tricky case is where we use the
enum labels as constants, like:
show_date(t, tz, DATE_NORMAL);
Ideally we could say:
show_date(t, tz, &{ DATE_NORMAL });
but of course C does not allow that. Likewise, we cannot
cast the constant to a struct, because we need to pass an
actual address. Our options are basically:
1. Manually add a "struct date_mode d = { DATE_NORMAL }"
definition to each caller, and pass "&d". This makes
the callers uglier, because they sometimes do not even
have their own scope (e.g., they are inside a switch
statement).
2. Provide a pre-made global "date_normal" struct that can
be passed by address. We'd also need "date_rfc2822",
"date_iso8601", and so forth. But at least the ugliness
is defined in one place.
3. Provide a wrapper that generates the correct struct on
the fly. The big downside is that we end up pointing to
a single global, which makes our wrapper non-reentrant.
But show_date is already not reentrant, so it does not
matter.
This patch implements 3, along with a minor macro to keep
the size of the callers sane.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-25 18:55:02 +02:00
|
|
|
&opt->date_mode,
|
2012-05-07 23:11:32 +02:00
|
|
|
opt->date_mode_explicit);
|
2008-04-29 10:32:59 +02:00
|
|
|
if (opt->commit_format == CMIT_FMT_ONELINE)
|
2007-01-28 04:40:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2006-04-19 01:45:27 +02:00
|
|
|
}
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
2012-01-04 22:51:28 +01:00
|
|
|
if (opt->show_signature) {
|
2011-10-19 00:53:23 +02:00
|
|
|
show_signature(opt, commit);
|
2012-01-04 22:51:28 +01:00
|
|
|
show_mergetag(opt, commit);
|
|
|
|
}
|
2011-10-19 00:53:23 +02:00
|
|
|
|
2012-10-18 03:51:47 +02:00
|
|
|
if (opt->show_notes) {
|
|
|
|
int raw;
|
|
|
|
struct strbuf notebuf = STRBUF_INIT;
|
|
|
|
|
|
|
|
raw = (opt->commit_format == CMIT_FMT_USERFORMAT);
|
2017-05-30 19:30:41 +02:00
|
|
|
format_display_notes(&commit->object.oid, ¬ebuf,
|
2012-10-18 03:51:47 +02:00
|
|
|
get_log_output_encoding(), raw);
|
|
|
|
ctx.notes_message = notebuf.len
|
|
|
|
? strbuf_detach(¬ebuf, NULL)
|
|
|
|
: xcalloc(1, 1);
|
|
|
|
}
|
|
|
|
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
/*
|
|
|
|
* And then the pretty-printed message itself
|
|
|
|
*/
|
2013-02-12 11:17:38 +01:00
|
|
|
if (ctx.need_8bit_cte >= 0 && opt->add_signoff)
|
|
|
|
ctx.need_8bit_cte =
|
|
|
|
has_non_ascii(fmt_name(getenv("GIT_COMMITTER_NAME"),
|
|
|
|
getenv("GIT_COMMITTER_EMAIL")));
|
2009-10-19 17:48:08 +02:00
|
|
|
ctx.date_mode = opt->date_mode;
|
log: respect date_mode_explicit with --format:%gd
When we show a reflog selector (e.g., via "git log -g"), we
perform some DWIM magic: while we normally show the entry's
index (e.g., HEAD@{1}), if the user has given us a date
with "--date", then we show a date-based select (e.g.,
HEAD@{yesterday}).
However, we don't want to trigger this magic if the
alternate date format we got was from the "log.date"
configuration; that is not sufficiently strong context for
us to invoke this particular magic. To fix this, commit
f4ea32f (improve reflog date/number heuristic, 2009-09-24)
introduced a "date_mode_explicit" flag in rev_info. This
flag is set only when we see a "--date" option on the
command line, and we a vanilla date to the reflog code if
the date was not explicit.
Later, commit 8f8f547 (Introduce new pretty formats %g[sdD]
for reflog information, 2009-10-19) added another way to
show selectors, and it did not respect the date_mode_explicit
flag from f4ea32f.
This patch propagates the date_mode_explicit flag to the
pretty-print code, which can then use it to pass the
appropriate date field to the reflog code. This brings the
behavior of "%gd" in line with the other formats, and means
that its output is independent of any user configuration.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-04 07:25:18 +02:00
|
|
|
ctx.date_mode_explicit = opt->date_mode_explicit;
|
2009-10-19 17:48:08 +02:00
|
|
|
ctx.abbrev = opt->diffopt.abbrev;
|
|
|
|
ctx.after_subject = extra_headers;
|
2011-05-27 00:28:17 +02:00
|
|
|
ctx.preserve_subject = opt->preserve_subject;
|
2009-10-19 17:48:10 +02:00
|
|
|
ctx.reflog_info = opt->reflog_info;
|
2011-05-27 00:27:49 +02:00
|
|
|
ctx.fmt = opt->commit_format;
|
2013-01-05 22:26:41 +01:00
|
|
|
ctx.mailmap = opt->mailmap;
|
2012-12-17 23:56:49 +01:00
|
|
|
ctx.color = opt->diffopt.use_color;
|
2016-03-16 17:15:53 +01:00
|
|
|
ctx.expand_tabs_in_log = opt->expand_tabs_in_log;
|
2013-06-26 12:19:50 +02:00
|
|
|
ctx.output_encoding = get_log_output_encoding();
|
teach format-patch to place other authors into in-body "From"
Format-patch generates emails with the "From" address set to the
author of each patch. If you are going to send the emails, however,
you would want to replace the author identity with yours (if they
are not the same), and bump the author identity to an in-body
header.
Normally this is handled by git-send-email, which does the
transformation before sending out the emails. However, some
workflows may not use send-email (e.g., imap-send, or a custom
script which feeds the mbox to a non-git MUA). They could each
implement this feature themselves, but getting it right is
non-trivial (one must canonicalize the identities by reversing any
RFC2047 encoding or RFC822 quoting of the headers, which has caused
many bugs in send-email over the years).
This patch takes a different approach: it teaches format-patch a
"--from" option which handles the ident check and in-body header
while it is writing out the email. It's much simpler to do at this
level (because we haven't done any quoting yet), and any workflow
based on format-patch can easily turn it on.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-03 09:08:22 +02:00
|
|
|
if (opt->from_ident.mail_begin && opt->from_ident.name_begin)
|
|
|
|
ctx.from_ident = &opt->from_ident;
|
2016-06-16 15:18:37 +02:00
|
|
|
if (opt->graph)
|
|
|
|
ctx.graph_width = graph_width(opt->graph);
|
2011-05-27 00:27:49 +02:00
|
|
|
pretty_print_commit(&ctx, commit, &msgbuf);
|
2012-10-18 05:48:25 +02:00
|
|
|
|
|
|
|
if (opt->add_signoff)
|
2013-02-12 11:17:38 +01:00
|
|
|
append_signoff(&msgbuf, 0, APPEND_SIGNOFF_DEDUP);
|
2012-10-18 05:48:25 +02:00
|
|
|
|
2012-10-18 04:02:46 +02:00
|
|
|
if ((ctx.fmt != CMIT_FMT_USERFORMAT) &&
|
2012-10-18 06:27:22 +02:00
|
|
|
ctx.notes_message && *ctx.notes_message) {
|
2016-06-05 06:46:39 +02:00
|
|
|
if (cmit_fmt_is_mail(ctx.fmt)) {
|
2012-10-18 06:27:22 +02:00
|
|
|
strbuf_addstr(&msgbuf, "---\n");
|
|
|
|
opt->shown_dashes = 1;
|
|
|
|
}
|
2012-10-18 04:02:46 +02:00
|
|
|
strbuf_addstr(&msgbuf, ctx.notes_message);
|
2012-10-18 06:27:22 +02:00
|
|
|
}
|
2006-06-01 00:11:49 +02:00
|
|
|
|
2008-05-04 12:36:54 +02:00
|
|
|
if (opt->show_log_size) {
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "log size %i\n", (int)msgbuf.len);
|
2008-05-04 12:36:54 +02:00
|
|
|
graph_show_oneline(opt->graph);
|
|
|
|
}
|
2007-07-20 20:15:13 +02:00
|
|
|
|
2008-05-04 12:36:54 +02:00
|
|
|
/*
|
|
|
|
* Set opt->missing_newline if msgbuf doesn't
|
|
|
|
* end in a newline (including if it is empty)
|
|
|
|
*/
|
|
|
|
if (!msgbuf.len || msgbuf.buf[msgbuf.len - 1] != '\n')
|
|
|
|
opt->missing_newline = 1;
|
|
|
|
else
|
|
|
|
opt->missing_newline = 0;
|
|
|
|
|
2016-09-01 01:27:20 +02:00
|
|
|
graph_show_commit_msg(opt->graph, opt->diffopt.file, &msgbuf);
|
2014-07-29 19:56:48 +02:00
|
|
|
if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
|
2008-05-04 12:36:54 +02:00
|
|
|
if (!opt->missing_newline)
|
|
|
|
graph_show_padding(opt->graph);
|
2016-06-22 17:01:32 +02:00
|
|
|
putc(opt->diffopt.line_termination, opt->diffopt.file);
|
2008-05-04 12:36:54 +02:00
|
|
|
}
|
|
|
|
|
2007-09-10 12:35:06 +02:00
|
|
|
strbuf_release(&msgbuf);
|
2012-10-18 03:51:47 +02:00
|
|
|
free(ctx.notes_message);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
}
|
|
|
|
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-15 01:52:13 +02:00
|
|
|
int log_tree_diff_flush(struct rev_info *opt)
|
2006-04-09 10:11:11 +02:00
|
|
|
{
|
2012-10-18 06:27:22 +02:00
|
|
|
opt->shown_dashes = 0;
|
2006-04-09 10:11:11 +02:00
|
|
|
diffcore_std(&opt->diffopt);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
2006-04-09 10:11:11 +02:00
|
|
|
if (diff_queue_is_empty()) {
|
|
|
|
int saved_fmt = opt->diffopt.output_format;
|
|
|
|
opt->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
|
|
|
|
diff_flush(&opt->diffopt);
|
|
|
|
opt->diffopt.output_format = saved_fmt;
|
|
|
|
return 0;
|
|
|
|
}
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
2006-06-28 00:08:19 +02:00
|
|
|
if (opt->loginfo && !opt->no_commit_id) {
|
2008-04-29 10:32:59 +02:00
|
|
|
show_log(opt);
|
2007-10-09 18:35:22 +02:00
|
|
|
if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
|
|
|
|
opt->verbose_header &&
|
2014-07-29 19:56:48 +02:00
|
|
|
opt->commit_format != CMIT_FMT_ONELINE &&
|
|
|
|
!commit_format_is_empty(opt->commit_format)) {
|
2012-11-13 19:09:07 +01:00
|
|
|
/*
|
|
|
|
* When showing a verbose header (i.e. log message),
|
|
|
|
* and not in --pretty=oneline format, we would want
|
|
|
|
* an extra newline between the end of log and the
|
|
|
|
* diff/diffstat output for readability.
|
|
|
|
*/
|
2006-06-28 00:08:19 +02:00
|
|
|
int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
|
2010-05-26 09:08:03 +02:00
|
|
|
if (opt->diffopt.output_prefix) {
|
|
|
|
struct strbuf *msg = NULL;
|
|
|
|
msg = opt->diffopt.output_prefix(&opt->diffopt,
|
|
|
|
opt->diffopt.output_prefix_data);
|
2016-06-22 17:01:32 +02:00
|
|
|
fwrite(msg->buf, msg->len, 1, opt->diffopt.file);
|
2010-05-26 09:08:03 +02:00
|
|
|
}
|
2012-11-13 19:09:07 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We may have shown three-dashes line early
|
|
|
|
* between notes and the log message, in which
|
|
|
|
* case we only want a blank line after the
|
|
|
|
* notes without (an extra) three-dashes line.
|
|
|
|
* Otherwise, we show the three-dashes line if
|
|
|
|
* we are showing the patch with diffstat, but
|
|
|
|
* in that case, there is no extra blank line
|
|
|
|
* after the three-dashes line.
|
|
|
|
*/
|
|
|
|
if (!opt->shown_dashes &&
|
|
|
|
(pch & opt->diffopt.output_format) == pch)
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "---");
|
|
|
|
putc('\n', opt->diffopt.file);
|
2006-06-28 00:08:19 +02:00
|
|
|
}
|
|
|
|
}
|
2006-04-09 10:11:11 +02:00
|
|
|
diff_flush(&opt->diffopt);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-15 01:52:13 +02:00
|
|
|
static int do_diff_combined(struct rev_info *opt, struct commit *commit)
|
2006-04-09 10:11:11 +02:00
|
|
|
{
|
2011-12-17 11:20:07 +01:00
|
|
|
diff_tree_combined_merge(commit, opt->dense_combined_merges, opt);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
return !opt->loginfo;
|
2006-04-09 10:11:11 +02:00
|
|
|
}
|
|
|
|
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
/*
|
|
|
|
* Show the diff of a commit.
|
|
|
|
*
|
|
|
|
* Return true if we printed any log info messages
|
|
|
|
*/
|
|
|
|
static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log_info *log)
|
2006-04-09 10:11:11 +02:00
|
|
|
{
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
int showed_log;
|
2006-04-09 10:11:11 +02:00
|
|
|
struct commit_list *parents;
|
2015-11-10 03:22:28 +01:00
|
|
|
struct object_id *oid;
|
2006-04-09 10:11:11 +02:00
|
|
|
|
2017-10-31 19:19:11 +01:00
|
|
|
if (!opt->diff && !opt->diffopt.flags.exit_with_status)
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
return 0;
|
|
|
|
|
2013-10-24 10:52:36 +02:00
|
|
|
parse_commit_or_die(commit);
|
2018-04-06 21:09:38 +02:00
|
|
|
oid = get_commit_tree_oid(commit);
|
2013-03-28 09:19:34 +01:00
|
|
|
|
2006-04-09 10:11:11 +02:00
|
|
|
/* Root commit? */
|
log: use true parents for diff even when rewriting
When using pathspec filtering in combination with diff-based log
output, parent simplification happens before the diff is computed.
The diff is therefore against the *simplified* parents.
This works okay, arguably by accident, in the normal case:
simplification reduces to one parent as long as the commit is TREESAME
to it. So the simplified parent of any given commit must have the
same tree contents on the filtered paths as its true (unfiltered)
parent.
However, --full-diff breaks this guarantee, and indeed gives pretty
spectacular results when comparing the output of
git log --graph --stat ...
git log --graph --full-diff --stat ...
(--graph internally kicks in parent simplification, much like
--parents).
To fix it, store a copy of the parent list before simplification (in a
slab) whenever --full-diff is in effect. Then use the stored parents
instead of the simplified ones in the commit display code paths. The
latter do not actually check for --full-diff to avoid duplicated code;
they just grab the original parents if save_parents() has not been
called for this revision walk.
For ordinary commits it should be obvious that this is the right thing
to do.
Merge commits are a bit subtle. Observe that with default
simplification, merge simplification is an all-or-nothing decision:
either the merge is TREESAME to one parent and disappears, or it is
different from all parents and the parent list remains intact.
Redundant parents are not pruned, so the existing code also shows them
as a merge.
So if we do show a merge commit, the parent list just consists of the
rewrite result on each parent. Running, e.g., --cc on this in
--full-diff mode is not very useful: if any commits were skipped, some
hunks will disagree with all sides of the merge (with one side,
because commits were skipped; with the others, because they didn't
have those changes in the first place). This triggers --cc showing
these hunks spuriously.
Therefore I believe that even for merge commits it is better to show
the diffs wrt. the original parents.
Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Thomas Rast <trast@inf.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-31 22:13:20 +02:00
|
|
|
parents = get_saved_parents(opt, commit);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
if (!parents) {
|
2006-10-26 18:52:39 +02:00
|
|
|
if (opt->show_root_diff) {
|
2017-05-30 19:30:57 +02:00
|
|
|
diff_root_tree_oid(oid, "", &opt->diffopt);
|
2006-10-26 18:52:39 +02:00
|
|
|
log_tree_diff_flush(opt);
|
|
|
|
}
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
return !opt->loginfo;
|
2006-04-09 10:11:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* More than one parent? */
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
if (parents && parents->next) {
|
2006-04-09 10:11:11 +02:00
|
|
|
if (opt->ignore_merges)
|
|
|
|
return 0;
|
|
|
|
else if (opt->combine_merges)
|
|
|
|
return do_diff_combined(opt, commit);
|
2010-02-10 02:11:49 +01:00
|
|
|
else if (opt->first_parent_only) {
|
|
|
|
/*
|
|
|
|
* Generate merge log entry only for the first
|
|
|
|
* parent, showing summary diff of the others
|
|
|
|
* we merged _in_.
|
|
|
|
*/
|
2013-10-24 10:52:36 +02:00
|
|
|
parse_commit_or_die(parents->item);
|
2018-04-06 21:09:38 +02:00
|
|
|
diff_tree_oid(get_commit_tree_oid(parents->item),
|
2017-05-30 19:31:03 +02:00
|
|
|
oid, "", &opt->diffopt);
|
2010-02-10 02:11:49 +01:00
|
|
|
log_tree_diff_flush(opt);
|
|
|
|
return !opt->loginfo;
|
|
|
|
}
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
|
|
|
/* If we show individual diffs, show the parent info */
|
|
|
|
log->parent = parents->item;
|
2006-04-09 10:11:11 +02:00
|
|
|
}
|
|
|
|
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
showed_log = 0;
|
|
|
|
for (;;) {
|
2006-04-09 10:11:11 +02:00
|
|
|
struct commit *parent = parents->item;
|
|
|
|
|
2013-10-24 10:52:36 +02:00
|
|
|
parse_commit_or_die(parent);
|
2018-04-06 21:09:38 +02:00
|
|
|
diff_tree_oid(get_commit_tree_oid(parent),
|
2017-05-30 19:31:03 +02:00
|
|
|
oid, "", &opt->diffopt);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
log_tree_diff_flush(opt);
|
|
|
|
|
|
|
|
showed_log |= !opt->loginfo;
|
|
|
|
|
|
|
|
/* Set up the log info for the next parent, if any.. */
|
|
|
|
parents = parents->next;
|
|
|
|
if (!parents)
|
|
|
|
break;
|
|
|
|
log->parent = parents->item;
|
|
|
|
opt->loginfo = log;
|
|
|
|
}
|
|
|
|
return showed_log;
|
|
|
|
}
|
|
|
|
|
|
|
|
int log_tree_commit(struct rev_info *opt, struct commit *commit)
|
|
|
|
{
|
|
|
|
struct log_info log;
|
2016-06-22 17:01:28 +02:00
|
|
|
int shown, close_file = opt->diffopt.close_file;
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
|
|
|
log.commit = commit;
|
|
|
|
log.parent = NULL;
|
|
|
|
opt->loginfo = &log;
|
2016-06-22 17:01:28 +02:00
|
|
|
opt->diffopt.close_file = 0;
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
|
Implement line-history search (git log -L)
This is a rewrite of much of Bo's work, mainly in an effort to split
it into smaller, easier to understand routines.
The algorithm is built around the struct range_set, which encodes a
series of line ranges as intervals [a,b). This is used in two
contexts:
* A set of lines we are tracking (which will change as we dig through
history).
* To encode diffs, as pairs of ranges.
The main routine is range_set_map_across_diff(). It processes the
diff between a commit C and some parent P. It determines which diff
hunks are relevant to the ranges tracked in C, and computes the new
ranges for P.
The algorithm is then simply to process history in topological order
from newest to oldest, computing ranges and (partial) diffs. At
branch points, we need to merge the ranges we are watching. We will
find that many commits do not affect the chosen ranges, and mark them
TREESAME (in addition to those already filtered by pathspec limiting).
Another pass of history simplification then gets rid of such commits.
This is wired as an extra filtering pass in the log machinery. This
currently only reduces code duplication, but should allow for other
simplifications and options to be used.
Finally, we hook a diff printer into the output chain. Ideally we
would wire directly into the diff logic, to optionally use features
like word diff. However, that will require some major reworking of
the diff chain, so we completely replace the output with our own diff
for now.
As this was a GSoC project, and has quite some history by now, many
people have helped. In no particular order, thanks go to
Jakub Narebski <jnareb@gmail.com>
Jens Lehmann <Jens.Lehmann@web.de>
Jonathan Nieder <jrnieder@gmail.com>
Junio C Hamano <gitster@pobox.com>
Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Will Palmer <wmpalmer@gmail.com>
Apologies to everyone I forgot.
Signed-off-by: Bo Yang <struggleyb.nku@gmail.com>
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-28 17:47:32 +01:00
|
|
|
if (opt->line_level_traverse)
|
|
|
|
return line_log_print(opt, commit);
|
|
|
|
|
2014-03-25 14:23:27 +01:00
|
|
|
if (opt->track_linear && !opt->linear && !opt->reverse_output_stage)
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
|
2006-04-19 01:45:27 +02:00
|
|
|
shown = log_tree_diff(opt, commit, &log);
|
|
|
|
if (!shown && opt->loginfo && opt->always_show_header) {
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
log.parent = NULL;
|
2008-04-29 10:32:59 +02:00
|
|
|
show_log(opt);
|
2006-04-19 01:45:27 +02:00
|
|
|
shown = 1;
|
2006-04-09 10:11:11 +02:00
|
|
|
}
|
2014-03-25 14:23:27 +01:00
|
|
|
if (opt->track_linear && !opt->linear && opt->reverse_output_stage)
|
2016-06-22 17:01:32 +02:00
|
|
|
fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 20:59:32 +02:00
|
|
|
opt->loginfo = NULL;
|
2016-06-22 17:01:32 +02:00
|
|
|
maybe_flush_or_die(opt->diffopt.file, "stdout");
|
2016-06-22 17:01:28 +02:00
|
|
|
if (close_file)
|
|
|
|
fclose(opt->diffopt.file);
|
2006-04-19 01:45:27 +02:00
|
|
|
return shown;
|
2006-04-09 10:11:11 +02:00
|
|
|
}
|