2006-04-21 17:27:34 +00:00
|
|
|
/*
|
|
|
|
* Builtin "git log" and related commands (show, whatchanged)
|
|
|
|
*
|
|
|
|
* (C) Copyright 2006 Linus Torvalds
|
|
|
|
* 2006 Junio Hamano
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
2017-06-14 18:07:36 +00:00
|
|
|
#include "config.h"
|
2015-06-22 14:03:05 +00:00
|
|
|
#include "refs.h"
|
2018-05-15 23:42:15 +00:00
|
|
|
#include "object-store.h"
|
2008-02-18 07:26:03 +00:00
|
|
|
#include "color.h"
|
2006-04-21 17:27:34 +00:00
|
|
|
#include "commit.h"
|
|
|
|
#include "diff.h"
|
2020-12-21 15:19:33 +00:00
|
|
|
#include "diff-merges.h"
|
2006-04-21 17:27:34 +00:00
|
|
|
#include "revision.h"
|
|
|
|
#include "log-tree.h"
|
2006-04-21 20:19:58 +00:00
|
|
|
#include "builtin.h"
|
2006-12-14 10:31:05 +00:00
|
|
|
#include "tag.h"
|
2007-02-08 17:51:56 +00:00
|
|
|
#include "reflog-walk.h"
|
2007-04-10 00:01:27 +00:00
|
|
|
#include "patch-ids.h"
|
2008-02-19 03:56:13 +00:00
|
|
|
#include "run-command.h"
|
2008-02-25 23:24:17 +00:00
|
|
|
#include "shortlog.h"
|
2008-12-29 17:45:20 +00:00
|
|
|
#include "remote.h"
|
2009-02-19 21:26:31 +00:00
|
|
|
#include "string-list.h"
|
2009-05-16 09:24:46 +00:00
|
|
|
#include "parse-options.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 16:47:32 +00:00
|
|
|
#include "line-log.h"
|
2011-09-22 03:32:28 +00:00
|
|
|
#include "branch.h"
|
2012-03-07 10:54:19 +00:00
|
|
|
#include "streaming.h"
|
2012-06-02 18:51:42 +00:00
|
|
|
#include "version.h"
|
2013-01-05 21:26:43 +00:00
|
|
|
#include "mailmap.h"
|
2013-03-27 15:13:39 +00:00
|
|
|
#include "gpg-interface.h"
|
2017-08-10 18:32:55 +00:00
|
|
|
#include "progress.h"
|
2018-05-19 05:28:29 +00:00
|
|
|
#include "commit-slab.h"
|
2018-06-29 01:21:51 +00:00
|
|
|
#include "repository.h"
|
2018-07-20 16:33:04 +00:00
|
|
|
#include "commit-reach.h"
|
2018-07-22 09:57:13 +00:00
|
|
|
#include "range-diff.h"
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
#include "tmp-objdir.h"
|
2006-04-21 17:27:34 +00:00
|
|
|
|
2018-01-25 11:59:26 +00:00
|
|
|
#define MAIL_DEFAULT_WRAP 72
|
2019-10-15 09:06:40 +00:00
|
|
|
#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
#define FORMAT_PATCH_NAME_MAX_DEFAULT 64
|
2018-01-25 11:59:26 +00:00
|
|
|
|
2008-05-22 15:24:07 +00:00
|
|
|
/* Set a default date-time format for git log ("log.date" config variable) */
|
|
|
|
static const char *default_date_mode = NULL;
|
|
|
|
|
2011-05-18 17:56:04 +00:00
|
|
|
static int default_abbrev_commit;
|
2006-11-23 09:36:33 +00:00
|
|
|
static int default_show_root = 1;
|
2015-07-08 01:29:34 +00:00
|
|
|
static int default_follow;
|
2016-06-22 16:51:26 +00:00
|
|
|
static int default_show_signature;
|
2020-04-08 04:31:38 +00:00
|
|
|
static int default_encode_email_headers = 1;
|
2010-02-17 18:20:49 +00:00
|
|
|
static int decoration_style;
|
2011-04-14 14:28:30 +00:00
|
|
|
static int decoration_given;
|
2019-08-01 21:48:34 +00:00
|
|
|
static int use_mailmap_config = 1;
|
2022-08-29 21:38:36 +00:00
|
|
|
static unsigned int force_in_body_from;
|
2022-12-22 20:16:19 +00:00
|
|
|
static int stdout_mboxrd;
|
2007-07-04 10:37:27 +00:00
|
|
|
static const char *fmt_patch_subject_prefix = "PATCH";
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
|
2008-03-02 09:05:53 +00:00
|
|
|
static const char *fmt_pretty;
|
2006-11-23 09:36:33 +00:00
|
|
|
|
2011-04-14 14:28:30 +00:00
|
|
|
static const char * const builtin_log_usage[] = {
|
2015-04-02 21:26:56 +00:00
|
|
|
N_("git log [<options>] [<revision-range>] [[--] <path>...]"),
|
2015-02-11 21:44:19 +00:00
|
|
|
N_("git show [<options>] <object>..."),
|
2011-04-14 14:28:30 +00:00
|
|
|
NULL
|
|
|
|
};
|
2009-08-06 10:47:21 +00: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 16:47:32 +00:00
|
|
|
struct line_opt_callback_data {
|
|
|
|
struct rev_info *rev;
|
|
|
|
const char *prefix;
|
|
|
|
struct string_list args;
|
|
|
|
};
|
|
|
|
|
2019-07-15 12:41:04 +00:00
|
|
|
static int session_is_interactive(void)
|
|
|
|
{
|
|
|
|
return isatty(1) || pager_in_use();
|
|
|
|
}
|
|
|
|
|
2017-03-24 05:46:31 +00:00
|
|
|
static int auto_decoration_style(void)
|
|
|
|
{
|
2019-07-15 12:41:04 +00:00
|
|
|
return session_is_interactive() ? DECORATE_SHORT_REFS : 0;
|
2017-03-24 05:46:31 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 18:20:50 +00:00
|
|
|
static int parse_decoration_style(const char *value)
|
2010-02-17 18:20:49 +00:00
|
|
|
{
|
2017-08-07 18:20:49 +00:00
|
|
|
switch (git_parse_maybe_bool(value)) {
|
2010-02-17 18:20:49 +00:00
|
|
|
case 1:
|
|
|
|
return DECORATE_SHORT_REFS;
|
|
|
|
case 0:
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!strcmp(value, "full"))
|
|
|
|
return DECORATE_FULL_REFS;
|
|
|
|
else if (!strcmp(value, "short"))
|
|
|
|
return DECORATE_SHORT_REFS;
|
2014-05-29 22:19:40 +00:00
|
|
|
else if (!strcmp(value, "auto"))
|
2017-03-24 05:46:31 +00:00
|
|
|
return auto_decoration_style();
|
2019-02-16 11:24:41 +00:00
|
|
|
/*
|
|
|
|
* Please update _git_log() in git-completion.bash when you
|
|
|
|
* add new decoration styles.
|
|
|
|
*/
|
2010-02-17 18:20:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-08-05 17:58:40 +00:00
|
|
|
static int use_default_decoration_filter = 1;
|
|
|
|
static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
|
|
|
|
static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
|
|
|
|
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
|
|
|
|
|
|
|
|
static int clear_decorations_callback(const struct option *opt,
|
|
|
|
const char *arg, int unset)
|
|
|
|
{
|
|
|
|
string_list_clear(&decorate_refs_include, 0);
|
|
|
|
string_list_clear(&decorate_refs_exclude, 0);
|
|
|
|
use_default_decoration_filter = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-14 14:28:30 +00:00
|
|
|
static int decorate_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
if (unset)
|
|
|
|
decoration_style = 0;
|
|
|
|
else if (arg)
|
2017-08-07 18:20:50 +00:00
|
|
|
decoration_style = parse_decoration_style(arg);
|
2011-04-14 14:28:30 +00:00
|
|
|
else
|
|
|
|
decoration_style = DECORATE_SHORT_REFS;
|
|
|
|
|
|
|
|
if (decoration_style < 0)
|
2014-09-14 22:07:10 +00:00
|
|
|
die(_("invalid --decorate option: %s"), arg);
|
2011-04-14 14:28:30 +00:00
|
|
|
|
|
|
|
decoration_given = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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 16:47:32 +00:00
|
|
|
static int log_line_range_callback(const struct option *option, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
struct line_opt_callback_data *data = option->value;
|
|
|
|
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
|
|
|
|
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 16:47:32 +00:00
|
|
|
if (!arg)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
data->rev->line_level_traverse = 1;
|
|
|
|
string_list_append(&data->args, arg);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
static void init_log_defaults(void)
|
|
|
|
{
|
2016-02-25 08:59:21 +00:00
|
|
|
init_diff_ui_defaults();
|
2017-05-14 18:00:58 +00:00
|
|
|
|
|
|
|
decoration_style = auto_decoration_style();
|
2016-02-25 08:59:20 +00:00
|
|
|
}
|
|
|
|
|
2011-04-01 09:20:31 +00:00
|
|
|
static void cmd_log_init_defaults(struct rev_info *rev)
|
2006-04-21 17:27:34 +00:00
|
|
|
{
|
2008-03-02 09:05:53 +00:00
|
|
|
if (fmt_pretty)
|
2008-04-08 00:11:34 +00:00
|
|
|
get_commit_format(fmt_pretty, rev);
|
2015-07-08 01:29:34 +00:00
|
|
|
if (default_follow)
|
2017-10-31 18:19:11 +00:00
|
|
|
rev->diffopt.flags.default_follow_renames = 1;
|
2006-04-21 17:27:34 +00:00
|
|
|
rev->verbose_header = 1;
|
2017-10-31 18:19:11 +00:00
|
|
|
rev->diffopt.flags.recursive = 1;
|
2012-03-01 12:26:41 +00:00
|
|
|
rev->diffopt.stat_width = -1; /* use full terminal width */
|
2012-03-01 12:26:46 +00:00
|
|
|
rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
|
2011-05-18 17:56:04 +00:00
|
|
|
rev->abbrev_commit = default_abbrev_commit;
|
2006-11-23 09:36:33 +00:00
|
|
|
rev->show_root_diff = default_show_root;
|
2007-07-04 10:37:27 +00:00
|
|
|
rev->subject_prefix = fmt_patch_subject_prefix;
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
rev->patch_name_max = fmt_patch_name_max;
|
2016-06-22 16:51:26 +00:00
|
|
|
rev->show_signature = default_show_signature;
|
2020-04-08 04:31:38 +00:00
|
|
|
rev->encode_email_headers = default_encode_email_headers;
|
2017-10-31 18:19:11 +00:00
|
|
|
rev->diffopt.flags.allow_textconv = 1;
|
2008-05-22 15:24:07 +00:00
|
|
|
|
|
|
|
if (default_date_mode)
|
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 16:55:02 +00:00
|
|
|
parse_date_format(default_date_mode, &rev->date_mode);
|
2011-04-01 09:20:31 +00:00
|
|
|
}
|
2008-05-22 15:24:07 +00:00
|
|
|
|
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful
decorations. This includes:
* The HEAD ref
* Branches (refs/heads/)
* Stashes (refs/stash)
* Tags (refs/tags/)
* Remote branches (refs/remotes/)
* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)
Each of these namespaces was selected due to existing test cases that
verify these namespaces appear in the decorations. In particular,
stashes and replace refs can have custom colors from the
color.decorate.<slot> config option.
While one test checks for a decoration from notes, it only applies to
the tip of refs/notes/commit (or its configured ref name). Notes form
their own kind of decoration instead. Modify the expected output for the
tests in t4013 that expect this note decoration. There are several
tests throughout the codebase that verify that --decorate-refs,
--decorate-refs-exclude, and log.excludeDecoration work as designed and
the tests continue to pass without intervention.
However, there are other refs that are less helpful to show as
decoration:
* Prefetch refs (refs/prefetch/)
* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)
* Bundle refs (refs/bundle/) [!]
[!] The bundle refs are part of a parallel series that bootstraps a repo
from a bundle file, storing the bundle's refs into the repo's
refs/bundle/ namespace.
In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set
log.excludeDecoration durin prefetch, 2021-01-19) added logic to add
refs/prefetch/ to the log.excludeDecoration config option. Additional
feedback pointed out that having such a side-effect can be confusing and
perhaps not helpful to users. Instead, we should hide these ref
namespaces that are being used by Git for internal reasons but are not
helpful for the users to see.
The way to provide a seamless user experience without setting the config
is to modify the default decoration filters to match our expectation of
what refs the user actually wants to see.
In builtin/log.c, after parsing the --decorate-refs and
--decorate-refs-exclude options from the command-line, call
set_default_decoration_filter(). This method populates the exclusions
from log.excludeDecoration, then checks if the list of pattern
modifications are empty. If none are specified, then the default set is
restricted to the set of inclusions mentioned earlier (HEAD, branches,
etc.). A previous change introduced the ref_namespaces array, which
includes all of these currently-used namespaces. The 'decoration' value
is non-zero when that namespace is associated with a special coloring
and fits into the list of "expected" decorations as described above,
which makes the implementation of this filter very simple.
Note that the logic in ref_filter_match() in log-tree.c follows this
matching pattern:
1. If there are exclusion patterns and the ref matches one, then ignore
the decoration.
2. If there are inclusion patterns and the ref matches one, then
definitely include the decoration.
3. If there are config-based exclusions from log.excludeDecoration and
the ref matches one, then ignore the decoration.
With this logic in mind, we need to ensure that we do not populate our
new defaults if any of these filters are manually set. Specifically, if
a user runs
git -c log.excludeDecoration=HEAD log
then we expect the HEAD decoration to not appear. If we left the default
inclusions in the set, then HEAD would match that inclusion before
reaching the config-based exclusions.
A potential alternative would be to check the list of default inclusions
at the end, after the config-based exclusions. This would still create a
behavior change for some uses of --decorate-refs-exclude=<X>, and could
be overwritten somewhat with --decorate-refs=refs/ and
--decorate-refs=HEAD. However, it no longer becomes possible to include
refs outside of the defaults while also excluding some using
log.excludeDecoration.
Another alternative would be to exclude the known namespaces that are
not intended to be shown. This would reduce the visible effect of the
change for expert users who use their own custom ref namespaces. The
implementation change would be very simple to swap due to our use of
ref_namespaces:
int i;
struct string_list *exclude = decoration_filter->exclude_ref_pattern;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < NAMESPACE__COUNT; i++) {
if (ref_namespaces[i].decoration)
continue;
string_list_append(exclude, ref_namespaces[i].ref);
}
The main downside of this approach is that we expect to add new hidden
namespaces in the future, and that means that Git versions will be less
stable in how they behave as those namespaces are added.
It is critical that we provide ways for expert users to disable this
behavior change via command-line options and config keys. These changes
will be implemented in a future change.
Add a test that checks that the defaults are not added when
--decorate-refs is specified. We verify this by showing that HEAD is not
included as it normally would. Also add a test that shows that the
default filter avoids the unwanted decorations from refs/prefetch,
refs/rebase-merge,
and refs/bundle.
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
|
|
|
static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
|
|
|
|
{
|
|
|
|
int i;
|
2022-08-05 17:58:41 +00:00
|
|
|
char *value = NULL;
|
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful
decorations. This includes:
* The HEAD ref
* Branches (refs/heads/)
* Stashes (refs/stash)
* Tags (refs/tags/)
* Remote branches (refs/remotes/)
* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)
Each of these namespaces was selected due to existing test cases that
verify these namespaces appear in the decorations. In particular,
stashes and replace refs can have custom colors from the
color.decorate.<slot> config option.
While one test checks for a decoration from notes, it only applies to
the tip of refs/notes/commit (or its configured ref name). Notes form
their own kind of decoration instead. Modify the expected output for the
tests in t4013 that expect this note decoration. There are several
tests throughout the codebase that verify that --decorate-refs,
--decorate-refs-exclude, and log.excludeDecoration work as designed and
the tests continue to pass without intervention.
However, there are other refs that are less helpful to show as
decoration:
* Prefetch refs (refs/prefetch/)
* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)
* Bundle refs (refs/bundle/) [!]
[!] The bundle refs are part of a parallel series that bootstraps a repo
from a bundle file, storing the bundle's refs into the repo's
refs/bundle/ namespace.
In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set
log.excludeDecoration durin prefetch, 2021-01-19) added logic to add
refs/prefetch/ to the log.excludeDecoration config option. Additional
feedback pointed out that having such a side-effect can be confusing and
perhaps not helpful to users. Instead, we should hide these ref
namespaces that are being used by Git for internal reasons but are not
helpful for the users to see.
The way to provide a seamless user experience without setting the config
is to modify the default decoration filters to match our expectation of
what refs the user actually wants to see.
In builtin/log.c, after parsing the --decorate-refs and
--decorate-refs-exclude options from the command-line, call
set_default_decoration_filter(). This method populates the exclusions
from log.excludeDecoration, then checks if the list of pattern
modifications are empty. If none are specified, then the default set is
restricted to the set of inclusions mentioned earlier (HEAD, branches,
etc.). A previous change introduced the ref_namespaces array, which
includes all of these currently-used namespaces. The 'decoration' value
is non-zero when that namespace is associated with a special coloring
and fits into the list of "expected" decorations as described above,
which makes the implementation of this filter very simple.
Note that the logic in ref_filter_match() in log-tree.c follows this
matching pattern:
1. If there are exclusion patterns and the ref matches one, then ignore
the decoration.
2. If there are inclusion patterns and the ref matches one, then
definitely include the decoration.
3. If there are config-based exclusions from log.excludeDecoration and
the ref matches one, then ignore the decoration.
With this logic in mind, we need to ensure that we do not populate our
new defaults if any of these filters are manually set. Specifically, if
a user runs
git -c log.excludeDecoration=HEAD log
then we expect the HEAD decoration to not appear. If we left the default
inclusions in the set, then HEAD would match that inclusion before
reaching the config-based exclusions.
A potential alternative would be to check the list of default inclusions
at the end, after the config-based exclusions. This would still create a
behavior change for some uses of --decorate-refs-exclude=<X>, and could
be overwritten somewhat with --decorate-refs=refs/ and
--decorate-refs=HEAD. However, it no longer becomes possible to include
refs outside of the defaults while also excluding some using
log.excludeDecoration.
Another alternative would be to exclude the known namespaces that are
not intended to be shown. This would reduce the visible effect of the
change for expert users who use their own custom ref namespaces. The
implementation change would be very simple to swap due to our use of
ref_namespaces:
int i;
struct string_list *exclude = decoration_filter->exclude_ref_pattern;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < NAMESPACE__COUNT; i++) {
if (ref_namespaces[i].decoration)
continue;
string_list_append(exclude, ref_namespaces[i].ref);
}
The main downside of this approach is that we expect to add new hidden
namespaces in the future, and that means that Git versions will be less
stable in how they behave as those namespaces are added.
It is critical that we provide ways for expert users to disable this
behavior change via command-line options and config keys. These changes
will be implemented in a future change.
Add a test that checks that the defaults are not added when
--decorate-refs is specified. We verify this by showing that HEAD is not
included as it normally would. Also add a test that shows that the
default filter avoids the unwanted decorations from refs/prefetch,
refs/rebase-merge,
and refs/bundle.
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
|
|
|
struct string_list *include = decoration_filter->include_ref_pattern;
|
|
|
|
const struct string_list *config_exclude =
|
|
|
|
git_config_get_value_multi("log.excludeDecoration");
|
|
|
|
|
|
|
|
if (config_exclude) {
|
|
|
|
struct string_list_item *item;
|
|
|
|
for_each_string_list_item(item, config_exclude)
|
|
|
|
string_list_append(decoration_filter->exclude_ref_config_pattern,
|
|
|
|
item->string);
|
|
|
|
}
|
|
|
|
|
2022-08-05 17:58:41 +00:00
|
|
|
/*
|
|
|
|
* By default, decorate_all is disabled. Enable it if
|
|
|
|
* log.initialDecorationSet=all. Don't ever disable it by config,
|
|
|
|
* since the command-line takes precedent.
|
|
|
|
*/
|
|
|
|
if (use_default_decoration_filter &&
|
|
|
|
!git_config_get_string("log.initialdecorationset", &value) &&
|
|
|
|
!strcmp("all", value))
|
|
|
|
use_default_decoration_filter = 0;
|
|
|
|
free(value);
|
|
|
|
|
2022-08-05 17:58:40 +00:00
|
|
|
if (!use_default_decoration_filter ||
|
|
|
|
decoration_filter->exclude_ref_pattern->nr ||
|
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful
decorations. This includes:
* The HEAD ref
* Branches (refs/heads/)
* Stashes (refs/stash)
* Tags (refs/tags/)
* Remote branches (refs/remotes/)
* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)
Each of these namespaces was selected due to existing test cases that
verify these namespaces appear in the decorations. In particular,
stashes and replace refs can have custom colors from the
color.decorate.<slot> config option.
While one test checks for a decoration from notes, it only applies to
the tip of refs/notes/commit (or its configured ref name). Notes form
their own kind of decoration instead. Modify the expected output for the
tests in t4013 that expect this note decoration. There are several
tests throughout the codebase that verify that --decorate-refs,
--decorate-refs-exclude, and log.excludeDecoration work as designed and
the tests continue to pass without intervention.
However, there are other refs that are less helpful to show as
decoration:
* Prefetch refs (refs/prefetch/)
* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)
* Bundle refs (refs/bundle/) [!]
[!] The bundle refs are part of a parallel series that bootstraps a repo
from a bundle file, storing the bundle's refs into the repo's
refs/bundle/ namespace.
In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set
log.excludeDecoration durin prefetch, 2021-01-19) added logic to add
refs/prefetch/ to the log.excludeDecoration config option. Additional
feedback pointed out that having such a side-effect can be confusing and
perhaps not helpful to users. Instead, we should hide these ref
namespaces that are being used by Git for internal reasons but are not
helpful for the users to see.
The way to provide a seamless user experience without setting the config
is to modify the default decoration filters to match our expectation of
what refs the user actually wants to see.
In builtin/log.c, after parsing the --decorate-refs and
--decorate-refs-exclude options from the command-line, call
set_default_decoration_filter(). This method populates the exclusions
from log.excludeDecoration, then checks if the list of pattern
modifications are empty. If none are specified, then the default set is
restricted to the set of inclusions mentioned earlier (HEAD, branches,
etc.). A previous change introduced the ref_namespaces array, which
includes all of these currently-used namespaces. The 'decoration' value
is non-zero when that namespace is associated with a special coloring
and fits into the list of "expected" decorations as described above,
which makes the implementation of this filter very simple.
Note that the logic in ref_filter_match() in log-tree.c follows this
matching pattern:
1. If there are exclusion patterns and the ref matches one, then ignore
the decoration.
2. If there are inclusion patterns and the ref matches one, then
definitely include the decoration.
3. If there are config-based exclusions from log.excludeDecoration and
the ref matches one, then ignore the decoration.
With this logic in mind, we need to ensure that we do not populate our
new defaults if any of these filters are manually set. Specifically, if
a user runs
git -c log.excludeDecoration=HEAD log
then we expect the HEAD decoration to not appear. If we left the default
inclusions in the set, then HEAD would match that inclusion before
reaching the config-based exclusions.
A potential alternative would be to check the list of default inclusions
at the end, after the config-based exclusions. This would still create a
behavior change for some uses of --decorate-refs-exclude=<X>, and could
be overwritten somewhat with --decorate-refs=refs/ and
--decorate-refs=HEAD. However, it no longer becomes possible to include
refs outside of the defaults while also excluding some using
log.excludeDecoration.
Another alternative would be to exclude the known namespaces that are
not intended to be shown. This would reduce the visible effect of the
change for expert users who use their own custom ref namespaces. The
implementation change would be very simple to swap due to our use of
ref_namespaces:
int i;
struct string_list *exclude = decoration_filter->exclude_ref_pattern;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < NAMESPACE__COUNT; i++) {
if (ref_namespaces[i].decoration)
continue;
string_list_append(exclude, ref_namespaces[i].ref);
}
The main downside of this approach is that we expect to add new hidden
namespaces in the future, and that means that Git versions will be less
stable in how they behave as those namespaces are added.
It is critical that we provide ways for expert users to disable this
behavior change via command-line options and config keys. These changes
will be implemented in a future change.
Add a test that checks that the defaults are not added when
--decorate-refs is specified. We verify this by showing that HEAD is not
included as it normally would. Also add a test that shows that the
default filter avoids the unwanted decorations from refs/prefetch,
refs/rebase-merge,
and refs/bundle.
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
|
|
|
decoration_filter->include_ref_pattern->nr ||
|
|
|
|
decoration_filter->exclude_ref_config_pattern->nr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No command-line or config options were given, so
|
|
|
|
* populate with sensible defaults.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
|
|
|
|
if (!ref_namespace[i].decoration)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
string_list_append(include, ref_namespace[i].ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-01 09:20:31 +00:00
|
|
|
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
|
|
|
|
struct rev_info *rev, struct setup_revision_opt *opt)
|
|
|
|
{
|
|
|
|
struct userformat_want w;
|
2019-08-01 21:48:34 +00:00
|
|
|
int quiet = 0, source = 0, mailmap;
|
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 16:47:32 +00:00
|
|
|
static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
|
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful
decorations. This includes:
* The HEAD ref
* Branches (refs/heads/)
* Stashes (refs/stash)
* Tags (refs/tags/)
* Remote branches (refs/remotes/)
* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)
Each of these namespaces was selected due to existing test cases that
verify these namespaces appear in the decorations. In particular,
stashes and replace refs can have custom colors from the
color.decorate.<slot> config option.
While one test checks for a decoration from notes, it only applies to
the tip of refs/notes/commit (or its configured ref name). Notes form
their own kind of decoration instead. Modify the expected output for the
tests in t4013 that expect this note decoration. There are several
tests throughout the codebase that verify that --decorate-refs,
--decorate-refs-exclude, and log.excludeDecoration work as designed and
the tests continue to pass without intervention.
However, there are other refs that are less helpful to show as
decoration:
* Prefetch refs (refs/prefetch/)
* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)
* Bundle refs (refs/bundle/) [!]
[!] The bundle refs are part of a parallel series that bootstraps a repo
from a bundle file, storing the bundle's refs into the repo's
refs/bundle/ namespace.
In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set
log.excludeDecoration durin prefetch, 2021-01-19) added logic to add
refs/prefetch/ to the log.excludeDecoration config option. Additional
feedback pointed out that having such a side-effect can be confusing and
perhaps not helpful to users. Instead, we should hide these ref
namespaces that are being used by Git for internal reasons but are not
helpful for the users to see.
The way to provide a seamless user experience without setting the config
is to modify the default decoration filters to match our expectation of
what refs the user actually wants to see.
In builtin/log.c, after parsing the --decorate-refs and
--decorate-refs-exclude options from the command-line, call
set_default_decoration_filter(). This method populates the exclusions
from log.excludeDecoration, then checks if the list of pattern
modifications are empty. If none are specified, then the default set is
restricted to the set of inclusions mentioned earlier (HEAD, branches,
etc.). A previous change introduced the ref_namespaces array, which
includes all of these currently-used namespaces. The 'decoration' value
is non-zero when that namespace is associated with a special coloring
and fits into the list of "expected" decorations as described above,
which makes the implementation of this filter very simple.
Note that the logic in ref_filter_match() in log-tree.c follows this
matching pattern:
1. If there are exclusion patterns and the ref matches one, then ignore
the decoration.
2. If there are inclusion patterns and the ref matches one, then
definitely include the decoration.
3. If there are config-based exclusions from log.excludeDecoration and
the ref matches one, then ignore the decoration.
With this logic in mind, we need to ensure that we do not populate our
new defaults if any of these filters are manually set. Specifically, if
a user runs
git -c log.excludeDecoration=HEAD log
then we expect the HEAD decoration to not appear. If we left the default
inclusions in the set, then HEAD would match that inclusion before
reaching the config-based exclusions.
A potential alternative would be to check the list of default inclusions
at the end, after the config-based exclusions. This would still create a
behavior change for some uses of --decorate-refs-exclude=<X>, and could
be overwritten somewhat with --decorate-refs=refs/ and
--decorate-refs=HEAD. However, it no longer becomes possible to include
refs outside of the defaults while also excluding some using
log.excludeDecoration.
Another alternative would be to exclude the known namespaces that are
not intended to be shown. This would reduce the visible effect of the
change for expert users who use their own custom ref namespaces. The
implementation change would be very simple to swap due to our use of
ref_namespaces:
int i;
struct string_list *exclude = decoration_filter->exclude_ref_pattern;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < NAMESPACE__COUNT; i++) {
if (ref_namespaces[i].decoration)
continue;
string_list_append(exclude, ref_namespaces[i].ref);
}
The main downside of this approach is that we expect to add new hidden
namespaces in the future, and that means that Git versions will be less
stable in how they behave as those namespaces are added.
It is critical that we provide ways for expert users to disable this
behavior change via command-line options and config keys. These changes
will be implemented in a future change.
Add a test that checks that the defaults are not added when
--decorate-refs is specified. We verify this by showing that HEAD is not
included as it normally would. Also add a test that shows that the
default filter avoids the unwanted decorations from refs/prefetch,
refs/rebase-merge,
and refs/bundle.
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
|
|
|
struct decoration_filter decoration_filter = {
|
|
|
|
.exclude_ref_pattern = &decorate_refs_exclude,
|
|
|
|
.include_ref_pattern = &decorate_refs_include,
|
|
|
|
.exclude_ref_config_pattern = &decorate_refs_exclude_config,
|
|
|
|
};
|
2018-05-19 05:28:24 +00:00
|
|
|
static struct revision_sources revision_sources;
|
2011-04-14 14:28:30 +00:00
|
|
|
|
|
|
|
const struct option builtin_log_options[] = {
|
2013-08-03 11:51:20 +00:00
|
|
|
OPT__QUIET(&quiet, N_("suppress diff output")),
|
2013-04-07 17:46:22 +00:00
|
|
|
OPT_BOOL(0, "source", &source, N_("show source")),
|
2021-01-06 14:44:03 +00:00
|
|
|
OPT_BOOL(0, "use-mailmap", &mailmap, N_("use mail map file")),
|
2020-03-16 20:30:38 +00:00
|
|
|
OPT_ALIAS(0, "mailmap", "use-mailmap"),
|
2022-08-05 17:58:40 +00:00
|
|
|
OPT_CALLBACK_F(0, "clear-decorations", NULL, NULL,
|
|
|
|
N_("clear all previously-defined decoration filters"),
|
|
|
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
|
|
|
|
clear_decorations_callback),
|
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 21:33:41 +00:00
|
|
|
OPT_STRING_LIST(0, "decorate-refs", &decorate_refs_include,
|
|
|
|
N_("pattern"), N_("only decorate refs that match <pattern>")),
|
|
|
|
OPT_STRING_LIST(0, "decorate-refs-exclude", &decorate_refs_exclude,
|
|
|
|
N_("pattern"), N_("do not decorate refs that match <pattern>")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK_F(0, "decorate", NULL, NULL, N_("decorate options"),
|
|
|
|
PARSE_OPT_OPTARG, decorate_callback),
|
2020-11-01 17:28:44 +00:00
|
|
|
OPT_CALLBACK('L', NULL, &line_cb, "range:file",
|
2021-01-06 14:44:03 +00:00
|
|
|
N_("trace the evolution of line range <start>,<end> or function :<funcname> in <file>"),
|
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 16:47:32 +00:00
|
|
|
log_line_range_callback),
|
2011-04-14 14:28:30 +00:00
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
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 16:47:32 +00:00
|
|
|
line_cb.rev = rev;
|
|
|
|
line_cb.prefix = prefix;
|
|
|
|
|
2013-01-05 21:26:46 +00:00
|
|
|
mailmap = use_mailmap_config;
|
2011-04-14 14:28:30 +00:00
|
|
|
argc = parse_options(argc, argv, prefix,
|
|
|
|
builtin_log_options, builtin_log_usage,
|
2022-08-19 16:03:57 +00:00
|
|
|
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
|
2011-04-14 14:28:30 +00:00
|
|
|
PARSE_OPT_KEEP_DASHDASH);
|
2006-12-25 19:48:35 +00:00
|
|
|
|
2011-05-28 19:25:24 +00:00
|
|
|
if (quiet)
|
|
|
|
rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;
|
log: fix --quiet synonym for -s
Originally the "--quiet" option was parsed by the
diff-option parser into the internal QUICK option. This had
the effect of silencing diff output from the log (which was
not intended, but happened to work and people started to
use it). But it also had other odd side effects at the diff
level (for example, it would suppress the second commit in
"git show A B").
To fix this, commit 1c40c36 converted log to parse-options
and handled the "quiet" option separately, not passing it
on to the diff code. However, it simply ignored the option,
which was a regression for people using it as a synonym for
"-s". Commit 01771a8 then fixed that by interpreting the
option to add DIFF_FORMAT_NO_OUTPUT to the list of output
formats.
However, that commit did not fix it in all cases. It sets
the flag after setup_revisions is called. Naively, this
makes sense because you would expect the setup_revisions
parser to overwrite our output format flag if "-p" or
another output format flag is seen.
However, that is not how the NO_OUTPUT flag works. We
actually store it in the bit-field as just another format.
At the end of setup_revisions, we call diff_setup_done,
which post-processes the bitfield and clears any other
formats if we have set NO_OUTPUT. By setting the flag after
setup_revisions is done, diff_setup_done does not have a
chance to make this tweak, and we end up with other format
options still set.
As a result, the flag would have no effect in "git log -p
--quiet" or "git show --quiet". Fix it by setting the
format flag before the call to setup_revisions.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-08-28 21:29:34 +00:00
|
|
|
argc = setup_revisions(argc, argv, rev, opt);
|
2008-05-22 15:24:07 +00:00
|
|
|
|
2011-04-14 14:28:30 +00:00
|
|
|
/* Any arguments at this point are not recognized */
|
|
|
|
if (argc > 1)
|
2014-09-14 22:07:10 +00:00
|
|
|
die(_("unrecognized argument: %s"), argv[1]);
|
2011-04-14 14:28:30 +00:00
|
|
|
|
2020-11-04 17:54:01 +00:00
|
|
|
if (rev->line_level_traverse && rev->prune_data.nr)
|
|
|
|
die(_("-L<range>:<file> cannot be used with pathspec"));
|
|
|
|
|
2010-04-13 20:31:12 +00:00
|
|
|
memset(&w, 0, sizeof(w));
|
|
|
|
userformat_find_requirements(NULL, &w);
|
|
|
|
|
|
|
|
if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
|
2010-01-20 21:59:36 +00:00
|
|
|
rev->show_notes = 1;
|
2010-03-12 17:04:26 +00:00
|
|
|
if (rev->show_notes)
|
2019-12-09 13:10:39 +00:00
|
|
|
load_display_notes(&rev->notes_opt);
|
2010-01-20 21:59:36 +00:00
|
|
|
|
2018-01-04 22:50:41 +00:00
|
|
|
if ((rev->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
|
|
|
|
rev->diffopt.filter || rev->diffopt.flags.follow_renames)
|
2006-06-25 12:39:35 +00:00
|
|
|
rev->always_show_header = 0;
|
2011-04-14 14:28:30 +00:00
|
|
|
|
2019-01-11 06:30:46 +00:00
|
|
|
if (source || w.source) {
|
2018-05-19 05:28:24 +00:00
|
|
|
init_revision_sources(&revision_sources);
|
|
|
|
rev->sources = &revision_sources;
|
|
|
|
}
|
2010-04-06 21:48:55 +00:00
|
|
|
|
2013-01-05 21:26:43 +00:00
|
|
|
if (mailmap) {
|
2022-04-13 20:01:32 +00:00
|
|
|
rev->mailmap = xmalloc(sizeof(struct string_list));
|
|
|
|
string_list_init_nodup(rev->mailmap);
|
2021-01-12 20:18:06 +00:00
|
|
|
read_mailmap(rev->mailmap);
|
2013-01-05 21:26:43 +00:00
|
|
|
}
|
|
|
|
|
2011-05-18 17:56:04 +00:00
|
|
|
if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
|
|
|
|
/*
|
|
|
|
* "log --pretty=raw" is special; ignore UI oriented
|
|
|
|
* configuration variables such as decoration.
|
|
|
|
*/
|
|
|
|
if (!decoration_given)
|
|
|
|
decoration_style = 0;
|
|
|
|
if (!rev->abbrev_commit_given)
|
|
|
|
rev->abbrev_commit = 0;
|
|
|
|
}
|
2010-04-06 21:48:55 +00:00
|
|
|
|
log: handle --decorate-refs with userformat "%d"
In order to show ref decorations, we first have to load them. If you
run:
git log --decorate
then git-log will recognize the option and load them up front via
cmd_log_init(). Likewise if log.decorate is set.
If you don't say --decorate explicitly, but do mention "%d" or "%D" in
the output format, like so:
git log --format=%d
then this also works, because we lazy-load the ref decorations. This has
been true since 3b3d443feb (add '%d' pretty format specifier to show
decoration, 2008-09-04), though the lazy-load was later moved into
log-tree.c.
But there's one problem: that lazy-load just uses the defaults; it
doesn't take into account any --decorate-refs options (or its exclude
variant, or their config). So this does not work:
git log --decorate-refs=whatever --format=%d
It will decorate using all refs, not just the specified ones. This has
been true since --decorate-refs was added in 65516f586b (log: add option
to choose which refs to decorate, 2017-11-21). Adding further confusion
is that it _may_ work because of the auto-decoration feature. If that's
in use (and it often is, as it's the default), then if the output is
going to stdout, we do enable decorations early (and so load them up
front, respecting the extra options). But otherwise we do not. So:
git log --decorate-refs=whatever --format=%d >some-file
would typically behave differently than it does when the output goes to
the pager or terminal!
The solution is simple: we should recognize in cmd_log_init() that we're
going to show decorations, and make sure we load them there. We already
check userformat_find_requirements(), so we can couple this with our
existing code there.
There are two new tests. The first shows off the actual fix. The second
makes sure that our fix doesn't cause us to stomp on an existing
--decorate option (see the new comment in the code, as well).
Reported-by: Josh Rampersad <josh.rampersad@voiceflow.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-12-02 05:35:43 +00:00
|
|
|
if (rev->commit_format == CMIT_FMT_USERFORMAT) {
|
|
|
|
if (!w.decorate) {
|
|
|
|
/*
|
|
|
|
* Disable decoration loading if the format will not
|
|
|
|
* show them anyway.
|
|
|
|
*/
|
|
|
|
decoration_style = 0;
|
|
|
|
} else if (!decoration_style) {
|
|
|
|
/*
|
|
|
|
* If we are going to show them, make sure we do load
|
|
|
|
* them here, but taking care not to override a
|
|
|
|
* specific style set by config or --decorate.
|
|
|
|
*/
|
|
|
|
decoration_style = DECORATE_SHORT_REFS;
|
|
|
|
}
|
|
|
|
}
|
2021-06-22 16:04:50 +00:00
|
|
|
|
2021-12-02 05:37:53 +00:00
|
|
|
if (decoration_style || rev->simplify_by_decoration) {
|
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful
decorations. This includes:
* The HEAD ref
* Branches (refs/heads/)
* Stashes (refs/stash)
* Tags (refs/tags/)
* Remote branches (refs/remotes/)
* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)
Each of these namespaces was selected due to existing test cases that
verify these namespaces appear in the decorations. In particular,
stashes and replace refs can have custom colors from the
color.decorate.<slot> config option.
While one test checks for a decoration from notes, it only applies to
the tip of refs/notes/commit (or its configured ref name). Notes form
their own kind of decoration instead. Modify the expected output for the
tests in t4013 that expect this note decoration. There are several
tests throughout the codebase that verify that --decorate-refs,
--decorate-refs-exclude, and log.excludeDecoration work as designed and
the tests continue to pass without intervention.
However, there are other refs that are less helpful to show as
decoration:
* Prefetch refs (refs/prefetch/)
* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)
* Bundle refs (refs/bundle/) [!]
[!] The bundle refs are part of a parallel series that bootstraps a repo
from a bundle file, storing the bundle's refs into the repo's
refs/bundle/ namespace.
In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set
log.excludeDecoration durin prefetch, 2021-01-19) added logic to add
refs/prefetch/ to the log.excludeDecoration config option. Additional
feedback pointed out that having such a side-effect can be confusing and
perhaps not helpful to users. Instead, we should hide these ref
namespaces that are being used by Git for internal reasons but are not
helpful for the users to see.
The way to provide a seamless user experience without setting the config
is to modify the default decoration filters to match our expectation of
what refs the user actually wants to see.
In builtin/log.c, after parsing the --decorate-refs and
--decorate-refs-exclude options from the command-line, call
set_default_decoration_filter(). This method populates the exclusions
from log.excludeDecoration, then checks if the list of pattern
modifications are empty. If none are specified, then the default set is
restricted to the set of inclusions mentioned earlier (HEAD, branches,
etc.). A previous change introduced the ref_namespaces array, which
includes all of these currently-used namespaces. The 'decoration' value
is non-zero when that namespace is associated with a special coloring
and fits into the list of "expected" decorations as described above,
which makes the implementation of this filter very simple.
Note that the logic in ref_filter_match() in log-tree.c follows this
matching pattern:
1. If there are exclusion patterns and the ref matches one, then ignore
the decoration.
2. If there are inclusion patterns and the ref matches one, then
definitely include the decoration.
3. If there are config-based exclusions from log.excludeDecoration and
the ref matches one, then ignore the decoration.
With this logic in mind, we need to ensure that we do not populate our
new defaults if any of these filters are manually set. Specifically, if
a user runs
git -c log.excludeDecoration=HEAD log
then we expect the HEAD decoration to not appear. If we left the default
inclusions in the set, then HEAD would match that inclusion before
reaching the config-based exclusions.
A potential alternative would be to check the list of default inclusions
at the end, after the config-based exclusions. This would still create a
behavior change for some uses of --decorate-refs-exclude=<X>, and could
be overwritten somewhat with --decorate-refs=refs/ and
--decorate-refs=HEAD. However, it no longer becomes possible to include
refs outside of the defaults while also excluding some using
log.excludeDecoration.
Another alternative would be to exclude the known namespaces that are
not intended to be shown. This would reduce the visible effect of the
change for expert users who use their own custom ref namespaces. The
implementation change would be very simple to swap due to our use of
ref_namespaces:
int i;
struct string_list *exclude = decoration_filter->exclude_ref_pattern;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < NAMESPACE__COUNT; i++) {
if (ref_namespaces[i].decoration)
continue;
string_list_append(exclude, ref_namespaces[i].ref);
}
The main downside of this approach is that we expect to add new hidden
namespaces in the future, and that means that Git versions will be less
stable in how they behave as those namespaces are added.
It is critical that we provide ways for expert users to disable this
behavior change via command-line options and config keys. These changes
will be implemented in a future change.
Add a test that checks that the defaults are not added when
--decorate-refs is specified. We verify this by showing that HEAD is not
included as it normally would. Also add a test that shows that the
default filter avoids the unwanted decorations from refs/prefetch,
refs/rebase-merge,
and refs/bundle.
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
|
|
|
set_default_decoration_filter(&decoration_filter);
|
2020-04-16 14:15:49 +00:00
|
|
|
|
2021-12-02 05:37:53 +00:00
|
|
|
if (decoration_style)
|
|
|
|
rev->show_decorations = 1;
|
2020-04-16 14:15:49 +00: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 21:33:41 +00:00
|
|
|
load_ref_decorations(&decoration_filter, decoration_style);
|
2009-08-15 14:23:12 +00: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 16:47:32 +00:00
|
|
|
|
|
|
|
if (rev->line_level_traverse)
|
|
|
|
line_log_init(rev, line_cb.prefix, &line_cb.args);
|
|
|
|
|
2010-08-24 17:33:59 +00:00
|
|
|
setup_pager();
|
2006-06-25 12:39:35 +00:00
|
|
|
}
|
|
|
|
|
2011-04-01 09:20:31 +00:00
|
|
|
static void cmd_log_init(int argc, const char **argv, const char *prefix,
|
|
|
|
struct rev_info *rev, struct setup_revision_opt *opt)
|
|
|
|
{
|
|
|
|
cmd_log_init_defaults(rev);
|
|
|
|
cmd_log_init_finish(argc, argv, prefix, rev, opt);
|
|
|
|
}
|
|
|
|
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
static int cmd_log_deinit(int ret, struct rev_info *rev)
|
|
|
|
{
|
|
|
|
release_revisions(rev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-11-04 20:12:05 +00:00
|
|
|
/*
|
|
|
|
* This gives a rough estimate for how many commits we
|
|
|
|
* will print out in the list.
|
|
|
|
*/
|
2019-03-20 08:13:42 +00:00
|
|
|
static int estimate_commit_count(struct commit_list *list)
|
2007-11-04 20:12:05 +00:00
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while (list) {
|
|
|
|
struct commit *commit = list->item;
|
|
|
|
unsigned int flags = commit->object.flags;
|
|
|
|
list = list->next;
|
2007-11-13 07:16:08 +00:00
|
|
|
if (!(flags & (TREESAME | UNINTERESTING)))
|
2007-11-05 21:22:34 +00:00
|
|
|
n++;
|
2007-11-04 20:12:05 +00:00
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_early_header(struct rev_info *rev, const char *stage, int nr)
|
|
|
|
{
|
|
|
|
if (rev->shown_one) {
|
|
|
|
rev->shown_one = 0;
|
|
|
|
if (rev->commit_format != CMIT_FMT_ONELINE)
|
|
|
|
putchar(rev->diffopt.line_termination);
|
|
|
|
}
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
|
2007-11-04 20:12:05 +00:00
|
|
|
}
|
|
|
|
|
2009-06-18 17:28:43 +00:00
|
|
|
static struct itimerval early_output_timer;
|
2007-11-04 20:12:05 +00:00
|
|
|
|
2007-11-03 18:11:10 +00:00
|
|
|
static void log_show_early(struct rev_info *revs, struct commit_list *list)
|
|
|
|
{
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
int i = revs->early_output;
|
2007-11-04 20:12:05 +00:00
|
|
|
int show_header = 1;
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
int no_free = revs->diffopt.no_free;
|
2007-11-03 18:11:10 +00:00
|
|
|
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
revs->diffopt.no_free = 0;
|
toposort: rename "lifo" field
The primary invariant of sort_in_topological_order() is that a
parent commit is not emitted until all children of it are. When
traversing a forked history like this with "git log C E":
A----B----C
\
D----E
we ensure that A is emitted after all of B, C, D, and E are done, B
has to wait until C is done, and D has to wait until E is done.
In some applications, however, we would further want to control how
these child commits B, C, D and E on two parallel ancestry chains
are shown.
Most of the time, we would want to see C and B emitted together, and
then E and D, and finally A (i.e. the --topo-order output). The
"lifo" parameter of the sort_in_topological_order() function is used
to control this behaviour. We start the traversal by knowing two
commits, C and E. While keeping in mind that we also need to
inspect E later, we pick C first to inspect, and we notice and
record that B needs to be inspected. By structuring the "work to be
done" set as a LIFO stack, we ensure that B is inspected next,
before other in-flight commits we had known that we will need to
inspect, e.g. E.
When showing in --date-order, we would want to see commits ordered
by timestamps, i.e. show C, E, B and D in this order before showing
A, possibly mixing commits from two parallel histories together.
When "lifo" parameter is set to false, the function keeps the "work
to be done" set sorted in the date order to realize this semantics.
After inspecting C, we add B to the "work to be done" set, but the
next commit we inspect from the set is E which is newer than B.
The name "lifo", however, is too strongly tied to the way how the
function implements its behaviour, and does not describe what the
behaviour _means_.
Replace this field with an enum rev_sort_order, with two possible
values: REV_SORT_IN_GRAPH_ORDER and REV_SORT_BY_COMMIT_DATE, and
update the existing code. The mechanical replacement rule is:
"lifo == 0" is equivalent to "sort_order == REV_SORT_BY_COMMIT_DATE"
"lifo == 1" is equivalent to "sort_order == REV_SORT_IN_GRAPH_ORDER"
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-06-06 23:07:14 +00:00
|
|
|
sort_in_topological_order(&list, revs->sort_order);
|
2007-11-03 18:11:10 +00:00
|
|
|
while (list && i) {
|
|
|
|
struct commit *commit = list->item;
|
2007-11-04 20:12:05 +00:00
|
|
|
switch (simplify_commit(revs, commit)) {
|
|
|
|
case commit_show:
|
|
|
|
if (show_header) {
|
2019-03-20 08:13:42 +00:00
|
|
|
int n = estimate_commit_count(list);
|
2007-11-04 20:12:05 +00:00
|
|
|
show_early_header(revs, "incomplete", n);
|
|
|
|
show_header = 0;
|
|
|
|
}
|
|
|
|
log_tree_commit(revs, commit);
|
|
|
|
i--;
|
|
|
|
break;
|
|
|
|
case commit_ignore:
|
|
|
|
break;
|
|
|
|
case commit_error:
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
revs->diffopt.no_free = no_free;
|
|
|
|
diff_free(&revs->diffopt);
|
2007-11-04 20:12:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-11-03 18:11:10 +00:00
|
|
|
list = list->next;
|
|
|
|
}
|
2007-11-04 20:12:05 +00:00
|
|
|
|
|
|
|
/* Did we already get enough commits for the early output? */
|
2016-06-22 15:01:28 +00:00
|
|
|
if (!i) {
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
revs->diffopt.no_free = 0;
|
|
|
|
diff_free(&revs->diffopt);
|
2007-11-04 20:12:05 +00:00
|
|
|
return;
|
2016-06-22 15:01:28 +00:00
|
|
|
}
|
2007-11-04 20:12:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ..if no, then repeat it twice a second until we
|
|
|
|
* do.
|
|
|
|
*
|
|
|
|
* NOTE! We don't use "it_interval", because if the
|
|
|
|
* reader isn't listening, we want our output to be
|
|
|
|
* throttled by the writing, and not have the timer
|
|
|
|
* trigger every second even if we're blocked on a
|
|
|
|
* reader!
|
|
|
|
*/
|
|
|
|
early_output_timer.it_value.tv_sec = 0;
|
|
|
|
early_output_timer.it_value.tv_usec = 500000;
|
|
|
|
setitimer(ITIMER_REAL, &early_output_timer, NULL);
|
2007-11-03 18:11:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void early_output(int signal)
|
|
|
|
{
|
|
|
|
show_early_output = log_show_early;
|
|
|
|
}
|
|
|
|
|
2019-03-20 08:13:42 +00:00
|
|
|
static void setup_early_output(void)
|
2007-11-03 18:11:10 +00:00
|
|
|
{
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the signal handler, minimally intrusively:
|
|
|
|
* we only set a single volatile integer word (not
|
|
|
|
* using sigatomic_t - trying to avoid unnecessary
|
|
|
|
* system dependencies and headers), and using
|
|
|
|
* SA_RESTART.
|
|
|
|
*/
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
sa.sa_handler = early_output;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = SA_RESTART;
|
|
|
|
sigaction(SIGALRM, &sa, NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we can get the whole output in less than a
|
|
|
|
* tenth of a second, don't even bother doing the
|
|
|
|
* early-output thing..
|
|
|
|
*
|
|
|
|
* This is a one-time-only trigger.
|
|
|
|
*/
|
2007-11-04 20:12:05 +00:00
|
|
|
early_output_timer.it_value.tv_sec = 0;
|
|
|
|
early_output_timer.it_value.tv_usec = 100000;
|
|
|
|
setitimer(ITIMER_REAL, &early_output_timer, NULL);
|
2007-11-03 18:11:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void finish_early_output(struct rev_info *rev)
|
|
|
|
{
|
2019-03-20 08:13:42 +00:00
|
|
|
int n = estimate_commit_count(rev->commits);
|
2007-11-03 18:11:10 +00:00
|
|
|
signal(SIGALRM, SIG_IGN);
|
2007-11-04 20:12:05 +00:00
|
|
|
show_early_header(rev, "done", n);
|
2007-11-03 18:11:10 +00:00
|
|
|
}
|
|
|
|
|
2.36 show regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
e900d494 (diff: add an API for deferred freeing, 2021-02-11)
introduced a mechanism to delay freeing resources held in
diff_options struct that need to be kept as long as the struct will
be reused to compute diff. "git log -p" was taught to utilize the
mechanism but it was done with an incorrect assumption that the
underlying helper function, cmd_log_walk(), is called only once,
and it is OK to do the freeing at the end of it.
Alas, for "git show A B", the function is called once for each
commit given, so it is not OK to free the resources until we finish
calling it for all the commits given from the command line.
During 2.36 release cycle, we started clearing the <pathspec> as
part of this freeing, which made the bug a lot more visible.
Fix this breakage by tweaking how cmd_log_walk() frees the resources
at the end and using a variant of it that does not immediately free
the resources to show each commit object from the command line in
"git show".
Protect the fix with a few new tests.
Reported-by: Daniel Li <dan@danielyli.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-30 05:29:51 +00:00
|
|
|
static int cmd_log_walk_no_free(struct rev_info *rev)
|
2006-06-25 12:39:35 +00:00
|
|
|
{
|
|
|
|
struct commit *commit;
|
2011-01-06 21:50:06 +00:00
|
|
|
int saved_nrl = 0;
|
diff: add an API for deferred freeing
Add a diff_free() function to free anything we may have allocated in
the "diff_options" struct, and the ability to make calling it a noop
by setting "no_free" in "diff_options".
This is required because when e.g. "git diff" is run we'll allocate
things in that struct, use the diff machinery once, and then exit.
But if we run e.g. "git log -p" we're going to re-use what we
allocated across multiple diff_flush() calls, and only want to free
things at the end.
We've thus ended up with features like the recently added "diff -I"[1]
where we'll leak memory. As it turns out it could have simply used the
pattern established in 6ea57703f6 (log: prepare log/log-tree to reuse
the diffopt.close_file attribute, 2016-06-22).
Manually adding more such flags to things log_tree_commit() every time
we need to allocate something would be tedious. Let's instead move
that fclose() code it to a new diff_free(), in anticipation of freeing
more things in that function in follow-up commits.
Some functions such as log_tree_commit() need an idiom of optionally
retaining a previous "no_free", as they may either free the memory
themselves, or their caller may do so. I'm keeping that idiom in
log_show_early() for good measure, even though I don't think it's
currently called in this manner. It also gets passed an existing
"struct rev_info", so future callers may want to set the "no_free"
flag.
This change is a bit hard to read because while the freeing pattern
we're introducing isn't unusual, the "file" member is a special
snowflake. We usually don't want to fclose() it. This is because
"file" is usually stdout, in which case we don't want to fclose()
it. We only want to opt-in to closing it when we e.g. open a file on
the filesystem. Thus the opt-in "close_file" flag.
So the API in general just needs a "no_free" flag to defer freeing,
but the "file" member still needs its "close_file" flag. This is made
more confusing because while refactoring this code we could replace
some "close_file=0" with "no_free=1", whereas others need to set both
flags.
This is because there were some cases where an existing "close_file=0"
meant "let's defer deallocation", and others where it meant "we don't
want to close this file handle at all".
1. 296d4a94e7 (diff: add -I<regex> that ignores matching changes,
2020-10-20)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 10:45:34 +00:00
|
|
|
int saved_dcctc = 0;
|
2006-04-21 17:27:34 +00:00
|
|
|
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
if (rev->remerge_diff) {
|
2022-02-02 02:37:29 +00:00
|
|
|
rev->remerge_objdir = tmp_objdir_create("remerge-diff");
|
|
|
|
if (!rev->remerge_objdir)
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
die(_("unable to create temporary object directory"));
|
2022-02-02 02:37:29 +00:00
|
|
|
tmp_objdir_replace_primary_odb(rev->remerge_objdir, 1);
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
}
|
2006-04-21 17:27:34 +00:00
|
|
|
|
2007-11-03 18:11:10 +00:00
|
|
|
if (rev->early_output)
|
2019-03-20 08:13:42 +00:00
|
|
|
setup_early_output();
|
2007-11-03 18:11:10 +00:00
|
|
|
|
2008-02-18 07:31:56 +00:00
|
|
|
if (prepare_revision_walk(rev))
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("revision walk setup failed"));
|
2007-11-03 18:11:10 +00:00
|
|
|
|
|
|
|
if (rev->early_output)
|
|
|
|
finish_early_output(rev);
|
|
|
|
|
2008-08-11 06:46:24 +00:00
|
|
|
/*
|
2008-08-11 06:46:25 +00:00
|
|
|
* For --check and --exit-code, the exit code is based on CHECK_FAILED
|
|
|
|
* and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
|
|
|
|
* retain that state information if replacing rev->diffopt in this loop
|
2008-08-11 06:46:24 +00:00
|
|
|
*/
|
2006-04-21 17:27:34 +00:00
|
|
|
while ((commit = get_revision(rev)) != NULL) {
|
2015-08-20 22:51:45 +00:00
|
|
|
if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
|
2011-03-09 20:52:15 +00:00
|
|
|
/*
|
|
|
|
* We decremented max_count in get_revision,
|
|
|
|
* but we didn't actually show the commit.
|
|
|
|
*/
|
|
|
|
rev->max_count++;
|
2007-01-20 21:28:16 +00:00
|
|
|
if (!rev->reflog_info) {
|
2017-07-09 10:13:51 +00:00
|
|
|
/*
|
|
|
|
* We may show a given commit multiple times when
|
|
|
|
* walking the reflogs.
|
|
|
|
*/
|
2018-12-15 00:09:40 +00:00
|
|
|
free_commit_buffer(the_repository->parsed_objects,
|
|
|
|
commit);
|
2017-07-07 09:07:34 +00:00
|
|
|
free_commit_list(commit->parents);
|
|
|
|
commit->parents = NULL;
|
2007-01-20 21:28:16 +00:00
|
|
|
}
|
2011-01-06 21:50:06 +00:00
|
|
|
if (saved_nrl < rev->diffopt.needed_rename_limit)
|
|
|
|
saved_nrl = rev->diffopt.needed_rename_limit;
|
|
|
|
if (rev->diffopt.degraded_cc_to_c)
|
|
|
|
saved_dcctc = 1;
|
2006-04-21 17:27:34 +00:00
|
|
|
}
|
2011-01-06 21:50:06 +00:00
|
|
|
rev->diffopt.degraded_cc_to_c = saved_dcctc;
|
|
|
|
rev->diffopt.needed_rename_limit = saved_nrl;
|
|
|
|
|
2022-02-02 02:37:29 +00:00
|
|
|
if (rev->remerge_diff) {
|
|
|
|
tmp_objdir_destroy(rev->remerge_objdir);
|
|
|
|
rev->remerge_objdir = NULL;
|
|
|
|
}
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
|
2008-08-11 06:46:24 +00:00
|
|
|
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
|
2017-10-31 18:19:11 +00:00
|
|
|
rev->diffopt.flags.check_failed) {
|
2008-08-11 06:46:24 +00:00
|
|
|
return 02;
|
|
|
|
}
|
2008-08-11 06:46:25 +00:00
|
|
|
return diff_result_code(&rev->diffopt, 0);
|
2006-04-21 17:27:34 +00:00
|
|
|
}
|
|
|
|
|
2.36 show regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
e900d494 (diff: add an API for deferred freeing, 2021-02-11)
introduced a mechanism to delay freeing resources held in
diff_options struct that need to be kept as long as the struct will
be reused to compute diff. "git log -p" was taught to utilize the
mechanism but it was done with an incorrect assumption that the
underlying helper function, cmd_log_walk(), is called only once,
and it is OK to do the freeing at the end of it.
Alas, for "git show A B", the function is called once for each
commit given, so it is not OK to free the resources until we finish
calling it for all the commits given from the command line.
During 2.36 release cycle, we started clearing the <pathspec> as
part of this freeing, which made the bug a lot more visible.
Fix this breakage by tweaking how cmd_log_walk() frees the resources
at the end and using a variant of it that does not immediately free
the resources to show each commit object from the command line in
"git show".
Protect the fix with a few new tests.
Reported-by: Daniel Li <dan@danielyli.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-30 05:29:51 +00:00
|
|
|
static int cmd_log_walk(struct rev_info *rev)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
rev->diffopt.no_free = 1;
|
|
|
|
retval = cmd_log_walk_no_free(rev);
|
|
|
|
rev->diffopt.no_free = 0;
|
|
|
|
diff_free(&rev->diffopt);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2008-05-14 17:46:53 +00:00
|
|
|
static int git_log_config(const char *var, const char *value, void *cb)
|
2006-11-23 09:36:33 +00:00
|
|
|
{
|
2014-10-04 18:54:50 +00:00
|
|
|
const char *slot_name;
|
|
|
|
|
2008-03-02 09:05:53 +00:00
|
|
|
if (!strcmp(var, "format.pretty"))
|
|
|
|
return git_config_string(&fmt_pretty, var, value);
|
2008-07-05 05:24:41 +00:00
|
|
|
if (!strcmp(var, "format.subjectprefix"))
|
|
|
|
return git_config_string(&fmt_patch_subject_prefix, var, value);
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
if (!strcmp(var, "format.filenamemaxlength")) {
|
|
|
|
fmt_patch_name_max = git_config_int(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2020-04-08 04:31:38 +00:00
|
|
|
if (!strcmp(var, "format.encodeemailheaders")) {
|
|
|
|
default_encode_email_headers = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2011-05-18 17:56:04 +00:00
|
|
|
if (!strcmp(var, "log.abbrevcommit")) {
|
|
|
|
default_abbrev_commit = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-22 15:24:07 +00:00
|
|
|
if (!strcmp(var, "log.date"))
|
|
|
|
return git_config_string(&default_date_mode, var, value);
|
2010-02-16 23:39:52 +00:00
|
|
|
if (!strcmp(var, "log.decorate")) {
|
2017-08-07 18:20:50 +00:00
|
|
|
decoration_style = parse_decoration_style(value);
|
2010-02-17 18:20:49 +00:00
|
|
|
if (decoration_style < 0)
|
|
|
|
decoration_style = 0; /* maybe warn? */
|
2010-02-16 23:39:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2021-04-13 11:41:17 +00:00
|
|
|
if (!strcmp(var, "log.diffmerges"))
|
|
|
|
return diff_merges_config(value);
|
2006-11-23 09:36:33 +00:00
|
|
|
if (!strcmp(var, "log.showroot")) {
|
|
|
|
default_show_root = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-07-08 01:29:34 +00:00
|
|
|
if (!strcmp(var, "log.follow")) {
|
|
|
|
default_follow = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-10-04 18:54:50 +00:00
|
|
|
if (skip_prefix(var, "color.decorate.", &slot_name))
|
2014-10-20 19:23:48 +00:00
|
|
|
return parse_decorate_color_config(var, slot_name, value);
|
2013-01-05 21:26:46 +00:00
|
|
|
if (!strcmp(var, "log.mailmap")) {
|
|
|
|
use_mailmap_config = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2016-06-22 16:51:26 +00:00
|
|
|
if (!strcmp(var, "log.showsignature")) {
|
|
|
|
default_show_signature = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-05 21:26:46 +00:00
|
|
|
|
2013-03-27 15:13:39 +00:00
|
|
|
if (git_gpg_config(var, value, cb) < 0)
|
2012-10-09 23:49:57 +00:00
|
|
|
return -1;
|
2008-05-14 17:46:53 +00:00
|
|
|
return git_diff_ui_config(var, value, cb);
|
2006-11-23 09:36:33 +00:00
|
|
|
}
|
|
|
|
|
2006-07-29 05:44:25 +00:00
|
|
|
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
|
2006-04-21 17:27:34 +00:00
|
|
|
{
|
|
|
|
struct rev_info rev;
|
2010-03-09 06:58:09 +00:00
|
|
|
struct setup_revision_opt opt;
|
2006-04-21 17:27:34 +00:00
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
init_log_defaults();
|
2008-05-14 17:46:53 +00:00
|
|
|
git_config(git_log_config, NULL);
|
2008-02-18 07:26:03 +00:00
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
2022-02-16 00:00:36 +00:00
|
|
|
git_config(grep_config, &rev.grep_filter);
|
|
|
|
|
2006-04-21 17:27:34 +00:00
|
|
|
rev.diff = 1;
|
2006-06-11 17:57:35 +00:00
|
|
|
rev.simplify_history = 0;
|
2010-03-09 06:58:09 +00:00
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
opt.def = "HEAD";
|
2012-07-02 19:43:05 +00:00
|
|
|
opt.revarg_opt = REVARG_COMMITTISH;
|
2010-03-09 06:58:09 +00:00
|
|
|
cmd_log_init(argc, argv, prefix, &rev, &opt);
|
2006-06-25 12:39:35 +00:00
|
|
|
if (!rev.diffopt.output_format)
|
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_RAW;
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
2006-04-21 17:27:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-20 08:14:01 +00:00
|
|
|
static void show_tagger(const char *buf, struct rev_info *rev)
|
2007-12-18 18:01:33 +00:00
|
|
|
{
|
2009-01-02 18:08:43 +00:00
|
|
|
struct strbuf out = STRBUF_INIT;
|
2011-05-26 22:27:49 +00:00
|
|
|
struct pretty_print_context pp = {0};
|
2007-12-18 18:01:33 +00:00
|
|
|
|
2011-05-26 22:27:49 +00:00
|
|
|
pp.fmt = rev->commit_format;
|
|
|
|
pp.date_mode = rev->date_mode;
|
|
|
|
pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev->diffopt.file, "%s", out.buf);
|
2009-01-02 18:08:43 +00:00
|
|
|
strbuf_release(&out);
|
2007-12-18 18:01:33 +00:00
|
|
|
}
|
|
|
|
|
2016-09-05 20:07:55 +00:00
|
|
|
static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name)
|
2012-03-07 10:54:19 +00:00
|
|
|
{
|
2016-09-05 20:07:55 +00:00
|
|
|
struct object_id oidc;
|
2013-05-10 15:10:12 +00:00
|
|
|
struct object_context obj_context;
|
|
|
|
char *buf;
|
|
|
|
unsigned long size;
|
|
|
|
|
2016-06-22 15:01:59 +00:00
|
|
|
fflush(rev->diffopt.file);
|
2017-10-31 18:19:11 +00:00
|
|
|
if (!rev->diffopt.flags.textconv_set_via_cmdline ||
|
|
|
|
!rev->diffopt.flags.allow_textconv)
|
2016-09-05 20:07:59 +00:00
|
|
|
return stream_blob_to_fd(1, oid, NULL, 0);
|
2013-05-10 15:10:12 +00:00
|
|
|
|
2019-01-12 02:13:28 +00:00
|
|
|
if (get_oid_with_context(the_repository, obj_name,
|
|
|
|
GET_OID_RECORD_PATH,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 23:49:28 +00:00
|
|
|
&oidc, &obj_context))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("not a valid object name %s"), obj_name);
|
2017-05-19 12:54:43 +00:00
|
|
|
if (!obj_context.path ||
|
2018-09-21 15:57:22 +00:00
|
|
|
!textconv_object(the_repository, obj_context.path,
|
|
|
|
obj_context.mode, &oidc, 1, &buf, &size)) {
|
2017-05-19 12:54:43 +00:00
|
|
|
free(obj_context.path);
|
2016-09-05 20:07:59 +00:00
|
|
|
return stream_blob_to_fd(1, oid, NULL, 0);
|
2017-05-19 12:54:43 +00:00
|
|
|
}
|
2013-05-10 15:10:12 +00:00
|
|
|
|
|
|
|
if (!buf)
|
2014-09-14 22:07:10 +00:00
|
|
|
die(_("git show %s: bad file"), obj_name);
|
2013-05-10 15:10:12 +00:00
|
|
|
|
|
|
|
write_or_die(1, buf, size);
|
2017-05-19 12:54:43 +00:00
|
|
|
free(obj_context.path);
|
2013-05-10 15:10:12 +00:00
|
|
|
return 0;
|
2012-03-07 10:54:19 +00:00
|
|
|
}
|
|
|
|
|
2016-09-05 20:07:55 +00:00
|
|
|
static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
|
2006-12-14 10:31:05 +00:00
|
|
|
{
|
|
|
|
unsigned long size;
|
2007-02-26 19:55:59 +00:00
|
|
|
enum object_type type;
|
sha1_file: convert read_sha1_file to struct object_id
Convert read_sha1_file to take a pointer to struct object_id and rename
it read_object_file. Do the same for read_sha1_file_extended.
Convert one use in grep.c to use the new function without any other code
change, since the pointer being passed is a void pointer that is already
initialized with a pointer to struct object_id. Update the declaration
and definitions of the modified functions, and apply the following
semantic patch to convert the remaining callers:
@@
expression E1, E2, E3;
@@
- read_sha1_file(E1.hash, E2, E3)
+ read_object_file(&E1, E2, E3)
@@
expression E1, E2, E3;
@@
- read_sha1_file(E1->hash, E2, E3)
+ read_object_file(E1, E2, E3)
@@
expression E1, E2, E3, E4;
@@
- read_sha1_file_extended(E1.hash, E2, E3, E4)
+ read_object_file_extended(&E1, E2, E3, E4)
@@
expression E1, E2, E3, E4;
@@
- read_sha1_file_extended(E1->hash, E2, E3, E4)
+ read_object_file_extended(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-03-12 02:27:53 +00:00
|
|
|
char *buf = read_object_file(oid, &type, &size);
|
2006-12-14 10:31:05 +00:00
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
if (!buf)
|
2019-02-22 18:24:07 +00:00
|
|
|
return error(_("could not read object %s"), oid_to_hex(oid));
|
2006-12-14 10:31:05 +00:00
|
|
|
|
2012-03-07 10:54:19 +00:00
|
|
|
assert(type == OBJ_TAG);
|
|
|
|
while (offset < size && buf[offset] != '\n') {
|
|
|
|
int new_offset = offset + 1;
|
2019-03-20 08:14:01 +00:00
|
|
|
const char *ident;
|
2012-03-07 10:54:19 +00:00
|
|
|
while (new_offset < size && buf[new_offset++] != '\n')
|
|
|
|
; /* do nothing */
|
2019-03-20 08:14:01 +00:00
|
|
|
if (skip_prefix(buf + offset, "tagger ", &ident))
|
|
|
|
show_tagger(ident, rev);
|
2012-03-07 10:54:19 +00:00
|
|
|
offset = new_offset;
|
|
|
|
}
|
2006-12-14 10:31:05 +00:00
|
|
|
|
|
|
|
if (offset < size)
|
2016-06-22 15:01:59 +00:00
|
|
|
fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
|
2006-12-14 10:31:05 +00:00
|
|
|
free(buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-25 17:09:48 +00:00
|
|
|
static int show_tree_object(const struct object_id *oid UNUSED,
|
|
|
|
struct strbuf *base UNUSED,
|
2022-08-19 10:08:49 +00:00
|
|
|
const char *pathname, unsigned mode,
|
|
|
|
void *context)
|
2006-12-14 10:31:05 +00:00
|
|
|
{
|
2016-06-22 15:01:59 +00:00
|
|
|
FILE *file = context;
|
|
|
|
fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
|
2006-12-14 10:31:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-08-20 21:14:46 +00:00
|
|
|
static void show_setup_revisions_tweak(struct rev_info *rev,
|
|
|
|
struct setup_revision_opt *opt)
|
2010-03-09 07:27:25 +00:00
|
|
|
{
|
2020-12-21 15:19:35 +00:00
|
|
|
if (rev->first_parent_only)
|
2020-12-21 15:19:36 +00:00
|
|
|
diff_merges_default_to_first_parent(rev);
|
2020-12-21 15:19:35 +00:00
|
|
|
else
|
|
|
|
diff_merges_default_to_dense_combined(rev);
|
2010-03-09 07:27:25 +00:00
|
|
|
if (!rev->diffopt.output_format)
|
|
|
|
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
|
|
|
|
}
|
|
|
|
|
2006-07-29 05:44:25 +00:00
|
|
|
int cmd_show(int argc, const char **argv, const char *prefix)
|
2006-04-21 17:27:34 +00:00
|
|
|
{
|
|
|
|
struct rev_info rev;
|
2022-08-02 15:33:14 +00:00
|
|
|
unsigned int i;
|
2010-03-09 06:58:09 +00:00
|
|
|
struct setup_revision_opt opt;
|
2011-03-25 09:34:19 +00:00
|
|
|
struct pathspec match_all;
|
2022-08-02 15:33:14 +00:00
|
|
|
int ret = 0;
|
2006-04-21 17:27:34 +00:00
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
init_log_defaults();
|
2008-05-14 17:46:53 +00:00
|
|
|
git_config(git_log_config, NULL);
|
2008-02-18 07:26:03 +00:00
|
|
|
|
2022-04-26 20:43:17 +00:00
|
|
|
if (the_repository->gitdir) {
|
|
|
|
prepare_repo_settings(the_repository);
|
|
|
|
the_repository->settings.command_requires_full_index = 0;
|
|
|
|
}
|
|
|
|
|
2013-07-14 08:35:59 +00:00
|
|
|
memset(&match_all, 0, sizeof(match_all));
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
2022-02-16 00:00:36 +00:00
|
|
|
git_config(grep_config, &rev.grep_filter);
|
|
|
|
|
2006-04-21 17:27:34 +00:00
|
|
|
rev.diff = 1;
|
|
|
|
rev.always_show_header = 1;
|
2021-08-05 11:25:24 +00:00
|
|
|
rev.no_walk = 1;
|
2012-03-01 12:26:40 +00:00
|
|
|
rev.diffopt.stat_width = -1; /* Scale to real terminal size */
|
|
|
|
|
2010-03-09 06:58:09 +00:00
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
opt.def = "HEAD";
|
2015-08-20 21:14:46 +00:00
|
|
|
opt.tweak = show_setup_revisions_tweak;
|
2010-03-09 06:58:09 +00:00
|
|
|
cmd_log_init(argc, argv, prefix, &rev, &opt);
|
2006-12-14 10:31:05 +00:00
|
|
|
|
2012-06-19 21:15:57 +00:00
|
|
|
if (!rev.no_walk)
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
2012-06-19 21:15:57 +00:00
|
|
|
|
2.36 show regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
e900d494 (diff: add an API for deferred freeing, 2021-02-11)
introduced a mechanism to delay freeing resources held in
diff_options struct that need to be kept as long as the struct will
be reused to compute diff. "git log -p" was taught to utilize the
mechanism but it was done with an incorrect assumption that the
underlying helper function, cmd_log_walk(), is called only once,
and it is OK to do the freeing at the end of it.
Alas, for "git show A B", the function is called once for each
commit given, so it is not OK to free the resources until we finish
calling it for all the commits given from the command line.
During 2.36 release cycle, we started clearing the <pathspec> as
part of this freeing, which made the bug a lot more visible.
Fix this breakage by tweaking how cmd_log_walk() frees the resources
at the end and using a variant of it that does not immediately free
the resources to show each commit object from the command line in
"git show".
Protect the fix with a few new tests.
Reported-by: Daniel Li <dan@danielyli.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-30 05:29:51 +00:00
|
|
|
rev.diffopt.no_free = 1;
|
2022-08-02 15:33:14 +00:00
|
|
|
for (i = 0; i < rev.pending.nr && !ret; i++) {
|
|
|
|
struct object *o = rev.pending.objects[i].item;
|
|
|
|
const char *name = rev.pending.objects[i].name;
|
2006-12-14 10:31:05 +00:00
|
|
|
switch (o->type) {
|
|
|
|
case OBJ_BLOB:
|
2016-09-05 20:07:55 +00:00
|
|
|
ret = show_blob_object(&o->oid, &rev, name);
|
2006-12-14 10:31:05 +00:00
|
|
|
break;
|
|
|
|
case OBJ_TAG: {
|
|
|
|
struct tag *t = (struct tag *)o;
|
2019-09-05 19:59:42 +00:00
|
|
|
struct object_id *oid = get_tagged_oid(t);
|
2006-12-14 10:31:05 +00:00
|
|
|
|
show: add space between multiple items
When showing an annotated tag, "git show" will always
display the pointed-to object. However, it didn't separate
the two with whitespace, making it more difficult to notice
where the new object started. For example:
$ git tag -m 'my message' foo
$ git show foo
tag foo
Tagger: Jeff King <peff@peff.net>
Date: Fri Jul 17 18:46:25 2009 -0400
my message
commit 41cabf8fed2694ba33e01d64f9094f2fc5e5805a
Author: Jeff King <peff@peff.net>
Date: Thu Jul 16 17:31:34 2009 -0400
...
This patch respects and sets the rev.shown_one member to
prepend a blank line before showing a second item. We use
this member of rev_info instead of a local flag, because the
log_tree_commit we call into for showing commits already
respects and sets that flag. Meaning that everything will be
spaced properly if you intermix commits and tags, like:
$ git show v1.6.3 v1.6.2 HEAD
In that case, a single blank line will separate the first
tag, the commit it points to, the second tag, the commit
that one points to, and the final commit.
While we're at it, let's also support trees, so that even
something as crazy as
$ git show HEAD^{tree} HEAD~1^{tree} HEAD
will also be spaced in an easy-to-read way. However, we
intentionally do _not_ insert blank lines for blobs, so
that specifying multiple blobs gives a strict concatenation.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-18 10:14:37 +00:00
|
|
|
if (rev.shown_one)
|
|
|
|
putchar('\n');
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev.diffopt.file, "%stag %s%s\n",
|
2007-11-10 19:05:14 +00:00
|
|
|
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
2006-12-14 10:31:05 +00:00
|
|
|
t->tag,
|
2007-11-10 19:05:14 +00:00
|
|
|
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
2016-09-05 20:07:55 +00:00
|
|
|
ret = show_tag_object(&o->oid, &rev);
|
show: add space between multiple items
When showing an annotated tag, "git show" will always
display the pointed-to object. However, it didn't separate
the two with whitespace, making it more difficult to notice
where the new object started. For example:
$ git tag -m 'my message' foo
$ git show foo
tag foo
Tagger: Jeff King <peff@peff.net>
Date: Fri Jul 17 18:46:25 2009 -0400
my message
commit 41cabf8fed2694ba33e01d64f9094f2fc5e5805a
Author: Jeff King <peff@peff.net>
Date: Thu Jul 16 17:31:34 2009 -0400
...
This patch respects and sets the rev.shown_one member to
prepend a blank line before showing a second item. We use
this member of rev_info instead of a local flag, because the
log_tree_commit we call into for showing commits already
respects and sets that flag. Meaning that everything will be
spaced properly if you intermix commits and tags, like:
$ git show v1.6.3 v1.6.2 HEAD
In that case, a single blank line will separate the first
tag, the commit it points to, the second tag, the commit
that one points to, and the final commit.
While we're at it, let's also support trees, so that even
something as crazy as
$ git show HEAD^{tree} HEAD~1^{tree} HEAD
will also be spaced in an easy-to-read way. However, we
intentionally do _not_ insert blank lines for blobs, so
that specifying multiple blobs gives a strict concatenation.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-18 10:14:37 +00:00
|
|
|
rev.shown_one = 1;
|
2008-12-15 08:36:56 +00:00
|
|
|
if (ret)
|
|
|
|
break;
|
2019-09-05 19:59:42 +00:00
|
|
|
o = parse_object(the_repository, oid);
|
2008-12-15 08:36:56 +00:00
|
|
|
if (!o)
|
2019-02-22 18:24:07 +00:00
|
|
|
ret = error(_("could not read object %s"),
|
2019-09-05 19:59:42 +00:00
|
|
|
oid_to_hex(oid));
|
2022-08-02 15:33:14 +00:00
|
|
|
rev.pending.objects[i].item = o;
|
2006-12-14 10:31:05 +00:00
|
|
|
i--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJ_TREE:
|
show: add space between multiple items
When showing an annotated tag, "git show" will always
display the pointed-to object. However, it didn't separate
the two with whitespace, making it more difficult to notice
where the new object started. For example:
$ git tag -m 'my message' foo
$ git show foo
tag foo
Tagger: Jeff King <peff@peff.net>
Date: Fri Jul 17 18:46:25 2009 -0400
my message
commit 41cabf8fed2694ba33e01d64f9094f2fc5e5805a
Author: Jeff King <peff@peff.net>
Date: Thu Jul 16 17:31:34 2009 -0400
...
This patch respects and sets the rev.shown_one member to
prepend a blank line before showing a second item. We use
this member of rev_info instead of a local flag, because the
log_tree_commit we call into for showing commits already
respects and sets that flag. Meaning that everything will be
spaced properly if you intermix commits and tags, like:
$ git show v1.6.3 v1.6.2 HEAD
In that case, a single blank line will separate the first
tag, the commit it points to, the second tag, the commit
that one points to, and the final commit.
While we're at it, let's also support trees, so that even
something as crazy as
$ git show HEAD^{tree} HEAD~1^{tree} HEAD
will also be spaced in an easy-to-read way. However, we
intentionally do _not_ insert blank lines for blobs, so
that specifying multiple blobs gives a strict concatenation.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-18 10:14:37 +00:00
|
|
|
if (rev.shown_one)
|
|
|
|
putchar('\n');
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev.diffopt.file, "%stree %s%s\n\n",
|
2007-11-10 19:05:14 +00:00
|
|
|
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
2006-12-14 10:31:05 +00:00
|
|
|
name,
|
2007-11-10 19:05:14 +00:00
|
|
|
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
2021-03-20 22:37:51 +00:00
|
|
|
read_tree(the_repository, (struct tree *)o,
|
|
|
|
&match_all, show_tree_object,
|
|
|
|
rev.diffopt.file);
|
show: add space between multiple items
When showing an annotated tag, "git show" will always
display the pointed-to object. However, it didn't separate
the two with whitespace, making it more difficult to notice
where the new object started. For example:
$ git tag -m 'my message' foo
$ git show foo
tag foo
Tagger: Jeff King <peff@peff.net>
Date: Fri Jul 17 18:46:25 2009 -0400
my message
commit 41cabf8fed2694ba33e01d64f9094f2fc5e5805a
Author: Jeff King <peff@peff.net>
Date: Thu Jul 16 17:31:34 2009 -0400
...
This patch respects and sets the rev.shown_one member to
prepend a blank line before showing a second item. We use
this member of rev_info instead of a local flag, because the
log_tree_commit we call into for showing commits already
respects and sets that flag. Meaning that everything will be
spaced properly if you intermix commits and tags, like:
$ git show v1.6.3 v1.6.2 HEAD
In that case, a single blank line will separate the first
tag, the commit it points to, the second tag, the commit
that one points to, and the final commit.
While we're at it, let's also support trees, so that even
something as crazy as
$ git show HEAD^{tree} HEAD~1^{tree} HEAD
will also be spaced in an easy-to-read way. However, we
intentionally do _not_ insert blank lines for blobs, so
that specifying multiple blobs gives a strict concatenation.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-18 10:14:37 +00:00
|
|
|
rev.shown_one = 1;
|
2006-12-14 10:31:05 +00:00
|
|
|
break;
|
|
|
|
case OBJ_COMMIT:
|
2022-08-02 15:33:13 +00:00
|
|
|
{
|
|
|
|
struct object_array old;
|
2022-08-02 15:33:14 +00:00
|
|
|
struct object_array blank = OBJECT_ARRAY_INIT;
|
2022-08-02 15:33:13 +00:00
|
|
|
|
|
|
|
memcpy(&old, &rev.pending, sizeof(old));
|
2022-08-02 15:33:14 +00:00
|
|
|
memcpy(&rev.pending, &blank, sizeof(rev.pending));
|
|
|
|
|
2006-12-14 10:31:05 +00:00
|
|
|
add_object_array(o, name, &rev.pending);
|
2.36 show regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
e900d494 (diff: add an API for deferred freeing, 2021-02-11)
introduced a mechanism to delay freeing resources held in
diff_options struct that need to be kept as long as the struct will
be reused to compute diff. "git log -p" was taught to utilize the
mechanism but it was done with an incorrect assumption that the
underlying helper function, cmd_log_walk(), is called only once,
and it is OK to do the freeing at the end of it.
Alas, for "git show A B", the function is called once for each
commit given, so it is not OK to free the resources until we finish
calling it for all the commits given from the command line.
During 2.36 release cycle, we started clearing the <pathspec> as
part of this freeing, which made the bug a lot more visible.
Fix this breakage by tweaking how cmd_log_walk() frees the resources
at the end and using a variant of it that does not immediately free
the resources to show each commit object from the command line in
"git show".
Protect the fix with a few new tests.
Reported-by: Daniel Li <dan@danielyli.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-30 05:29:51 +00:00
|
|
|
ret = cmd_log_walk_no_free(&rev);
|
2022-08-02 15:33:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* No need for
|
|
|
|
* object_array_clear(&pending). It was
|
|
|
|
* cleared already in prepare_revision_walk()
|
|
|
|
*/
|
2022-08-02 15:33:13 +00:00
|
|
|
memcpy(&rev.pending, &old, sizeof(rev.pending));
|
2006-12-14 10:31:05 +00:00
|
|
|
break;
|
2022-08-02 15:33:13 +00:00
|
|
|
}
|
2006-12-14 10:31:05 +00:00
|
|
|
default:
|
2019-02-22 18:24:07 +00:00
|
|
|
ret = error(_("unknown type: %d"), o->type);
|
2006-12-14 10:31:05 +00:00
|
|
|
}
|
|
|
|
}
|
2.36 show regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
e900d494 (diff: add an API for deferred freeing, 2021-02-11)
introduced a mechanism to delay freeing resources held in
diff_options struct that need to be kept as long as the struct will
be reused to compute diff. "git log -p" was taught to utilize the
mechanism but it was done with an incorrect assumption that the
underlying helper function, cmd_log_walk(), is called only once,
and it is OK to do the freeing at the end of it.
Alas, for "git show A B", the function is called once for each
commit given, so it is not OK to free the resources until we finish
calling it for all the commits given from the command line.
During 2.36 release cycle, we started clearing the <pathspec> as
part of this freeing, which made the bug a lot more visible.
Fix this breakage by tweaking how cmd_log_walk() frees the resources
at the end and using a variant of it that does not immediately free
the resources to show each commit object from the command line in
"git show".
Protect the fix with a few new tests.
Reported-by: Daniel Li <dan@danielyli.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-30 05:29:51 +00:00
|
|
|
|
|
|
|
rev.diffopt.no_free = 0;
|
|
|
|
diff_free(&rev.diffopt);
|
|
|
|
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(ret, &rev);
|
2006-04-21 17:27:34 +00:00
|
|
|
}
|
|
|
|
|
2007-02-08 17:51:56 +00:00
|
|
|
/*
|
|
|
|
* This is equivalent to "git log -g --abbrev-commit --pretty=oneline"
|
|
|
|
*/
|
|
|
|
int cmd_log_reflog(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
|
|
|
struct rev_info rev;
|
2010-03-09 06:58:09 +00:00
|
|
|
struct setup_revision_opt opt;
|
2007-02-08 17:51:56 +00:00
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
init_log_defaults();
|
2008-05-14 17:46:53 +00:00
|
|
|
git_config(git_log_config, NULL);
|
2008-02-18 07:26:03 +00:00
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
2007-02-08 17:51:56 +00:00
|
|
|
init_reflog_walk(&rev.reflog_info);
|
2022-02-16 00:00:36 +00:00
|
|
|
git_config(grep_config, &rev.grep_filter);
|
|
|
|
|
2007-02-08 17:51:56 +00:00
|
|
|
rev.verbose_header = 1;
|
2010-03-09 06:58:09 +00:00
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
opt.def = "HEAD";
|
2011-04-01 09:20:33 +00:00
|
|
|
cmd_log_init_defaults(&rev);
|
2011-05-18 17:56:04 +00:00
|
|
|
rev.abbrev_commit = 1;
|
2007-02-08 17:51:56 +00:00
|
|
|
rev.commit_format = CMIT_FMT_ONELINE;
|
2008-04-08 00:11:34 +00:00
|
|
|
rev.use_terminator = 1;
|
2007-02-08 17:51:56 +00:00
|
|
|
rev.always_show_header = 1;
|
2011-04-01 09:20:33 +00:00
|
|
|
cmd_log_init_finish(argc, argv, prefix, &rev, &opt);
|
2007-02-08 17:51:56 +00:00
|
|
|
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
2007-02-08 17:51:56 +00:00
|
|
|
}
|
|
|
|
|
2015-08-20 21:14:46 +00:00
|
|
|
static void log_setup_revisions_tweak(struct rev_info *rev,
|
|
|
|
struct setup_revision_opt *opt)
|
2015-07-08 01:29:34 +00:00
|
|
|
{
|
2017-10-31 18:19:11 +00:00
|
|
|
if (rev->diffopt.flags.default_follow_renames &&
|
2015-07-08 01:29:34 +00:00
|
|
|
rev->prune_data.nr == 1)
|
2017-10-31 18:19:11 +00:00
|
|
|
rev->diffopt.flags.follow_renames = 1;
|
2015-08-20 21:36:49 +00:00
|
|
|
|
2020-12-21 15:19:35 +00:00
|
|
|
if (rev->first_parent_only)
|
2020-12-21 15:19:36 +00:00
|
|
|
diff_merges_default_to_first_parent(rev);
|
2015-07-08 01:29:34 +00:00
|
|
|
}
|
|
|
|
|
2006-07-29 05:44:25 +00:00
|
|
|
int cmd_log(int argc, const char **argv, const char *prefix)
|
2006-04-21 17:27:34 +00:00
|
|
|
{
|
|
|
|
struct rev_info rev;
|
2010-03-09 06:58:09 +00:00
|
|
|
struct setup_revision_opt opt;
|
2006-04-21 17:27:34 +00:00
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
init_log_defaults();
|
2008-05-14 17:46:53 +00:00
|
|
|
git_config(git_log_config, NULL);
|
2008-02-18 07:26:03 +00:00
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
2022-02-16 00:00:36 +00:00
|
|
|
git_config(grep_config, &rev.grep_filter);
|
|
|
|
|
2006-04-21 17:27:34 +00:00
|
|
|
rev.always_show_header = 1;
|
2010-03-09 06:58:09 +00:00
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
opt.def = "HEAD";
|
2012-07-02 19:43:05 +00:00
|
|
|
opt.revarg_opt = REVARG_COMMITTISH;
|
2015-08-20 21:14:46 +00:00
|
|
|
opt.tweak = log_setup_revisions_tweak;
|
2010-03-09 06:58:09 +00:00
|
|
|
cmd_log_init(argc, argv, prefix, &rev, &opt);
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
2006-04-21 17:27:34 +00:00
|
|
|
}
|
2006-04-21 20:19:58 +00:00
|
|
|
|
2007-02-23 22:27:58 +00:00
|
|
|
/* format-patch */
|
2006-05-04 23:16:40 +00:00
|
|
|
|
2007-01-17 23:03:39 +00:00
|
|
|
static const char *fmt_patch_suffix = ".patch";
|
2007-11-04 03:38:24 +00:00
|
|
|
static int numbered = 0;
|
2008-10-02 20:55:39 +00:00
|
|
|
static int auto_number = 1;
|
2006-06-02 13:21:17 +00:00
|
|
|
|
2009-02-12 15:51:55 +00:00
|
|
|
static char *default_attach = NULL;
|
|
|
|
|
2016-06-13 10:04:20 +00:00
|
|
|
static struct string_list extra_hdr = STRING_LIST_INIT_NODUP;
|
|
|
|
static struct string_list extra_to = STRING_LIST_INIT_NODUP;
|
|
|
|
static struct string_list extra_cc = STRING_LIST_INIT_NODUP;
|
2008-02-19 07:40:33 +00:00
|
|
|
|
|
|
|
static void add_header(const char *value)
|
|
|
|
{
|
2010-03-07 22:46:46 +00:00
|
|
|
struct string_list_item *item;
|
2008-02-19 07:40:33 +00:00
|
|
|
int len = strlen(value);
|
2008-08-19 18:42:04 +00:00
|
|
|
while (len && value[len - 1] == '\n')
|
2008-02-19 07:40:33 +00:00
|
|
|
len--;
|
2010-03-07 22:46:46 +00:00
|
|
|
|
2008-02-19 07:40:33 +00:00
|
|
|
if (!strncasecmp(value, "to: ", 4)) {
|
2010-06-25 23:41:38 +00:00
|
|
|
item = string_list_append(&extra_to, value + 4);
|
2010-03-07 22:46:46 +00:00
|
|
|
len -= 4;
|
|
|
|
} else if (!strncasecmp(value, "cc: ", 4)) {
|
2010-06-25 23:41:38 +00:00
|
|
|
item = string_list_append(&extra_cc, value + 4);
|
2010-03-07 22:46:46 +00:00
|
|
|
len -= 4;
|
|
|
|
} else {
|
2010-06-25 23:41:38 +00:00
|
|
|
item = string_list_append(&extra_hdr, value);
|
2008-02-19 07:40:33 +00:00
|
|
|
}
|
2010-03-07 22:46:46 +00:00
|
|
|
|
|
|
|
item->string[len] = '\0';
|
2008-02-19 07:40:33 +00:00
|
|
|
}
|
|
|
|
|
2019-10-15 09:06:37 +00:00
|
|
|
enum cover_setting {
|
|
|
|
COVER_UNSET,
|
|
|
|
COVER_OFF,
|
|
|
|
COVER_ON,
|
|
|
|
COVER_AUTO
|
|
|
|
};
|
|
|
|
|
|
|
|
enum thread_level {
|
|
|
|
THREAD_UNSET,
|
|
|
|
THREAD_SHALLOW,
|
|
|
|
THREAD_DEEP
|
|
|
|
};
|
|
|
|
|
2019-10-15 09:06:40 +00:00
|
|
|
enum cover_from_description {
|
|
|
|
COVER_FROM_NONE,
|
|
|
|
COVER_FROM_MESSAGE,
|
|
|
|
COVER_FROM_SUBJECT,
|
|
|
|
COVER_FROM_AUTO
|
|
|
|
};
|
|
|
|
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
enum auto_base_setting {
|
|
|
|
AUTO_BASE_NEVER,
|
|
|
|
AUTO_BASE_ALWAYS,
|
|
|
|
AUTO_BASE_WHEN_ABLE
|
|
|
|
};
|
|
|
|
|
2019-10-15 09:06:37 +00:00
|
|
|
static enum thread_level thread;
|
2010-06-16 05:59:25 +00:00
|
|
|
static int do_signoff;
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
static enum auto_base_setting auto_base;
|
2016-07-30 09:41:56 +00:00
|
|
|
static char *from;
|
2010-06-16 05:59:25 +00:00
|
|
|
static const char *signature = git_version_string;
|
2014-05-24 04:08:14 +00:00
|
|
|
static const char *signature_file;
|
2019-10-15 09:06:37 +00:00
|
|
|
static enum cover_setting config_cover_letter;
|
2016-01-13 13:20:11 +00:00
|
|
|
static const char *config_output_directory;
|
2019-10-15 09:06:40 +00:00
|
|
|
static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
|
2019-12-09 13:10:48 +00:00
|
|
|
static int show_notes;
|
|
|
|
static struct display_notes_opt notes_opt;
|
2013-04-07 17:46:23 +00:00
|
|
|
|
2019-10-15 09:06:40 +00:00
|
|
|
static enum cover_from_description parse_cover_from_description(const char *arg)
|
|
|
|
{
|
|
|
|
if (!arg || !strcmp(arg, "default"))
|
|
|
|
return COVER_FROM_MESSAGE;
|
|
|
|
else if (!strcmp(arg, "none"))
|
|
|
|
return COVER_FROM_NONE;
|
|
|
|
else if (!strcmp(arg, "message"))
|
|
|
|
return COVER_FROM_MESSAGE;
|
|
|
|
else if (!strcmp(arg, "subject"))
|
|
|
|
return COVER_FROM_SUBJECT;
|
|
|
|
else if (!strcmp(arg, "auto"))
|
|
|
|
return COVER_FROM_AUTO;
|
|
|
|
else
|
|
|
|
die(_("%s: invalid cover from description mode"), arg);
|
|
|
|
}
|
2009-02-19 21:26:33 +00:00
|
|
|
|
2008-05-14 17:46:53 +00:00
|
|
|
static int git_format_config(const char *var, const char *value, void *cb)
|
2006-06-02 13:21:17 +00:00
|
|
|
{
|
|
|
|
if (!strcmp(var, "format.headers")) {
|
2007-01-17 19:13:02 +00:00
|
|
|
if (!value)
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("format.headers without value"));
|
2008-02-19 07:40:33 +00:00
|
|
|
add_header(value);
|
2006-06-02 13:21:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-07-05 05:24:41 +00:00
|
|
|
if (!strcmp(var, "format.suffix"))
|
|
|
|
return git_config_string(&fmt_patch_suffix, var, value);
|
2010-02-16 23:39:34 +00:00
|
|
|
if (!strcmp(var, "format.to")) {
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(&extra_to, value);
|
2010-02-16 23:39:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-04-26 21:19:06 +00:00
|
|
|
if (!strcmp(var, "format.cc")) {
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(&extra_cc, value);
|
2008-04-26 21:19:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2011-09-12 17:46:41 +00:00
|
|
|
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff") ||
|
2015-01-07 20:32:12 +00:00
|
|
|
!strcmp(var, "color.ui") || !strcmp(var, "diff.submodule")) {
|
2006-07-09 06:28:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-11-04 03:38:24 +00:00
|
|
|
if (!strcmp(var, "format.numbered")) {
|
2008-02-11 21:09:16 +00:00
|
|
|
if (value && !strcasecmp(value, "auto")) {
|
2007-11-04 03:38:24 +00:00
|
|
|
auto_number = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
numbered = git_config_bool(var, value);
|
2008-10-02 20:55:39 +00:00
|
|
|
auto_number = auto_number && numbered;
|
2007-11-04 03:38:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-02-12 15:51:55 +00:00
|
|
|
if (!strcmp(var, "format.attach")) {
|
|
|
|
if (value && *value)
|
|
|
|
default_attach = xstrdup(value);
|
|
|
|
else
|
|
|
|
default_attach = xstrdup(git_version_string);
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-19 21:26:33 +00:00
|
|
|
if (!strcmp(var, "format.thread")) {
|
|
|
|
if (value && !strcasecmp(value, "deep")) {
|
|
|
|
thread = THREAD_DEEP;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (value && !strcasecmp(value, "shallow")) {
|
|
|
|
thread = THREAD_SHALLOW;
|
|
|
|
return 0;
|
|
|
|
}
|
2019-10-15 09:06:35 +00:00
|
|
|
thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
|
2009-02-19 21:26:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-04-01 17:51:54 +00:00
|
|
|
if (!strcmp(var, "format.signoff")) {
|
|
|
|
do_signoff = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-06-16 05:59:25 +00:00
|
|
|
if (!strcmp(var, "format.signature"))
|
|
|
|
return git_config_string(&signature, var, value);
|
2014-05-24 04:08:14 +00:00
|
|
|
if (!strcmp(var, "format.signaturefile"))
|
|
|
|
return git_config_pathname(&signature_file, var, value);
|
2013-04-07 17:46:23 +00:00
|
|
|
if (!strcmp(var, "format.coverletter")) {
|
|
|
|
if (value && !strcasecmp(value, "auto")) {
|
|
|
|
config_cover_letter = COVER_AUTO;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
|
|
|
|
return 0;
|
|
|
|
}
|
2016-01-13 13:20:11 +00:00
|
|
|
if (!strcmp(var, "format.outputdirectory"))
|
|
|
|
return git_config_string(&config_output_directory, var, value);
|
2016-04-26 07:51:24 +00:00
|
|
|
if (!strcmp(var, "format.useautobase")) {
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (value && !strcasecmp(value, "whenAble")) {
|
|
|
|
auto_base = AUTO_BASE_WHEN_ABLE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
auto_base = git_config_bool(var, value) ? AUTO_BASE_ALWAYS : AUTO_BASE_NEVER;
|
2016-04-26 07:51:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2016-07-30 09:41:56 +00:00
|
|
|
if (!strcmp(var, "format.from")) {
|
2017-08-07 18:20:49 +00:00
|
|
|
int b = git_parse_maybe_bool(value);
|
2016-07-30 09:41:56 +00:00
|
|
|
free(from);
|
|
|
|
if (b < 0)
|
|
|
|
from = xstrdup(value);
|
|
|
|
else if (b)
|
|
|
|
from = xstrdup(git_committer_info(IDENT_NO_DATE));
|
|
|
|
else
|
|
|
|
from = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
2022-08-29 21:38:37 +00:00
|
|
|
if (!strcmp(var, "format.forceinbodyfrom")) {
|
|
|
|
force_in_body_from = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2019-05-16 23:14:14 +00:00
|
|
|
if (!strcmp(var, "format.notes")) {
|
|
|
|
int b = git_parse_maybe_bool(value);
|
notes: break set_display_notes() into smaller functions
In 8164c961e1 (format-patch: use --notes behavior for format.notes,
2019-12-09), we introduced set_display_notes() which was a monolithic
function with three mutually exclusive branches. Break the function up
into three small and simple functions that each are only responsible for
one task.
This family of functions accepts an `int *show_notes` instead of
returning a value suitable for assignment to `show_notes`. This is for
two reasons. First of all, this guarantees that the external
`show_notes` variable changes in lockstep with the
`struct display_notes_opt`. Second, this prompts future developers to be
careful about doing something meaningful with this value. In fact, a
NULL check is intentionally omitted because causing a segfault here
would tell the future developer that they are meant to use the value for
something meaningful.
One alternative was making the family of functions accept a
`struct rev_info *` instead of the `struct display_notes_opt *`, since
the former contains the `show_notes` field as well. This does not work
because we have to call git_config() before repo_init_revisions().
However, if we had a `struct rev_info`, we'd need to initialize it before
it gets assigned values from git_config(). As a result, we break the
circular dependency by having standalone `int show_notes` and
`struct display_notes_opt notes_opt` variables which temporarily hold
values from git_config() until the values are copied over to `rev`.
To implement this change, we need to get a pointer to
`rev_info::show_notes`. Unfortunately, this is not possible with
bitfields and only direct-assignment is possible. Change
`rev_info::show_notes` to a non-bitfield int so that we can get its
address.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-12-12 00:49:50 +00:00
|
|
|
if (b < 0)
|
|
|
|
enable_ref_display_notes(¬es_opt, &show_notes, value);
|
|
|
|
else if (b)
|
|
|
|
enable_default_display_notes(¬es_opt, &show_notes);
|
|
|
|
else
|
|
|
|
disable_display_notes(¬es_opt, &show_notes);
|
2019-05-16 23:14:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-10-15 09:06:40 +00:00
|
|
|
if (!strcmp(var, "format.coverfromdescription")) {
|
|
|
|
cover_from_description_mode = parse_cover_from_description(value);
|
|
|
|
return 0;
|
|
|
|
}
|
2022-12-22 20:16:19 +00:00
|
|
|
if (!strcmp(var, "format.mboxrd")) {
|
|
|
|
stdout_mboxrd = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2007-07-02 00:48:59 +00:00
|
|
|
|
2008-05-14 17:46:53 +00:00
|
|
|
return git_log_config(var, value, cb);
|
2006-06-02 13:21:17 +00:00
|
|
|
}
|
|
|
|
|
2006-06-06 15:46:23 +00:00
|
|
|
static const char *output_directory = NULL;
|
2009-01-12 23:18:02 +00:00
|
|
|
static int outdir_offset;
|
2006-05-05 01:33:05 +00:00
|
|
|
|
2016-06-22 15:01:59 +00:00
|
|
|
static int open_next_file(struct commit *commit, const char *subject,
|
2012-05-21 23:10:32 +00:00
|
|
|
struct rev_info *rev, int quiet)
|
2006-05-04 23:16:40 +00:00
|
|
|
{
|
2009-03-23 02:14:03 +00:00
|
|
|
struct strbuf filename = STRBUF_INIT;
|
2006-05-04 23:16:40 +00:00
|
|
|
|
2006-05-05 01:33:32 +00:00
|
|
|
if (output_directory) {
|
2009-03-23 02:14:03 +00:00
|
|
|
strbuf_addstr(&filename, output_directory);
|
use strbuf_complete to conditionally append slash
When working with paths in strbufs, we frequently want to
ensure that a directory contains a trailing slash before
appending to it. We can shorten this code (and make the
intent more obvious) by calling strbuf_complete.
Most of these cases are trivially identical conversions, but
there are two things to note:
- in a few cases we did not check that the strbuf is
non-empty (which would lead to an out-of-bounds memory
access). These were generally not triggerable in
practice, either from earlier assertions, or typically
because we would have just fed the strbuf to opendir(),
which would choke on an empty path.
- in a few cases we indexed the buffer with "original_len"
or similar, rather than the current sb->len, and it is
not immediately obvious from the diff that they are the
same. In all of these cases, I manually verified that
the strbuf does not change between the assignment and
the strbuf_complete call.
This does not convert cases which look like:
if (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))
strbuf_addch(sb, '/');
as those are obviously semantically different. Some of these
cases arguably should be doing that, but that is out of
scope for this change, which aims purely for cleanup with no
behavior change (and at least it will make such sites easier
to find and examine in the future, as we can grep for
strbuf_complete).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-09-24 21:08:35 +00:00
|
|
|
strbuf_complete(&filename, '/');
|
2006-05-05 01:33:32 +00:00
|
|
|
}
|
2006-05-04 23:16:40 +00:00
|
|
|
|
2012-12-22 05:39:37 +00:00
|
|
|
if (rev->numbered_files)
|
|
|
|
strbuf_addf(&filename, "%d", rev->nr);
|
2012-12-22 06:06:01 +00:00
|
|
|
else if (commit)
|
|
|
|
fmt_output_commit(&filename, commit, rev);
|
2012-12-22 05:39:37 +00:00
|
|
|
else
|
2012-12-22 06:06:01 +00:00
|
|
|
fmt_output_subject(&filename, subject, rev);
|
2007-06-05 20:06:53 +00:00
|
|
|
|
2011-04-12 15:35:38 +00:00
|
|
|
if (!quiet)
|
2016-06-22 15:02:04 +00:00
|
|
|
printf("%s\n", filename.buf + outdir_offset);
|
2009-03-18 17:00:45 +00:00
|
|
|
|
2022-05-02 16:50:37 +00:00
|
|
|
if (!(rev->diffopt.file = fopen(filename.buf, "w"))) {
|
2019-02-22 18:24:07 +00:00
|
|
|
error_errno(_("cannot open patch file %s"), filename.buf);
|
2017-05-03 10:16:56 +00:00
|
|
|
strbuf_release(&filename);
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 22:27:58 +00:00
|
|
|
|
2009-03-23 02:14:03 +00:00
|
|
|
strbuf_release(&filename);
|
2007-06-05 20:06:53 +00:00
|
|
|
return 0;
|
2006-05-04 23:16:40 +00:00
|
|
|
}
|
|
|
|
|
2012-07-27 17:21:38 +00:00
|
|
|
static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
|
2006-06-25 01:52:01 +00:00
|
|
|
{
|
|
|
|
struct rev_info check_rev;
|
2015-06-01 17:44:21 +00:00
|
|
|
struct commit *commit, *c1, *c2;
|
2006-06-25 01:52:01 +00:00
|
|
|
struct object *o1, *o2;
|
|
|
|
unsigned flags1, flags2;
|
|
|
|
|
|
|
|
if (rev->pending.nr != 2)
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("need exactly one range"));
|
2006-06-25 01:52:01 +00:00
|
|
|
|
|
|
|
o1 = rev->pending.objects[0].item;
|
|
|
|
o2 = rev->pending.objects[1].item;
|
2015-06-01 17:44:21 +00:00
|
|
|
flags1 = o1->flags;
|
2006-06-25 01:52:01 +00:00
|
|
|
flags2 = o2->flags;
|
2018-06-29 01:21:58 +00:00
|
|
|
c1 = lookup_commit_reference(the_repository, &o1->oid);
|
|
|
|
c2 = lookup_commit_reference(the_repository, &o2->oid);
|
2006-06-25 01:52:01 +00:00
|
|
|
|
|
|
|
if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("not a range"));
|
2006-06-25 01:52:01 +00:00
|
|
|
|
2018-09-21 15:57:30 +00:00
|
|
|
init_patch_ids(the_repository, ids);
|
2006-06-25 01:52:01 +00:00
|
|
|
|
|
|
|
/* given a range a..b get all patch ids for b..a */
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &check_rev, rev->prefix);
|
2012-07-29 23:25:36 +00:00
|
|
|
check_rev.max_parents = 1;
|
2006-06-25 01:52:01 +00:00
|
|
|
o1->flags ^= UNINTERESTING;
|
|
|
|
o2->flags ^= UNINTERESTING;
|
|
|
|
add_pending_object(&check_rev, o1, "o1");
|
|
|
|
add_pending_object(&check_rev, o2, "o2");
|
2008-02-18 07:31:56 +00:00
|
|
|
if (prepare_revision_walk(&check_rev))
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("revision walk setup failed"));
|
2006-06-25 01:52:01 +00:00
|
|
|
|
|
|
|
while ((commit = get_revision(&check_rev)) != NULL) {
|
2007-04-10 00:01:27 +00:00
|
|
|
add_commit_patch_id(commit, ids);
|
2006-06-25 01:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset for next revision walk */
|
2015-06-01 17:44:21 +00:00
|
|
|
clear_commit_marks(c1, SEEN | UNINTERESTING | SHOWN | ADDED);
|
|
|
|
clear_commit_marks(c2, SEEN | UNINTERESTING | SHOWN | ADDED);
|
2006-06-25 01:52:01 +00:00
|
|
|
o1->flags = flags1;
|
|
|
|
o2->flags = flags2;
|
|
|
|
}
|
|
|
|
|
2008-02-19 03:56:06 +00:00
|
|
|
static void gen_message_id(struct rev_info *info, char *base)
|
2006-07-15 00:48:51 +00:00
|
|
|
{
|
2008-10-09 19:12:12 +00:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2017-04-21 10:45:48 +00:00
|
|
|
strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
|
2017-04-26 19:29:31 +00:00
|
|
|
(timestamp_t) time(NULL),
|
2012-05-24 23:32:52 +00:00
|
|
|
git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
|
2008-02-19 03:56:06 +00:00
|
|
|
info->message_id = strbuf_detach(&buf, NULL);
|
2006-07-15 00:48:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 15:01:59 +00:00
|
|
|
static void print_signature(FILE *file)
|
2010-06-16 05:59:25 +00:00
|
|
|
{
|
2014-05-21 21:07:51 +00:00
|
|
|
if (!signature || !*signature)
|
|
|
|
return;
|
|
|
|
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(file, "-- \n%s", signature);
|
2014-05-21 21:07:51 +00:00
|
|
|
if (signature[strlen(signature)-1] != '\n')
|
2016-06-22 15:01:59 +00:00
|
|
|
putc('\n', file);
|
|
|
|
putc('\n', file);
|
2010-06-16 05:59:25 +00:00
|
|
|
}
|
|
|
|
|
2013-04-07 17:46:24 +00:00
|
|
|
static char *find_branch_name(struct rev_info *rev)
|
|
|
|
{
|
|
|
|
int i, positive = -1;
|
2015-11-10 02:22:28 +00:00
|
|
|
struct object_id branch_oid;
|
|
|
|
const struct object_id *tip_oid;
|
2014-06-18 19:48:29 +00:00
|
|
|
const char *ref, *v;
|
2013-04-07 17:46:24 +00:00
|
|
|
char *full_ref, *branch = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < rev->cmdline.nr; i++) {
|
|
|
|
if (rev->cmdline.rev[i].flags & UNINTERESTING)
|
|
|
|
continue;
|
|
|
|
if (positive < 0)
|
|
|
|
positive = i;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (positive < 0)
|
|
|
|
return NULL;
|
|
|
|
ref = rev->cmdline.rev[positive].name;
|
2015-11-10 02:22:28 +00:00
|
|
|
tip_oid = &rev->cmdline.rev[positive].item->oid;
|
2020-09-01 22:28:09 +00:00
|
|
|
if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
|
2014-06-18 19:48:29 +00:00
|
|
|
skip_prefix(full_ref, "refs/heads/", &v) &&
|
convert "oidcmp() == 0" to oideq()
Using the more restrictive oideq() should, in the long run,
give the compiler more opportunities to optimize these
callsites. For now, this conversion should be a complete
noop with respect to the generated code.
The result is also perhaps a little more readable, as it
avoids the "zero is equal" idiom. Since it's so prevalent in
C, I think seasoned programmers tend not to even notice it
anymore, but it can sometimes make for awkward double
negations (e.g., we can drop a few !!oidcmp() instances
here).
This patch was generated almost entirely by the included
coccinelle patch. This mechanical conversion should be
completely safe, because we check explicitly for cases where
oidcmp() is compared to 0, which is what oideq() is doing
under the hood. Note that we don't have to catch "!oidcmp()"
separately; coccinelle's standard isomorphisms make sure the
two are treated equivalently.
I say "almost" because I did hand-edit the coccinelle output
to fix up a few style violations (it mostly keeps the
original formatting, but sometimes unwraps long lines).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-28 21:22:40 +00:00
|
|
|
oideq(tip_oid, &branch_oid))
|
2014-06-18 19:48:29 +00:00
|
|
|
branch = xstrdup(v);
|
2013-04-07 17:46:24 +00:00
|
|
|
free(full_ref);
|
|
|
|
return branch;
|
|
|
|
}
|
|
|
|
|
2018-07-22 09:57:04 +00:00
|
|
|
static void show_diffstat(struct rev_info *rev,
|
|
|
|
struct commit *origin, struct commit *head)
|
|
|
|
{
|
|
|
|
struct diff_options opts;
|
|
|
|
|
|
|
|
memcpy(&opts, &rev->diffopt, sizeof(opts));
|
|
|
|
opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
|
|
|
|
diff_setup_done(&opts);
|
|
|
|
|
|
|
|
diff_tree_oid(get_commit_tree_oid(origin),
|
|
|
|
get_commit_tree_oid(head),
|
|
|
|
"", &opts);
|
|
|
|
diffcore_std(&opts);
|
|
|
|
diff_flush(&opts);
|
|
|
|
|
|
|
|
fprintf(rev->diffopt.file, "\n");
|
|
|
|
}
|
|
|
|
|
2019-10-15 09:06:40 +00:00
|
|
|
static void prepare_cover_text(struct pretty_print_context *pp,
|
|
|
|
const char *branch_name,
|
|
|
|
struct strbuf *sb,
|
|
|
|
const char *encoding,
|
|
|
|
int need_8bit_cte)
|
|
|
|
{
|
|
|
|
const char *subject = "*** SUBJECT HERE ***";
|
|
|
|
const char *body = "*** BLURB HERE ***";
|
|
|
|
struct strbuf description_sb = STRBUF_INIT;
|
|
|
|
struct strbuf subject_sb = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (cover_from_description_mode == COVER_FROM_NONE)
|
|
|
|
goto do_pp;
|
|
|
|
|
|
|
|
if (branch_name && *branch_name)
|
|
|
|
read_branch_desc(&description_sb, branch_name);
|
|
|
|
if (!description_sb.len)
|
|
|
|
goto do_pp;
|
|
|
|
|
|
|
|
if (cover_from_description_mode == COVER_FROM_SUBJECT ||
|
|
|
|
cover_from_description_mode == COVER_FROM_AUTO)
|
|
|
|
body = format_subject(&subject_sb, description_sb.buf, " ");
|
|
|
|
|
|
|
|
if (cover_from_description_mode == COVER_FROM_MESSAGE ||
|
|
|
|
(cover_from_description_mode == COVER_FROM_AUTO &&
|
|
|
|
subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
|
|
|
|
body = description_sb.buf;
|
|
|
|
else
|
|
|
|
subject = subject_sb.buf;
|
|
|
|
|
|
|
|
do_pp:
|
|
|
|
pp_title_line(pp, &subject, sb, encoding, need_8bit_cte);
|
|
|
|
pp_remainder(pp, &body, sb, 0);
|
|
|
|
|
|
|
|
strbuf_release(&description_sb);
|
|
|
|
strbuf_release(&subject_sb);
|
|
|
|
}
|
|
|
|
|
2019-11-20 21:18:47 +00:00
|
|
|
static int get_notes_refs(struct string_list_item *item, void *arg)
|
|
|
|
{
|
2020-07-28 20:24:27 +00:00
|
|
|
strvec_pushf(arg, "--notes=%s", item->string);
|
2019-11-20 21:18:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-28 20:24:27 +00:00
|
|
|
static void get_notes_args(struct strvec *arg, struct rev_info *rev)
|
2019-11-20 21:18:47 +00:00
|
|
|
{
|
|
|
|
if (!rev->show_notes) {
|
2020-07-28 20:24:27 +00:00
|
|
|
strvec_push(arg, "--no-notes");
|
2019-11-20 21:18:47 +00:00
|
|
|
} else if (rev->notes_opt.use_default_notes > 0 ||
|
|
|
|
(rev->notes_opt.use_default_notes == -1 &&
|
|
|
|
!rev->notes_opt.extra_notes_refs.nr)) {
|
2020-07-28 20:24:27 +00:00
|
|
|
strvec_push(arg, "--notes");
|
2019-11-20 21:18:47 +00:00
|
|
|
} else {
|
|
|
|
for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 19:28:34 +00:00
|
|
|
static void make_cover_letter(struct rev_info *rev, int use_separate_file,
|
2008-02-25 23:24:17 +00:00
|
|
|
struct commit *origin,
|
2013-04-07 17:46:24 +00:00
|
|
|
int nr, struct commit **list,
|
2011-09-22 03:32:28 +00:00
|
|
|
const char *branch_name,
|
2011-04-12 15:35:38 +00:00
|
|
|
int quiet)
|
2008-02-19 03:56:13 +00:00
|
|
|
{
|
|
|
|
const char *committer;
|
2008-02-25 23:24:17 +00:00
|
|
|
struct shortlog log;
|
2008-10-09 19:12:12 +00:00
|
|
|
struct strbuf sb = STRBUF_INIT;
|
2008-02-25 23:24:17 +00:00
|
|
|
int i;
|
2009-05-18 23:44:39 +00:00
|
|
|
const char *encoding = "UTF-8";
|
2008-03-15 07:09:20 +00:00
|
|
|
int need_8bit_cte = 0;
|
2011-05-26 22:27:49 +00:00
|
|
|
struct pretty_print_context pp = {0};
|
2013-04-07 17:46:24 +00:00
|
|
|
struct commit *head = list[0];
|
2008-02-19 03:56:13 +00:00
|
|
|
|
2016-06-05 04:46:39 +00:00
|
|
|
if (!cmit_fmt_is_mail(rev->commit_format))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("cover letter needs email format"));
|
2008-02-19 03:56:13 +00:00
|
|
|
|
2009-03-23 02:14:03 +00:00
|
|
|
committer = git_committer_info(0);
|
2009-03-23 02:14:02 +00:00
|
|
|
|
2020-11-04 19:28:34 +00:00
|
|
|
if (use_separate_file &&
|
2016-06-22 15:01:59 +00:00
|
|
|
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
|
2019-02-22 19:26:43 +00:00
|
|
|
die(_("failed to create cover-letter file"));
|
2008-02-19 03:56:13 +00:00
|
|
|
|
2018-05-02 02:20:52 +00:00
|
|
|
log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
|
2008-02-19 03:56:13 +00:00
|
|
|
|
2014-06-10 21:41:51 +00:00
|
|
|
for (i = 0; !need_8bit_cte && i < nr; i++) {
|
2014-06-10 21:44:13 +00:00
|
|
|
const char *buf = get_commit_buffer(list[i], NULL);
|
2014-06-10 21:41:51 +00:00
|
|
|
if (has_non_ascii(buf))
|
2009-08-10 16:22:22 +00:00
|
|
|
need_8bit_cte = 1;
|
2014-06-10 21:41:51 +00:00
|
|
|
unuse_commit_buffer(list[i], buf);
|
|
|
|
}
|
2009-08-10 16:22:22 +00:00
|
|
|
|
2013-04-07 17:46:24 +00:00
|
|
|
if (!branch_name)
|
|
|
|
branch_name = find_branch_name(rev);
|
|
|
|
|
2011-05-26 22:27:49 +00:00
|
|
|
pp.fmt = CMIT_FMT_EMAIL;
|
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 16:55:02 +00:00
|
|
|
pp.date_mode.type = DATE_RFC2822;
|
2017-03-01 11:37:07 +00:00
|
|
|
pp.rev = rev;
|
|
|
|
pp.print_email_subject = 1;
|
2011-05-26 22:27:49 +00:00
|
|
|
pp_user_info(&pp, NULL, &sb, committer, encoding);
|
2019-10-15 09:06:40 +00:00
|
|
|
prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte);
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev->diffopt.file, "%s\n", sb.buf);
|
2008-02-19 03:56:13 +00:00
|
|
|
|
|
|
|
strbuf_release(&sb);
|
|
|
|
|
2008-02-25 23:24:17 +00:00
|
|
|
shortlog_init(&log);
|
2008-03-02 15:53:39 +00:00
|
|
|
log.wrap_lines = 1;
|
2018-01-25 11:59:26 +00:00
|
|
|
log.wrap = MAIL_DEFAULT_WRAP;
|
2008-03-02 15:53:39 +00:00
|
|
|
log.in1 = 2;
|
|
|
|
log.in2 = 4;
|
2016-06-22 15:01:59 +00:00
|
|
|
log.file = rev->diffopt.file;
|
shortlog: allow multiple groups to be specified
Now that shortlog supports reading from trailers, it can be useful to
combine counts from multiple trailers, or between trailers and authors.
This can be done manually by post-processing the output from multiple
runs, but it's non-trivial to make sure that each name/commit pair is
counted only once.
This patch teaches shortlog to accept multiple --group options on the
command line, and pull data from all of them. That makes it possible to
run:
git shortlog -ns --group=author --group=trailer:co-authored-by
to get a shortlog that counts authors and co-authors equally.
The implementation is mostly straightforward. The "group" enum becomes a
bitfield, and the trailer key becomes a list. I didn't bother
implementing the multi-group semantics for reading from stdin. It would
be possible to do, but the existing matching code makes it awkward, and
I doubt anybody cares.
The duplicate suppression we used for trailers now covers authors and
committers as well (though in non-trailer single-group mode we can skip
the hash insertion and lookup, since we only see one value per commit).
There is one subtlety: we now care about the case when no group bit is
set (in which case we default to showing the author). The caller in
builtin/log.c needs to be adapted to ask explicitly for authors, rather
than relying on shortlog_init(). It would be possible with some
gymnastics to make this keep working as-is, but it's not worth it for a
single caller.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-09-27 08:40:15 +00:00
|
|
|
log.groups = SHORTLOG_GROUP_AUTHOR;
|
2022-10-24 18:55:41 +00:00
|
|
|
shortlog_finish_setup(&log);
|
2008-02-25 23:24:17 +00:00
|
|
|
for (i = 0; i < nr; i++)
|
|
|
|
shortlog_add_commit(&log, list[i]);
|
|
|
|
|
|
|
|
shortlog_output(&log);
|
|
|
|
|
2018-07-22 09:57:04 +00:00
|
|
|
/* We can only do diffstat with a unique reference point */
|
|
|
|
if (origin)
|
|
|
|
show_diffstat(rev, origin, head);
|
2008-02-19 03:56:13 +00:00
|
|
|
|
2018-07-22 09:57:05 +00:00
|
|
|
if (rev->idiff_oid1) {
|
2018-07-22 09:57:06 +00:00
|
|
|
fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title);
|
2020-09-08 07:16:09 +00:00
|
|
|
show_interdiff(rev->idiff_oid1, rev->idiff_oid2, 0,
|
|
|
|
&rev->diffopt);
|
2018-07-22 09:57:05 +00:00
|
|
|
}
|
2018-07-22 09:57:13 +00:00
|
|
|
|
|
|
|
if (rev->rdiff1) {
|
range-diff: always pass at least minimal diff options
Commit d8981c3f88 ("format-patch: do not let its diff-options affect
--range-diff", 2018-11-30) taught `show_range_diff()` to accept a
NULL-pointer as an indication that it should use its own "reasonable
default". That fixed a regression from a5170794 ("Merge branch
'ab/range-diff-no-patch'", 2018-11-18), but unfortunately it introduced
a regression of its own.
In particular, it means we forget the `file` member of the diff options,
so rather than placing a range-diff in the cover-letter, we write it to
stdout. In order to fix this, rewrite the two callers adjusted by
d8981c3f88 to instead create a "dummy" set of diff options where they
only fill in the fields we absolutely require, such as output file and
color.
Modify and extend the existing tests to try and verify that the right
contents end up in the right place.
Don't revert `show_range_diff()`, i.e., let it keep accepting NULL.
Rather than removing what is dead code and figuring out it isn't
actually dead and we've broken 2.20, just leave it for now.
[es: retain diff coloring when going to stdout]
Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-12-03 21:21:31 +00:00
|
|
|
/*
|
|
|
|
* Pass minimum required diff-options to range-diff; others
|
|
|
|
* can be added later if deemed desirable.
|
|
|
|
*/
|
|
|
|
struct diff_options opts;
|
2020-07-28 20:24:27 +00:00
|
|
|
struct strvec other_arg = STRVEC_INIT;
|
2021-02-05 14:46:11 +00:00
|
|
|
struct range_diff_options range_diff_opts = {
|
|
|
|
.creation_factor = rev->creation_factor,
|
|
|
|
.dual_color = 1,
|
|
|
|
.diffopt = &opts,
|
|
|
|
.other_arg = &other_arg
|
|
|
|
};
|
|
|
|
|
range-diff: always pass at least minimal diff options
Commit d8981c3f88 ("format-patch: do not let its diff-options affect
--range-diff", 2018-11-30) taught `show_range_diff()` to accept a
NULL-pointer as an indication that it should use its own "reasonable
default". That fixed a regression from a5170794 ("Merge branch
'ab/range-diff-no-patch'", 2018-11-18), but unfortunately it introduced
a regression of its own.
In particular, it means we forget the `file` member of the diff options,
so rather than placing a range-diff in the cover-letter, we write it to
stdout. In order to fix this, rewrite the two callers adjusted by
d8981c3f88 to instead create a "dummy" set of diff options where they
only fill in the fields we absolutely require, such as output file and
color.
Modify and extend the existing tests to try and verify that the right
contents end up in the right place.
Don't revert `show_range_diff()`, i.e., let it keep accepting NULL.
Rather than removing what is dead code and figuring out it isn't
actually dead and we've broken 2.20, just leave it for now.
[es: retain diff coloring when going to stdout]
Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-12-03 21:21:31 +00:00
|
|
|
diff_setup(&opts);
|
|
|
|
opts.file = rev->diffopt.file;
|
|
|
|
opts.use_color = rev->diffopt.use_color;
|
|
|
|
diff_setup_done(&opts);
|
2018-07-22 09:57:15 +00:00
|
|
|
fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
|
2019-11-20 21:18:47 +00:00
|
|
|
get_notes_args(&other_arg, rev);
|
2021-02-05 14:46:11 +00:00
|
|
|
show_range_diff(rev->rdiff1, rev->rdiff2, &range_diff_opts);
|
2020-07-28 20:24:27 +00:00
|
|
|
strvec_clear(&other_arg);
|
2018-07-22 09:57:13 +00:00
|
|
|
}
|
2006-07-15 00:48:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-14 05:30:45 +00:00
|
|
|
static const char *clean_message_id(const char *msg_id)
|
|
|
|
{
|
|
|
|
char ch;
|
|
|
|
const char *a, *z, *m;
|
|
|
|
|
|
|
|
m = msg_id;
|
|
|
|
while ((ch = *m) && (isspace(ch) || (ch == '<')))
|
|
|
|
m++;
|
|
|
|
a = m;
|
|
|
|
z = NULL;
|
|
|
|
while ((ch = *m)) {
|
|
|
|
if (!isspace(ch) && (ch != '>'))
|
|
|
|
z = m;
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
if (!z)
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("insane in-reply-to: %s"), msg_id);
|
2007-09-14 05:30:45 +00:00
|
|
|
if (++z == m)
|
|
|
|
return a;
|
2007-09-15 22:32:36 +00:00
|
|
|
return xmemdupz(a, z - a);
|
2007-09-14 05:30:45 +00:00
|
|
|
}
|
|
|
|
|
2009-01-12 23:18:02 +00:00
|
|
|
static const char *set_outdir(const char *prefix, const char *output_directory)
|
|
|
|
{
|
|
|
|
if (output_directory && is_absolute_path(output_directory))
|
|
|
|
return output_directory;
|
|
|
|
|
|
|
|
if (!prefix || !*prefix) {
|
|
|
|
if (output_directory)
|
|
|
|
return output_directory;
|
|
|
|
/* The user did not explicitly ask for "./" */
|
|
|
|
outdir_offset = 2;
|
|
|
|
return "./";
|
|
|
|
}
|
|
|
|
|
|
|
|
outdir_offset = strlen(prefix);
|
|
|
|
if (!output_directory)
|
|
|
|
return prefix;
|
|
|
|
|
2017-03-21 01:28:49 +00:00
|
|
|
return prefix_filename(prefix, output_directory);
|
2009-01-12 23:18:02 +00:00
|
|
|
}
|
|
|
|
|
2009-05-16 09:24:46 +00:00
|
|
|
static const char * const builtin_format_patch_usage[] = {
|
2015-01-13 07:44:47 +00:00
|
|
|
N_("git format-patch [<options>] [<since> | <revision-range>]"),
|
2009-05-16 09:24:46 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static int keep_subject = 0;
|
|
|
|
|
|
|
|
static int keep_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
|
|
|
BUG_ON_OPT_ARG(arg);
|
2009-05-16 09:24:46 +00:00
|
|
|
((struct rev_info *)opt->value)->total = -1;
|
|
|
|
keep_subject = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int subject_prefix = 0;
|
|
|
|
|
|
|
|
static int subject_prefix_callback(const struct option *opt, const char *arg,
|
|
|
|
int unset)
|
|
|
|
{
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
2009-05-16 09:24:46 +00:00
|
|
|
subject_prefix = 1;
|
|
|
|
((struct rev_info *)opt->value)->subject_prefix = arg;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:23:25 +00:00
|
|
|
static int rfc_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
|
|
|
BUG_ON_OPT_ARG(arg);
|
2016-09-20 04:23:25 +00:00
|
|
|
return subject_prefix_callback(opt, "RFC PATCH", unset);
|
|
|
|
}
|
|
|
|
|
2009-05-31 23:17:31 +00:00
|
|
|
static int numbered_cmdline_opt = 0;
|
|
|
|
|
2009-05-16 09:24:46 +00:00
|
|
|
static int numbered_callback(const struct option *opt, const char *arg,
|
|
|
|
int unset)
|
|
|
|
{
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_ARG(arg);
|
2009-05-31 23:17:31 +00:00
|
|
|
*(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
|
2009-05-16 09:24:46 +00:00
|
|
|
if (unset)
|
|
|
|
auto_number = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int no_numbered_callback(const struct option *opt, const char *arg,
|
|
|
|
int unset)
|
|
|
|
{
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
2009-05-16 09:24:46 +00:00
|
|
|
return numbered_callback(opt, arg, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int output_directory_callback(const struct option *opt, const char *arg,
|
|
|
|
int unset)
|
|
|
|
{
|
|
|
|
const char **dir = (const char **)opt->value;
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 06:45:42 +00:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
2009-05-16 09:24:46 +00:00
|
|
|
if (*dir)
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("two output directories?"));
|
2009-05-16 09:24:46 +00:00
|
|
|
*dir = arg;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int thread_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
2019-10-15 09:06:37 +00:00
|
|
|
enum thread_level *thread = (enum thread_level *)opt->value;
|
2009-05-16 09:24:46 +00:00
|
|
|
if (unset)
|
2019-10-15 09:06:37 +00:00
|
|
|
*thread = THREAD_UNSET;
|
2009-05-16 09:24:46 +00:00
|
|
|
else if (!arg || !strcmp(arg, "shallow"))
|
|
|
|
*thread = THREAD_SHALLOW;
|
|
|
|
else if (!strcmp(arg, "deep"))
|
|
|
|
*thread = THREAD_DEEP;
|
2019-02-16 11:24:41 +00:00
|
|
|
/*
|
|
|
|
* Please update _git_formatpatch() in git-completion.bash
|
|
|
|
* when you add new options.
|
|
|
|
*/
|
2009-05-16 09:24:46 +00:00
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int attach_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
struct rev_info *rev = (struct rev_info *)opt->value;
|
|
|
|
if (unset)
|
|
|
|
rev->mime_boundary = NULL;
|
|
|
|
else if (arg)
|
|
|
|
rev->mime_boundary = arg;
|
|
|
|
else
|
|
|
|
rev->mime_boundary = git_version_string;
|
|
|
|
rev->no_inline = unset ? 0 : 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int inline_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
struct rev_info *rev = (struct rev_info *)opt->value;
|
|
|
|
if (unset)
|
|
|
|
rev->mime_boundary = NULL;
|
|
|
|
else if (arg)
|
|
|
|
rev->mime_boundary = arg;
|
|
|
|
else
|
|
|
|
rev->mime_boundary = git_version_string;
|
|
|
|
rev->no_inline = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int header_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
2010-03-07 22:46:47 +00:00
|
|
|
if (unset) {
|
|
|
|
string_list_clear(&extra_hdr, 0);
|
|
|
|
string_list_clear(&extra_to, 0);
|
|
|
|
string_list_clear(&extra_cc, 0);
|
|
|
|
} else {
|
2019-12-04 21:24:55 +00:00
|
|
|
add_header(arg);
|
2010-03-07 22:46:47 +00:00
|
|
|
}
|
2009-05-16 09:24:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-16 23:39:34 +00:00
|
|
|
static int to_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
2010-03-07 22:46:47 +00:00
|
|
|
if (unset)
|
|
|
|
string_list_clear(&extra_to, 0);
|
|
|
|
else
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(&extra_to, arg);
|
2009-05-16 09:24:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cc_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
2010-03-07 22:46:47 +00:00
|
|
|
if (unset)
|
|
|
|
string_list_clear(&extra_cc, 0);
|
|
|
|
else
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(&extra_cc, arg);
|
2009-05-16 09:24:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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 07:08:22 +00:00
|
|
|
static int from_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
char **from = opt->value;
|
|
|
|
|
|
|
|
free(*from);
|
|
|
|
|
|
|
|
if (unset)
|
|
|
|
*from = NULL;
|
|
|
|
else if (arg)
|
|
|
|
*from = xstrdup(arg);
|
|
|
|
else
|
|
|
|
*from = xstrdup(git_committer_info(IDENT_NO_DATE));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
static int base_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
const char **base_commit = opt->value;
|
|
|
|
|
|
|
|
if (unset) {
|
|
|
|
auto_base = AUTO_BASE_NEVER;
|
|
|
|
*base_commit = NULL;
|
|
|
|
} else if (!strcmp(arg, "auto")) {
|
|
|
|
auto_base = AUTO_BASE_ALWAYS;
|
|
|
|
*base_commit = NULL;
|
|
|
|
} else {
|
|
|
|
auto_base = AUTO_BASE_NEVER;
|
|
|
|
*base_commit = arg;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
struct base_tree_info {
|
|
|
|
struct object_id base_commit;
|
|
|
|
int nr_patch_id, alloc_patch_id;
|
|
|
|
struct object_id *patch_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct commit *get_base_commit(const char *base_commit,
|
|
|
|
struct commit **list,
|
|
|
|
int total)
|
|
|
|
{
|
|
|
|
struct commit *base = NULL;
|
|
|
|
struct commit **rev;
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
int i = 0, rev_nr = 0, auto_select, die_on_failure;
|
|
|
|
|
|
|
|
switch (auto_base) {
|
|
|
|
case AUTO_BASE_NEVER:
|
|
|
|
if (base_commit) {
|
|
|
|
auto_select = 0;
|
|
|
|
die_on_failure = 1;
|
|
|
|
} else {
|
|
|
|
/* no base information is requested */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AUTO_BASE_ALWAYS:
|
|
|
|
case AUTO_BASE_WHEN_ABLE:
|
|
|
|
if (base_commit) {
|
|
|
|
BUG("requested automatic base selection but a commit was provided");
|
|
|
|
} else {
|
|
|
|
auto_select = 1;
|
|
|
|
die_on_failure = auto_base == AUTO_BASE_ALWAYS;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BUG("unexpected automatic base selection method");
|
|
|
|
}
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (!auto_select) {
|
2016-04-26 07:51:24 +00:00
|
|
|
base = lookup_commit_reference_by_name(base_commit);
|
|
|
|
if (!base)
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("unknown commit %s"), base_commit);
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
} else {
|
2016-04-26 07:51:23 +00:00
|
|
|
struct branch *curr_branch = branch_get(NULL);
|
|
|
|
const char *upstream = branch_get_upstream(curr_branch, NULL);
|
|
|
|
if (upstream) {
|
|
|
|
struct commit_list *base_list;
|
|
|
|
struct commit *commit;
|
2016-09-05 20:07:55 +00:00
|
|
|
struct object_id oid;
|
2016-04-26 07:51:23 +00:00
|
|
|
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (get_oid(upstream, &oid)) {
|
|
|
|
if (die_on_failure)
|
|
|
|
die(_("failed to resolve '%s' as a valid ref"), upstream);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
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-06 22:10:10 +00:00
|
|
|
commit = lookup_commit_or_die(&oid, "upstream base");
|
2016-04-26 07:51:23 +00:00
|
|
|
base_list = get_merge_bases_many(commit, total, list);
|
|
|
|
/* There should be one and only one merge base. */
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (!base_list || base_list->next) {
|
|
|
|
if (die_on_failure) {
|
|
|
|
die(_("could not find exact merge base"));
|
|
|
|
} else {
|
|
|
|
free_commit_list(base_list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2016-04-26 07:51:23 +00:00
|
|
|
base = base_list->item;
|
|
|
|
free_commit_list(base_list);
|
|
|
|
} else {
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (die_on_failure)
|
|
|
|
die(_("failed to get upstream, if you want to record base commit automatically,\n"
|
|
|
|
"please use git branch --set-upstream-to to track a remote branch.\n"
|
|
|
|
"Or you could specify base commit by --base=<base-commit-id> manually"));
|
|
|
|
else
|
|
|
|
return NULL;
|
2016-04-26 07:51:23 +00:00
|
|
|
}
|
|
|
|
}
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
|
|
|
ALLOC_ARRAY(rev, total);
|
|
|
|
for (i = 0; i < total; i++)
|
|
|
|
rev[i] = list[i];
|
|
|
|
|
|
|
|
rev_nr = total;
|
|
|
|
/*
|
|
|
|
* Get merge base through pair-wise computations
|
|
|
|
* and store it in rev[0].
|
|
|
|
*/
|
|
|
|
while (rev_nr > 1) {
|
|
|
|
for (i = 0; i < rev_nr / 2; i++) {
|
|
|
|
struct commit_list *merge_base;
|
|
|
|
merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (!merge_base || merge_base->next) {
|
|
|
|
if (die_on_failure) {
|
|
|
|
die(_("failed to find exact merge base"));
|
|
|
|
} else {
|
|
|
|
free(rev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
|
|
|
rev[i] = merge_base->item;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rev_nr % 2)
|
|
|
|
rev[i] = rev[2 * i];
|
2017-07-08 10:35:35 +00:00
|
|
|
rev_nr = DIV_ROUND_UP(rev_nr, 2);
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
}
|
|
|
|
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (!in_merge_bases(base, rev[0])) {
|
|
|
|
if (die_on_failure) {
|
|
|
|
die(_("base commit should be the ancestor of revision list"));
|
|
|
|
} else {
|
|
|
|
free(rev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < total; i++) {
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
if (base == list[i]) {
|
|
|
|
if (die_on_failure) {
|
|
|
|
die(_("base commit shouldn't be in revision list"));
|
|
|
|
} else {
|
|
|
|
free(rev);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
free(rev);
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
2018-05-19 05:28:29 +00:00
|
|
|
define_commit_slab(commit_base, int);
|
|
|
|
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
static void prepare_bases(struct base_tree_info *bases,
|
|
|
|
struct commit *base,
|
|
|
|
struct commit **list,
|
|
|
|
int total)
|
|
|
|
{
|
|
|
|
struct commit *commit;
|
|
|
|
struct rev_info revs;
|
|
|
|
struct diff_options diffopt;
|
2018-05-19 05:28:29 +00:00
|
|
|
struct commit_base commit_base;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!base)
|
|
|
|
return;
|
|
|
|
|
2018-05-19 05:28:29 +00:00
|
|
|
init_commit_base(&commit_base);
|
2018-09-21 15:57:24 +00:00
|
|
|
repo_diff_setup(the_repository, &diffopt);
|
2017-10-31 18:19:11 +00:00
|
|
|
diffopt.flags.recursive = 1;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
diff_setup_done(&diffopt);
|
|
|
|
|
|
|
|
oidcpy(&bases->base_commit, &base->object.oid);
|
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &revs, NULL);
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
revs.max_parents = 1;
|
|
|
|
revs.topo_order = 1;
|
|
|
|
for (i = 0; i < total; i++) {
|
|
|
|
list[i]->object.flags &= ~UNINTERESTING;
|
|
|
|
add_pending_object(&revs, &list[i]->object, "rev_list");
|
2018-05-19 05:28:29 +00:00
|
|
|
*commit_base_at(&commit_base, list[i]) = 1;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
}
|
|
|
|
base->object.flags |= UNINTERESTING;
|
|
|
|
add_pending_object(&revs, &base->object, "base");
|
|
|
|
|
|
|
|
if (prepare_revision_walk(&revs))
|
|
|
|
die(_("revision walk setup failed"));
|
|
|
|
/*
|
|
|
|
* Traverse the commits list, get prerequisite patch ids
|
|
|
|
* and stuff them in bases structure.
|
|
|
|
*/
|
|
|
|
while ((commit = get_revision(&revs)) != NULL) {
|
2016-09-05 20:07:55 +00:00
|
|
|
struct object_id oid;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
struct object_id *patch_id;
|
2018-05-19 05:28:29 +00:00
|
|
|
if (*commit_base_at(&commit_base, commit))
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
continue;
|
2022-10-24 20:07:40 +00:00
|
|
|
if (commit_patch_id(commit, &diffopt, &oid, 0))
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
die(_("cannot get patch id"));
|
|
|
|
ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
|
|
|
|
patch_id = bases->patch_id + bases->nr_patch_id;
|
2016-09-05 20:07:55 +00:00
|
|
|
oidcpy(patch_id, &oid);
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
bases->nr_patch_id++;
|
|
|
|
}
|
2018-05-19 05:28:29 +00:00
|
|
|
clear_commit_base(&commit_base);
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 15:01:59 +00:00
|
|
|
static void print_bases(struct base_tree_info *bases, FILE *file)
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Only do this once, either for the cover or for the first one */
|
|
|
|
if (is_null_oid(&bases->base_commit))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Show the base commit */
|
2016-09-08 01:12:01 +00:00
|
|
|
fprintf(file, "\nbase-commit: %s\n", oid_to_hex(&bases->base_commit));
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
|
|
|
/* Show the prerequisite patches */
|
|
|
|
for (i = bases->nr_patch_id - 1; i >= 0; i--)
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
|
|
|
free(bases->patch_id);
|
|
|
|
bases->nr_patch_id = 0;
|
|
|
|
bases->alloc_patch_id = 0;
|
|
|
|
oidclr(&bases->base_commit);
|
|
|
|
}
|
|
|
|
|
2021-03-23 11:12:25 +00:00
|
|
|
static const char *diff_title(struct strbuf *sb,
|
|
|
|
const char *reroll_count,
|
|
|
|
const char *generic,
|
|
|
|
const char *rerolled)
|
2018-07-22 09:57:06 +00:00
|
|
|
{
|
2021-03-23 11:12:25 +00:00
|
|
|
int v;
|
|
|
|
|
|
|
|
/* RFC may be v0, so allow -v1 to diff against v0 */
|
|
|
|
if (reroll_count && !strtol_i(reroll_count, 10, &v) &&
|
|
|
|
v >= 1)
|
|
|
|
strbuf_addf(sb, rerolled, v - 1);
|
|
|
|
else
|
2018-07-22 09:57:06 +00:00
|
|
|
strbuf_addstr(sb, generic);
|
|
|
|
return sb->buf;
|
|
|
|
}
|
|
|
|
|
2018-07-22 09:57:13 +00:00
|
|
|
static void infer_range_diff_ranges(struct strbuf *r1,
|
|
|
|
struct strbuf *r2,
|
|
|
|
const char *prev,
|
2018-07-22 09:57:14 +00:00
|
|
|
struct commit *origin,
|
2018-07-22 09:57:13 +00:00
|
|
|
struct commit *head)
|
|
|
|
{
|
|
|
|
const char *head_oid = oid_to_hex(&head->object.oid);
|
2021-01-27 16:37:22 +00:00
|
|
|
int prev_is_range = is_range_diff_range(prev);
|
2018-07-22 09:57:13 +00:00
|
|
|
|
2020-09-08 07:16:10 +00:00
|
|
|
if (prev_is_range)
|
|
|
|
strbuf_addstr(r1, prev);
|
|
|
|
else
|
2018-07-22 09:57:14 +00:00
|
|
|
strbuf_addf(r1, "%s..%s", head_oid, prev);
|
2020-09-08 07:16:10 +00:00
|
|
|
|
|
|
|
if (origin)
|
|
|
|
strbuf_addf(r2, "%s..%s", oid_to_hex(&origin->object.oid), head_oid);
|
|
|
|
else if (prev_is_range)
|
|
|
|
die(_("failed to infer range-diff origin of current series"));
|
|
|
|
else {
|
|
|
|
warning(_("using '%s' as range-diff origin of current series"), prev);
|
2018-07-22 09:57:14 +00:00
|
|
|
strbuf_addf(r2, "%s..%s", prev, head_oid);
|
|
|
|
}
|
2018-07-22 09:57:13 +00:00
|
|
|
}
|
|
|
|
|
2006-07-29 05:44:25 +00:00
|
|
|
int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
2006-04-21 20:19:58 +00:00
|
|
|
{
|
|
|
|
struct commit *commit;
|
|
|
|
struct commit **list = NULL;
|
|
|
|
struct rev_info rev;
|
2022-04-13 20:01:33 +00:00
|
|
|
char *to_free = NULL;
|
2010-03-09 06:58:09 +00:00
|
|
|
struct setup_revision_opt s_r_opt;
|
2009-05-16 09:24:46 +00:00
|
|
|
int nr = 0, total, i;
|
2006-05-04 23:16:40 +00:00
|
|
|
int use_stdout = 0;
|
2006-05-25 21:55:11 +00:00
|
|
|
int start_number = -1;
|
2012-12-22 05:27:38 +00:00
|
|
|
int just_numbers = 0;
|
2006-06-25 01:52:01 +00:00
|
|
|
int ignore_if_in_upstream = 0;
|
2013-04-07 17:46:23 +00:00
|
|
|
int cover_letter = -1;
|
2008-02-25 23:24:17 +00:00
|
|
|
int boundary_count = 0;
|
2008-05-09 22:55:43 +00:00
|
|
|
int no_binary_diff = 0;
|
2015-12-15 01:52:04 +00:00
|
|
|
int zero_commit = 0;
|
2013-04-07 17:46:24 +00:00
|
|
|
struct commit *origin = NULL;
|
2006-07-15 05:47:53 +00:00
|
|
|
const char *in_reply_to = NULL;
|
2007-04-10 00:01:27 +00:00
|
|
|
struct patch_ids ids;
|
2008-10-09 19:12:12 +00:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2009-11-04 07:19:40 +00:00
|
|
|
int use_patch_format = 0;
|
2011-04-12 15:35:38 +00:00
|
|
|
int quiet = 0;
|
2021-03-23 11:12:25 +00:00
|
|
|
const char *reroll_count = NULL;
|
2019-10-15 09:06:40 +00:00
|
|
|
char *cover_from_description_arg = NULL;
|
2011-09-22 03:32:28 +00:00
|
|
|
char *branch_name = NULL;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
char *base_commit = NULL;
|
|
|
|
struct base_tree_info bases;
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
struct commit *base;
|
2017-08-10 18:32:55 +00:00
|
|
|
int show_progress = 0;
|
|
|
|
struct progress *progress = NULL;
|
2018-07-22 09:57:05 +00:00
|
|
|
struct oid_array idiff_prev = OID_ARRAY_INIT;
|
2018-07-22 09:57:06 +00:00
|
|
|
struct strbuf idiff_title = STRBUF_INIT;
|
2018-07-22 09:57:13 +00:00
|
|
|
const char *rdiff_prev = NULL;
|
|
|
|
struct strbuf rdiff1 = STRBUF_INIT;
|
|
|
|
struct strbuf rdiff2 = STRBUF_INIT;
|
2018-07-22 09:57:15 +00:00
|
|
|
struct strbuf rdiff_title = STRBUF_INIT;
|
2018-07-22 09:57:16 +00:00
|
|
|
int creation_factor = -1;
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
|
2009-05-16 09:24:46 +00:00
|
|
|
const struct option builtin_format_patch_options[] = {
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("use [PATCH n/m] even with a single patch"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NOARG, numbered_callback),
|
|
|
|
OPT_CALLBACK_F('N', "no-numbered", &numbered, NULL,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("use [PATCH] even with multiple patches"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback),
|
Documentation: stylistically normalize references to Signed-off-by:
Ted reported an old typo in the git-commit.txt and merge-options.txt.
Namely, the phrase "Signed-off-by line" was used without either a
definite nor indefinite article.
Upon examination, it seems that the documentation (including items in
Documentation/, but also option help strings) have been quite
inconsistent on usage when referring to `Signed-off-by`.
First, very few places used a definite or indefinite article with the
phrase "Signed-off-by line", but that was the initial typo that led
to this investigation. So, normalize using either an indefinite or
definite article consistently.
The original phrasing, in Commit 3f971fc425b (Documentation updates,
2005-08-14), is "Add Signed-off-by line". Commit 6f855371a53 (Add
--signoff, --check, and long option-names. 2005-12-09) switched to
using "Add `Signed-off-by:` line", but didn't normalize the former
commit to match. Later commits seem to have cut and pasted from one
or the other, which is likely how the usage became so inconsistent.
Junio stated on the git mailing list in
<xmqqy2k1dfoh.fsf@gitster.c.googlers.com> a preference to leave off
the colon. Thus, prefer `Signed-off-by` (with backticks) for the
documentation files and Signed-off-by (without backticks) for option
help strings.
Additionally, Junio argued that "trailer" is now the standard term to
refer to `Signed-off-by`, saying that "becomes plenty clear that we
are not talking about any random line in the log message". As such,
prefer "trailer" over "line" anywhere the former word fits.
However, leave alone those few places in documentation that use
Signed-off-by to refer to the process (rather than the specific
trailer), or in places where mail headers are generally discussed in
comparison with Signed-off-by.
Reported-by: "Theodore Y. Ts'o" <tytso@mit.edu>
Signed-off-by: Bradley M. Kuhn <bkuhn@sfconservancy.org>
Acked-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-20 01:03:55 +00:00
|
|
|
OPT_BOOL('s', "signoff", &do_signoff, N_("add a Signed-off-by trailer")),
|
2013-04-07 17:46:22 +00:00
|
|
|
OPT_BOOL(0, "stdout", &use_stdout,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("print patches to standard out")),
|
2013-04-07 17:46:22 +00:00
|
|
|
OPT_BOOL(0, "cover-letter", &cover_letter,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("generate a cover letter")),
|
2013-04-07 17:46:22 +00:00
|
|
|
OPT_BOOL(0, "numbered-files", &just_numbers,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("use simple number sequence for output file names")),
|
|
|
|
OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
|
|
|
|
N_("use <sfx> instead of '.patch'")),
|
2009-05-16 09:24:46 +00:00
|
|
|
OPT_INTEGER(0, "start-number", &start_number,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("start numbering patches at <n> instead of 1")),
|
2021-03-23 11:12:25 +00:00
|
|
|
OPT_STRING('v', "reroll-count", &reroll_count, N_("reroll-count"),
|
2012-12-22 08:21:23 +00:00
|
|
|
N_("mark the series as Nth re-roll")),
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
OPT_INTEGER(0, "filename-max-length", &fmt_patch_name_max,
|
|
|
|
N_("max length of output filename")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK_F(0, "rfc", &rev, NULL,
|
2021-01-06 14:44:03 +00:00
|
|
|
N_("use [RFC PATCH] instead of [PATCH]"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback),
|
2019-10-15 09:06:40 +00:00
|
|
|
OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
|
|
|
|
N_("cover-from-description-mode"),
|
|
|
|
N_("generate parts of a cover letter based on a branch's description")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK_F(0, "subject-prefix", &rev, N_("prefix"),
|
2021-01-06 14:44:03 +00:00
|
|
|
N_("use [<prefix>] instead of [PATCH]"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NONEG, subject_prefix_callback),
|
|
|
|
OPT_CALLBACK_F('o', "output-directory", &output_directory,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("dir"), N_("store resulting files in <dir>"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NONEG, output_directory_callback),
|
|
|
|
OPT_CALLBACK_F('k', "keep-subject", &rev, NULL,
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("don't strip/add [PATCH]"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback),
|
2013-08-03 11:51:19 +00:00
|
|
|
OPT_BOOL(0, "no-binary", &no_binary_diff,
|
|
|
|
N_("don't output binary diffs")),
|
2015-12-15 01:52:04 +00:00
|
|
|
OPT_BOOL(0, "zero-commit", &zero_commit,
|
|
|
|
N_("output all-zero hash in From header")),
|
2013-08-03 11:51:19 +00:00
|
|
|
OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
|
|
|
|
N_("don't include a patch matching a commit upstream")),
|
2018-05-20 15:42:58 +00:00
|
|
|
OPT_SET_INT_F('p', "no-stat", &use_patch_format,
|
|
|
|
N_("show patch format instead of default (patch + stat)"),
|
|
|
|
1, PARSE_OPT_NONEG),
|
2012-08-20 12:32:12 +00:00
|
|
|
OPT_GROUP(N_("Messaging")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK(0, "add-header", NULL, N_("header"),
|
|
|
|
N_("add email header"), header_callback),
|
|
|
|
OPT_CALLBACK(0, "to", NULL, N_("email"), N_("add To: header"), to_callback),
|
|
|
|
OPT_CALLBACK(0, "cc", NULL, N_("email"), N_("add Cc: header"), cc_callback),
|
|
|
|
OPT_CALLBACK_F(0, "from", &from, N_("ident"),
|
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 07:08:22 +00:00
|
|
|
N_("set From address to <ident> (or committer ident if absent)"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_OPTARG, from_callback),
|
2012-08-20 12:32:12 +00:00
|
|
|
OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
|
|
|
|
N_("make first mail a reply to <message-id>")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK_F(0, "attach", &rev, N_("boundary"),
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("attach the patch"), PARSE_OPT_OPTARG,
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
attach_callback),
|
|
|
|
OPT_CALLBACK_F(0, "inline", &rev, N_("boundary"),
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("inline the patch"),
|
2009-05-16 09:24:46 +00:00
|
|
|
PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
inline_callback),
|
|
|
|
OPT_CALLBACK_F(0, "thread", &thread, N_("style"),
|
2012-08-20 12:32:12 +00:00
|
|
|
N_("enable message threading, styles: shallow, deep"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
PARSE_OPT_OPTARG, thread_callback),
|
2012-08-20 12:32:12 +00:00
|
|
|
OPT_STRING(0, "signature", &signature, N_("signature"),
|
|
|
|
N_("add a signature")),
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
OPT_CALLBACK_F(0, "base", &base_commit, N_("base-commit"),
|
|
|
|
N_("add prerequisite tree info to the patch series"),
|
|
|
|
0, base_callback),
|
2014-05-24 04:08:14 +00:00
|
|
|
OPT_FILENAME(0, "signature-file", &signature_file,
|
|
|
|
N_("add a signature from a file")),
|
2013-08-03 11:51:20 +00:00
|
|
|
OPT__QUIET(&quiet, N_("don't print the patch filenames")),
|
2017-08-10 18:32:55 +00:00
|
|
|
OPT_BOOL(0, "progress", &show_progress,
|
|
|
|
N_("show progress while generating patches")),
|
2018-07-22 09:57:05 +00:00
|
|
|
OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
|
2018-07-22 09:57:09 +00:00
|
|
|
N_("show changes against <rev> in cover letter or single patch"),
|
2018-07-22 09:57:05 +00:00
|
|
|
parse_opt_object_name),
|
2018-07-22 09:57:13 +00:00
|
|
|
OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"),
|
2018-07-22 09:57:17 +00:00
|
|
|
N_("show changes against <refspec> in cover letter or single patch")),
|
2018-07-22 09:57:16 +00:00
|
|
|
OPT_INTEGER(0, "creation-factor", &creation_factor,
|
|
|
|
N_("percentage by which creation is weighted")),
|
2022-08-29 21:38:36 +00:00
|
|
|
OPT_BOOL(0, "force-in-body-from", &force_in_body_from,
|
|
|
|
N_("show in-body From: even if identical to the e-mail header")),
|
2009-05-16 09:24:46 +00:00
|
|
|
OPT_END()
|
|
|
|
};
|
2006-04-21 20:19:58 +00:00
|
|
|
|
2010-03-07 22:46:46 +00:00
|
|
|
extra_hdr.strdup_strings = 1;
|
|
|
|
extra_to.strdup_strings = 1;
|
|
|
|
extra_cc.strdup_strings = 1;
|
2022-02-16 00:00:36 +00:00
|
|
|
|
2016-02-25 08:59:20 +00:00
|
|
|
init_log_defaults();
|
2019-12-09 13:10:48 +00:00
|
|
|
init_display_notes(¬es_opt);
|
|
|
|
git_config(git_format_config, NULL);
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
2022-02-16 00:00:36 +00:00
|
|
|
git_config(grep_config, &rev.grep_filter);
|
|
|
|
|
2019-12-09 13:10:48 +00:00
|
|
|
rev.show_notes = show_notes;
|
|
|
|
memcpy(&rev.notes_opt, ¬es_opt, sizeof(notes_opt));
|
2006-04-21 20:19:58 +00:00
|
|
|
rev.commit_format = CMIT_FMT_EMAIL;
|
2020-04-08 04:31:38 +00:00
|
|
|
rev.encode_email_headers = default_encode_email_headers;
|
2016-03-29 22:49:24 +00:00
|
|
|
rev.expand_tabs_in_log_default = 0;
|
2006-04-21 20:19:58 +00:00
|
|
|
rev.verbose_header = 1;
|
|
|
|
rev.diff = 1;
|
2011-03-21 10:14:06 +00:00
|
|
|
rev.max_parents = 1;
|
2017-10-31 18:19:11 +00:00
|
|
|
rev.diffopt.flags.recursive = 1;
|
2022-04-30 10:32:44 +00:00
|
|
|
rev.diffopt.no_free = 1;
|
2007-07-02 00:48:59 +00:00
|
|
|
rev.subject_prefix = fmt_patch_subject_prefix;
|
2010-03-09 06:58:09 +00:00
|
|
|
memset(&s_r_opt, 0, sizeof(s_r_opt));
|
|
|
|
s_r_opt.def = "HEAD";
|
2012-07-02 19:43:05 +00:00
|
|
|
s_r_opt.revarg_opt = REVARG_COMMITTISH;
|
2006-06-02 13:21:17 +00:00
|
|
|
|
2009-02-12 15:51:55 +00:00
|
|
|
if (default_attach) {
|
|
|
|
rev.mime_boundary = default_attach;
|
|
|
|
rev.no_inline = 1;
|
|
|
|
}
|
|
|
|
|
2006-05-05 01:33:32 +00:00
|
|
|
/*
|
|
|
|
* Parse the arguments before setup_revisions(), or something
|
2007-05-14 14:44:51 +00:00
|
|
|
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
|
2006-05-05 01:33:32 +00:00
|
|
|
* possibly a valid SHA1.
|
|
|
|
*/
|
2009-05-23 18:53:12 +00:00
|
|
|
argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
|
2009-05-16 09:24:46 +00:00
|
|
|
builtin_format_patch_usage,
|
2022-08-19 16:03:57 +00:00
|
|
|
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
|
2009-11-26 19:11:59 +00:00
|
|
|
PARSE_OPT_KEEP_DASHDASH);
|
2006-05-05 01:33:32 +00:00
|
|
|
|
2022-08-29 21:38:36 +00:00
|
|
|
rev.force_in_body_from = force_in_body_from;
|
|
|
|
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
|
|
|
|
if (fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
|
|
|
|
fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
|
|
|
|
|
2019-10-15 09:06:40 +00:00
|
|
|
if (cover_from_description_arg)
|
|
|
|
cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
|
|
|
|
|
2021-03-23 11:12:25 +00:00
|
|
|
if (reroll_count) {
|
2012-12-22 08:21:23 +00:00
|
|
|
struct strbuf sprefix = STRBUF_INIT;
|
2021-03-23 11:12:25 +00:00
|
|
|
|
|
|
|
strbuf_addf(&sprefix, "%s v%s",
|
2012-12-22 08:21:23 +00:00
|
|
|
rev.subject_prefix, reroll_count);
|
|
|
|
rev.reroll_count = reroll_count;
|
|
|
|
rev.subject_prefix = strbuf_detach(&sprefix, NULL);
|
|
|
|
}
|
|
|
|
|
2010-03-07 22:46:46 +00:00
|
|
|
for (i = 0; i < extra_hdr.nr; i++) {
|
|
|
|
strbuf_addstr(&buf, extra_hdr.items[i].string);
|
2008-02-19 07:40:33 +00:00
|
|
|
strbuf_addch(&buf, '\n');
|
|
|
|
}
|
|
|
|
|
2010-03-07 22:46:46 +00:00
|
|
|
if (extra_to.nr)
|
2008-02-19 07:40:33 +00:00
|
|
|
strbuf_addstr(&buf, "To: ");
|
2010-03-07 22:46:46 +00:00
|
|
|
for (i = 0; i < extra_to.nr; i++) {
|
2008-02-19 07:40:33 +00:00
|
|
|
if (i)
|
|
|
|
strbuf_addstr(&buf, " ");
|
2010-03-07 22:46:46 +00:00
|
|
|
strbuf_addstr(&buf, extra_to.items[i].string);
|
|
|
|
if (i + 1 < extra_to.nr)
|
2008-02-19 07:40:33 +00:00
|
|
|
strbuf_addch(&buf, ',');
|
|
|
|
strbuf_addch(&buf, '\n');
|
|
|
|
}
|
|
|
|
|
2010-03-07 22:46:46 +00:00
|
|
|
if (extra_cc.nr)
|
2008-02-19 07:40:33 +00:00
|
|
|
strbuf_addstr(&buf, "Cc: ");
|
2010-03-07 22:46:46 +00:00
|
|
|
for (i = 0; i < extra_cc.nr; i++) {
|
2008-02-19 07:40:33 +00:00
|
|
|
if (i)
|
|
|
|
strbuf_addstr(&buf, " ");
|
2010-03-07 22:46:46 +00:00
|
|
|
strbuf_addstr(&buf, extra_cc.items[i].string);
|
|
|
|
if (i + 1 < extra_cc.nr)
|
2008-02-19 07:40:33 +00:00
|
|
|
strbuf_addch(&buf, ',');
|
|
|
|
strbuf_addch(&buf, '\n');
|
|
|
|
}
|
|
|
|
|
2022-04-13 20:01:33 +00:00
|
|
|
rev.extra_headers = to_free = strbuf_detach(&buf, NULL);
|
2008-02-19 07:40:33 +00:00
|
|
|
|
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 07:08:22 +00:00
|
|
|
if (from) {
|
|
|
|
if (split_ident_line(&rev.from_ident, from, strlen(from)))
|
|
|
|
die(_("invalid ident line: %s"), from);
|
|
|
|
}
|
|
|
|
|
2006-05-26 18:30:49 +00:00
|
|
|
if (start_number < 0)
|
2006-05-25 21:55:11 +00:00
|
|
|
start_number = 1;
|
2009-05-09 08:12:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If numbered is set solely due to format.numbered in config,
|
|
|
|
* and it would conflict with --keep-subject (-k) from the
|
|
|
|
* command line, reset "numbered".
|
|
|
|
*/
|
|
|
|
if (numbered && keep_subject && !numbered_cmdline_opt)
|
|
|
|
numbered = 0;
|
|
|
|
|
2006-05-28 16:23:29 +00:00
|
|
|
if (numbered && keep_subject)
|
2022-01-05 20:02:14 +00:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
|
2007-04-11 23:58:07 +00:00
|
|
|
if (keep_subject && subject_prefix)
|
2022-01-05 20:02:14 +00:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
|
2011-05-26 22:28:17 +00:00
|
|
|
rev.preserve_subject = keep_subject;
|
2006-05-05 02:31:29 +00:00
|
|
|
|
2010-03-09 06:58:09 +00:00
|
|
|
argc = setup_revisions(argc, argv, &rev, &s_r_opt);
|
2006-05-05 01:33:32 +00:00
|
|
|
if (argc > 1)
|
2018-07-21 07:49:19 +00:00
|
|
|
die(_("unrecognized argument: %s"), argv[1]);
|
2006-05-04 23:16:40 +00:00
|
|
|
|
2009-11-07 09:51:56 +00:00
|
|
|
if (rev.diffopt.output_format & DIFF_FORMAT_NAME)
|
2011-02-22 23:41:58 +00:00
|
|
|
die(_("--name-only does not make sense"));
|
2009-11-07 09:51:56 +00:00
|
|
|
if (rev.diffopt.output_format & DIFF_FORMAT_NAME_STATUS)
|
2011-02-22 23:41:58 +00:00
|
|
|
die(_("--name-status does not make sense"));
|
2009-11-07 09:51:56 +00:00
|
|
|
if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF)
|
2011-02-22 23:41:58 +00:00
|
|
|
die(_("--check does not make sense"));
|
show, log: provide a --remerge-diff capability
When this option is specified, we remerge all (two parent) merge commits
and diff the actual merge commit to the automatically created version,
in order to show how users removed conflict markers, resolved the
different conflict versions, and potentially added new changes outside
of conflict regions in order to resolve semantic merge problems (or,
possibly, just to hide other random changes).
This capability works by creating a temporary object directory and
marking it as the primary object store. This makes it so that any blobs
or trees created during the automatic merge are easily removable
afterwards by just deleting all objects from the temporary object
directory.
There are a few ways that this implementation is suboptimal:
* `log --remerge-diff` becomes slow, because the temporary object
directory can fill with many loose objects while running
* the log output can be muddied with misplaced "warning: cannot merge
binary files" messages, since ll-merge.c unconditionally writes those
messages to stderr while running instead of allowing callers to
manage them.
* important conflict and warning messages are simply dropped; thus for
conflicts like modify/delete or rename/rename or file/directory which
are not representable with content conflict markers, there may be no
way for a user of --remerge-diff to know that there had been a
conflict which was resolved (and which possibly motivated other
changes in the merge commit).
* when fixing the previous issue, note that some unimportant conflict
and warning messages might start being included. We should instead
make sure these remain dropped.
Subsequent commits will address these issues.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-02 02:37:28 +00:00
|
|
|
if (rev.remerge_diff)
|
|
|
|
die(_("--remerge-diff does not make sense"));
|
2009-11-07 09:51:56 +00:00
|
|
|
|
|
|
|
if (!use_patch_format &&
|
|
|
|
(!rev.diffopt.output_format ||
|
|
|
|
rev.diffopt.output_format == DIFF_FORMAT_PATCH))
|
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY;
|
2018-02-01 12:47:50 +00:00
|
|
|
if (!rev.diffopt.stat_width)
|
|
|
|
rev.diffopt.stat_width = MAIL_DEFAULT_WRAP;
|
2009-11-07 09:51:56 +00:00
|
|
|
|
|
|
|
/* Always generate a patch */
|
|
|
|
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
|
2006-06-24 17:24:14 +00:00
|
|
|
|
2015-12-15 01:52:04 +00:00
|
|
|
rev.zero_commit = zero_commit;
|
format-patch: make output filename configurable
For the past 15 years, we've used the hardcoded 64 as the length
limit of the filename of the output from the "git format-patch"
command. Since the value is shorter than the 80-column terminal, it
could grow without line wrapping a bit. At the same time, since the
value is longer than half of the 80-column terminal, we could fit
two or more of them in "ls" output on such a terminal if we allowed
to lower it.
Introduce a new command line option --filename-max-length=<n> and a
new configuration variable format.filenameMaxLength to override the
hardcoded default.
While we are at it, remove a check that the name of output directory
does not exceed PATH_MAX---this check is pointless in that by the
time control reaches the function, the caller would already have
done an equivalent of "mkdir -p", so if the system does not like an
overly long directory name, the control wouldn't have reached here,
and otherwise, we know that the system allowed the output directory
to exist. In the worst case, we will get an error when we try to
open the output file and handle the error correctly anyway.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-06 21:56:24 +00:00
|
|
|
rev.patch_name_max = fmt_patch_name_max;
|
2015-12-15 01:52:04 +00:00
|
|
|
|
2017-10-31 18:19:11 +00:00
|
|
|
if (!rev.diffopt.flags.text && !no_binary_diff)
|
|
|
|
rev.diffopt.flags.binary = 1;
|
2007-01-17 22:32:52 +00:00
|
|
|
|
2010-03-12 17:04:26 +00:00
|
|
|
if (rev.show_notes)
|
2019-12-09 13:10:39 +00:00
|
|
|
load_display_notes(&rev.notes_opt);
|
2010-03-12 17:04:26 +00:00
|
|
|
|
2022-01-31 22:07:46 +00:00
|
|
|
die_for_incompatible_opt3(use_stdout, "--stdout",
|
|
|
|
rev.diffopt.close_file, "--output",
|
|
|
|
!!output_directory, "--output-directory");
|
2016-01-13 13:20:11 +00:00
|
|
|
|
2022-12-22 20:16:19 +00:00
|
|
|
if (use_stdout && stdout_mboxrd)
|
|
|
|
rev.commit_format = CMIT_FMT_MBOXRD;
|
|
|
|
|
2020-11-04 19:28:31 +00:00
|
|
|
if (use_stdout) {
|
2010-11-23 03:16:30 +00:00
|
|
|
setup_pager();
|
2022-04-30 10:32:44 +00:00
|
|
|
} else if (!rev.diffopt.close_file) {
|
2019-10-11 08:36:41 +00:00
|
|
|
int saved;
|
2020-11-04 19:28:31 +00:00
|
|
|
|
|
|
|
if (!output_directory)
|
|
|
|
output_directory = config_output_directory;
|
|
|
|
output_directory = set_outdir(prefix, output_directory);
|
|
|
|
|
format-patch: explicitly switch off color when writing to files
The --color=auto handling is done by seeing if file descriptor 1
(the standard output) is connected to a terminal. format-patch
used freopen() to reuse the standard output stream even when sending
its output to an on-disk file, and this check is appropriate.
In the next step, however, we will stop reusing "FILE *stdout", and
instead start using arbitrary file descriptor obtained by doing an
fopen(3) ourselves. The check --color=auto does will become useless,
as we no longer are writing to the standard output stream.
But then, we do not need to guess to begin with. As argued in the commit
message of 7787570c (format-patch: ignore ui.color, 2011-09-13), we do not
allow the ui.color setting to affect format-patch's output. The only time,
therefore, that we allow color sequences to be written to the output files
is when the user specified the --color=always command-line option explicitly.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-22 15:01:54 +00:00
|
|
|
if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
|
|
|
|
rev.diffopt.use_color = GIT_COLOR_NEVER;
|
2019-10-11 08:36:41 +00:00
|
|
|
/*
|
|
|
|
* We consider <outdir> as 'outside of gitdir', therefore avoid
|
|
|
|
* applying adjust_shared_perm in s-c-l-d.
|
|
|
|
*/
|
|
|
|
saved = get_shared_repository();
|
|
|
|
set_shared_repository(0);
|
|
|
|
switch (safe_create_leading_directories_const(output_directory)) {
|
|
|
|
case SCLD_OK:
|
|
|
|
case SCLD_EXISTS:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
die(_("could not create leading directories "
|
|
|
|
"of '%s'"), output_directory);
|
|
|
|
}
|
|
|
|
set_shared_repository(saved);
|
2006-06-06 15:46:23 +00:00
|
|
|
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
|
2019-02-22 18:24:07 +00:00
|
|
|
die_errno(_("could not create directory '%s'"),
|
2009-06-27 15:58:47 +00:00
|
|
|
output_directory);
|
2006-06-06 15:46:23 +00:00
|
|
|
}
|
|
|
|
|
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 00:42:35 +00:00
|
|
|
if (rev.pending.nr == 1) {
|
2013-04-07 17:46:21 +00:00
|
|
|
int check_head = 0;
|
|
|
|
|
2007-08-28 07:38:48 +00:00
|
|
|
if (rev.max_count < 0 && !rev.show_root_diff) {
|
|
|
|
/*
|
|
|
|
* This is traditional behaviour of "git format-patch
|
|
|
|
* origin" that prepares what the origin side still
|
|
|
|
* does not have.
|
|
|
|
*/
|
2007-01-17 21:35:13 +00:00
|
|
|
rev.pending.objects[0].item->flags |= UNINTERESTING;
|
2007-12-11 18:09:04 +00:00
|
|
|
add_head_to_pending(&rev);
|
2013-04-07 17:46:21 +00:00
|
|
|
check_head = 1;
|
2007-01-17 21:35:13 +00:00
|
|
|
}
|
2007-08-28 07:38:48 +00:00
|
|
|
/*
|
|
|
|
* Otherwise, it is "format-patch -22 HEAD", and/or
|
|
|
|
* "format-patch --root HEAD". The user wants
|
|
|
|
* get_revision() to do the usual traversal.
|
2007-01-17 21:35:13 +00:00
|
|
|
*/
|
2013-04-07 17:46:21 +00:00
|
|
|
|
|
|
|
if (!strcmp(rev.pending.objects[0].name, "HEAD"))
|
|
|
|
check_head = 1;
|
|
|
|
|
|
|
|
if (check_head) {
|
2014-06-18 19:48:29 +00:00
|
|
|
const char *ref, *v;
|
2014-07-15 19:59:36 +00:00
|
|
|
ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
|
2017-09-23 09:45:04 +00:00
|
|
|
NULL, NULL);
|
2014-06-18 19:48:29 +00:00
|
|
|
if (ref && skip_prefix(ref, "refs/heads/", &v))
|
|
|
|
branch_name = xstrdup(v);
|
2013-04-07 17:46:21 +00:00
|
|
|
else
|
|
|
|
branch_name = xstrdup(""); /* no branch */
|
|
|
|
}
|
2006-05-06 20:56:38 +00:00
|
|
|
}
|
2009-01-10 20:41:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We cannot move this anywhere earlier because we do want to
|
2010-02-04 05:23:18 +00:00
|
|
|
* know if --root was given explicitly from the command line.
|
2009-01-10 20:41:33 +00:00
|
|
|
*/
|
|
|
|
rev.show_root_diff = 1;
|
|
|
|
|
2010-03-30 02:46:38 +00:00
|
|
|
if (ignore_if_in_upstream) {
|
|
|
|
/* Don't say anything if head and upstream are the same. */
|
|
|
|
if (rev.pending.nr == 2) {
|
|
|
|
struct object_array_entry *o = rev.pending.objects;
|
convert "oidcmp() == 0" to oideq()
Using the more restrictive oideq() should, in the long run,
give the compiler more opportunities to optimize these
callsites. For now, this conversion should be a complete
noop with respect to the generated code.
The result is also perhaps a little more readable, as it
avoids the "zero is equal" idiom. Since it's so prevalent in
C, I think seasoned programmers tend not to even notice it
anymore, but it can sometimes make for awkward double
negations (e.g., we can drop a few !!oidcmp() instances
here).
This patch was generated almost entirely by the included
coccinelle patch. This mechanical conversion should be
completely safe, because we check explicitly for cases where
oidcmp() is compared to 0, which is what oideq() is doing
under the hood. Note that we don't have to catch "!oidcmp()"
separately; coccinelle's standard isomorphisms make sure the
two are treated equivalently.
I say "almost" because I did hand-edit the coccinelle output
to fix up a few style violations (it mostly keeps the
original formatting, but sometimes unwraps long lines).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-28 21:22:40 +00:00
|
|
|
if (oideq(&o[0].item->oid, &o[1].item->oid))
|
2018-07-22 09:57:05 +00:00
|
|
|
goto done;
|
2010-03-30 02:46:38 +00:00
|
|
|
}
|
2012-07-27 17:21:38 +00:00
|
|
|
get_patch_ids(&rev, &ids);
|
2010-03-30 02:46:38 +00:00
|
|
|
}
|
2006-06-25 01:52:01 +00:00
|
|
|
|
2008-02-18 07:31:56 +00:00
|
|
|
if (prepare_revision_walk(&rev))
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("revision walk setup failed"));
|
2008-02-25 23:24:17 +00:00
|
|
|
rev.boundary = 1;
|
2006-04-21 20:19:58 +00:00
|
|
|
while ((commit = get_revision(&rev)) != NULL) {
|
2008-02-25 23:24:17 +00:00
|
|
|
if (commit->object.flags & BOUNDARY) {
|
|
|
|
boundary_count++;
|
|
|
|
origin = (boundary_count == 1) ? commit : NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-08-20 22:51:45 +00:00
|
|
|
if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))
|
2006-06-25 01:52:01 +00:00
|
|
|
continue;
|
|
|
|
|
2006-04-21 20:19:58 +00:00
|
|
|
nr++;
|
2014-09-16 18:56:57 +00:00
|
|
|
REALLOC_ARRAY(list, nr);
|
2006-04-21 20:19:58 +00:00
|
|
|
list[nr - 1] = commit;
|
|
|
|
}
|
2013-04-07 17:46:20 +00:00
|
|
|
if (nr == 0)
|
|
|
|
/* nothing to do */
|
2018-07-22 09:57:05 +00:00
|
|
|
goto done;
|
2006-05-04 23:16:40 +00:00
|
|
|
total = nr;
|
2013-04-07 17:46:23 +00:00
|
|
|
if (cover_letter == -1) {
|
|
|
|
if (config_cover_letter == COVER_AUTO)
|
|
|
|
cover_letter = (total > 1);
|
|
|
|
else
|
|
|
|
cover_letter = (config_cover_letter == COVER_ON);
|
|
|
|
}
|
2016-08-23 22:45:50 +00:00
|
|
|
if (!keep_subject && auto_number && (total > 1 || cover_letter))
|
|
|
|
numbered = 1;
|
|
|
|
if (numbered)
|
|
|
|
rev.total = total + start_number - 1;
|
2013-04-07 17:46:23 +00:00
|
|
|
|
2018-07-22 09:57:05 +00:00
|
|
|
if (idiff_prev.nr) {
|
2018-07-22 09:57:09 +00:00
|
|
|
if (!cover_letter && total != 1)
|
|
|
|
die(_("--interdiff requires --cover-letter or single patch"));
|
2018-07-22 09:57:05 +00:00
|
|
|
rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];
|
|
|
|
rev.idiff_oid2 = get_commit_tree_oid(list[0]);
|
2018-07-22 09:57:06 +00:00
|
|
|
rev.idiff_title = diff_title(&idiff_title, reroll_count,
|
|
|
|
_("Interdiff:"),
|
|
|
|
_("Interdiff against v%d:"));
|
2018-07-22 09:57:05 +00:00
|
|
|
}
|
|
|
|
|
2018-07-22 09:57:16 +00:00
|
|
|
if (creation_factor < 0)
|
|
|
|
creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
|
|
|
|
else if (!rdiff_prev)
|
2022-01-05 20:02:19 +00:00
|
|
|
die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
|
2018-07-22 09:57:16 +00:00
|
|
|
|
2018-07-22 09:57:13 +00:00
|
|
|
if (rdiff_prev) {
|
2018-07-22 09:57:17 +00:00
|
|
|
if (!cover_letter && total != 1)
|
|
|
|
die(_("--range-diff requires --cover-letter or single patch"));
|
2018-07-22 09:57:13 +00:00
|
|
|
|
2018-07-22 09:57:14 +00:00
|
|
|
infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,
|
|
|
|
origin, list[0]);
|
2018-07-22 09:57:13 +00:00
|
|
|
rev.rdiff1 = rdiff1.buf;
|
|
|
|
rev.rdiff2 = rdiff2.buf;
|
2018-07-22 09:57:16 +00:00
|
|
|
rev.creation_factor = creation_factor;
|
2018-07-22 09:57:15 +00:00
|
|
|
rev.rdiff_title = diff_title(&rdiff_title, reroll_count,
|
|
|
|
_("Range-diff:"),
|
|
|
|
_("Range-diff against v%d:"));
|
2018-07-22 09:57:13 +00:00
|
|
|
}
|
|
|
|
|
2014-05-24 04:08:14 +00:00
|
|
|
if (!signature) {
|
|
|
|
; /* --no-signature inhibits all signatures */
|
|
|
|
} else if (signature && signature != git_version_string) {
|
|
|
|
; /* non-default signature already set */
|
|
|
|
} else if (signature_file) {
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (strbuf_read_file(&buf, signature_file, 128) < 0)
|
|
|
|
die_errno(_("unable to read signature file '%s'"), signature_file);
|
|
|
|
signature = strbuf_detach(&buf, NULL);
|
|
|
|
}
|
|
|
|
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
memset(&bases, 0, sizeof(bases));
|
format-patch: teach format.useAutoBase "whenAble" option
The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.
This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:
$ git format-patch -1 <an old commit>
fatal: base commit shouldn't be in revision list
This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).
We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.
Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.
In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.
Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.
This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.
Add tests to cover the new mode of operation for --base.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-10-01 21:46:53 +00:00
|
|
|
base = get_base_commit(base_commit, list, nr);
|
|
|
|
if (base) {
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
reset_revision_walk();
|
2018-06-04 15:05:43 +00:00
|
|
|
clear_object_flags(UNINTERESTING);
|
format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree
the patch series applies to. Teach git format-patch a '--base' option
to record the base tree info and append it at the end of the first
message (either the cover letter or the first patch in the series).
The base tree info consists of the "base commit", which is a well-known
commit that is part of the stable part of the project history everybody
else works off of, and zero or more "prerequisite patches", which are
well-known patches in flight that is not yet part of the "base commit"
that need to be applied on top of "base commit" in topological order
before the patches can be applied.
The "base commit" is shown as "base-commit: " followed by the 40-hex of
the commit object name. A "prerequisite patch" is shown as
"prerequisite-patch-id: " followed by the 40-hex "patch id", which can
be obtained by passing the patch through the "git patch-id --stable"
command.
Imagine that on top of the public commit P, you applied well-known
patches X, Y and Z from somebody else, and then built your three-patch
series A, B, C, the history would be like:
---P---X---Y---Z---A---B---C
With "git format-patch --base=P -3 C" (or variants thereof, e.g. with
"--cover-letter" of using "Z..C" instead of "-3 C" to specify the
range), the base tree information block is shown at the end of the
first message the command outputs (either the first patch, or the
cover letter), like this:
base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-26 07:51:22 +00:00
|
|
|
prepare_bases(&bases, base, list, nr);
|
|
|
|
}
|
|
|
|
|
2022-04-13 20:01:32 +00:00
|
|
|
if (in_reply_to || thread || cover_letter) {
|
|
|
|
rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids));
|
|
|
|
string_list_init_nodup(rev.ref_message_ids);
|
|
|
|
}
|
2009-02-19 21:26:31 +00:00
|
|
|
if (in_reply_to) {
|
|
|
|
const char *msgid = clean_message_id(in_reply_to);
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(rev.ref_message_ids, msgid);
|
2009-02-19 21:26:31 +00:00
|
|
|
}
|
2012-12-22 05:27:38 +00:00
|
|
|
rev.numbered_files = just_numbers;
|
2009-03-23 02:14:05 +00:00
|
|
|
rev.patch_suffix = fmt_patch_suffix;
|
2008-02-19 03:56:13 +00:00
|
|
|
if (cover_letter) {
|
|
|
|
if (thread)
|
|
|
|
gen_message_id(&rev, "cover");
|
2020-11-04 19:28:34 +00:00
|
|
|
make_cover_letter(&rev, !!output_directory,
|
2013-04-07 17:46:24 +00:00
|
|
|
origin, nr, list, branch_name, quiet);
|
2016-06-22 15:01:59 +00:00
|
|
|
print_bases(&bases, rev.diffopt.file);
|
2016-09-08 01:12:01 +00:00
|
|
|
print_signature(rev.diffopt.file);
|
2008-02-19 03:56:13 +00:00
|
|
|
total++;
|
|
|
|
start_number--;
|
2018-07-22 09:57:17 +00:00
|
|
|
/* interdiff/range-diff in cover-letter; omit from patches */
|
2018-07-22 09:57:09 +00:00
|
|
|
rev.idiff_oid1 = NULL;
|
2018-07-22 09:57:17 +00:00
|
|
|
rev.rdiff1 = NULL;
|
2008-02-19 03:56:13 +00:00
|
|
|
}
|
2013-02-12 10:17:38 +00:00
|
|
|
rev.add_signoff = do_signoff;
|
2017-08-10 18:32:55 +00:00
|
|
|
|
|
|
|
if (show_progress)
|
2017-08-24 17:20:02 +00:00
|
|
|
progress = start_delayed_progress(_("Generating patches"), total);
|
2006-04-21 20:19:58 +00:00
|
|
|
while (0 <= --nr) {
|
|
|
|
int shown;
|
2017-08-10 18:32:55 +00:00
|
|
|
display_progress(progress, total - nr);
|
2006-04-21 20:19:58 +00:00
|
|
|
commit = list[nr];
|
2006-05-26 18:30:49 +00:00
|
|
|
rev.nr = total - nr + (start_number - 1);
|
2006-07-15 00:48:51 +00:00
|
|
|
/* Make the second and subsequent mails replies to the first */
|
2006-07-15 00:49:04 +00:00
|
|
|
if (thread) {
|
2008-02-19 03:56:13 +00:00
|
|
|
/* Have we already had a message ID? */
|
2008-02-19 03:56:06 +00:00
|
|
|
if (rev.message_id) {
|
2008-02-19 03:56:13 +00:00
|
|
|
/*
|
2009-02-19 21:26:33 +00:00
|
|
|
* For deep threading: make every mail
|
|
|
|
* a reply to the previous one, no
|
|
|
|
* matter what other options are set.
|
|
|
|
*
|
|
|
|
* For shallow threading:
|
|
|
|
*
|
2009-02-19 21:26:32 +00:00
|
|
|
* Without --cover-letter and
|
|
|
|
* --in-reply-to, make every mail a
|
|
|
|
* reply to the one before.
|
|
|
|
*
|
|
|
|
* With --in-reply-to but no
|
|
|
|
* --cover-letter, make every mail a
|
|
|
|
* reply to the <reply-to>.
|
|
|
|
*
|
|
|
|
* With --cover-letter, make every
|
|
|
|
* mail but the cover letter a reply
|
|
|
|
* to the cover letter. The cover
|
|
|
|
* letter is a reply to the
|
|
|
|
* --in-reply-to, if specified.
|
2008-02-19 03:56:13 +00:00
|
|
|
*/
|
2009-02-19 21:26:33 +00:00
|
|
|
if (thread == THREAD_SHALLOW
|
|
|
|
&& rev.ref_message_ids->nr > 0
|
2009-02-19 21:26:32 +00:00
|
|
|
&& (!cover_letter || rev.nr > 1))
|
2008-02-19 03:56:06 +00:00
|
|
|
free(rev.message_id);
|
|
|
|
else
|
2010-06-25 23:41:38 +00:00
|
|
|
string_list_append(rev.ref_message_ids,
|
|
|
|
rev.message_id);
|
2006-07-15 00:49:04 +00:00
|
|
|
}
|
2015-11-10 02:22:28 +00:00
|
|
|
gen_message_id(&rev, oid_to_hex(&commit->object.oid));
|
2006-07-15 00:48:51 +00:00
|
|
|
}
|
2009-03-23 02:14:02 +00:00
|
|
|
|
2020-11-04 19:28:34 +00:00
|
|
|
if (output_directory &&
|
2016-06-22 15:01:59 +00:00
|
|
|
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("failed to create output files"));
|
2006-04-21 20:19:58 +00:00
|
|
|
shown = log_tree_commit(&rev, commit);
|
2018-12-15 00:09:40 +00:00
|
|
|
free_commit_buffer(the_repository->parsed_objects,
|
|
|
|
commit);
|
2006-05-26 18:30:49 +00:00
|
|
|
|
|
|
|
/* We put one extra blank line between formatted
|
|
|
|
* patches and this flag is used by log-tree code
|
|
|
|
* to see if it needs to emit a LF before showing
|
|
|
|
* the log; when using one file per patch, we do
|
|
|
|
* not want the extra blank line.
|
|
|
|
*/
|
2020-11-04 19:28:34 +00:00
|
|
|
if (output_directory)
|
2006-05-26 18:30:49 +00:00
|
|
|
rev.shown_one = 0;
|
2006-05-20 13:40:29 +00:00
|
|
|
if (shown) {
|
2016-09-08 01:12:01 +00:00
|
|
|
print_bases(&bases, rev.diffopt.file);
|
2006-05-20 13:40:29 +00:00
|
|
|
if (rev.mime_boundary)
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
|
2006-05-20 13:40:29 +00:00
|
|
|
mime_boundary_leader,
|
|
|
|
rev.mime_boundary);
|
|
|
|
else
|
2016-06-22 15:01:59 +00:00
|
|
|
print_signature(rev.diffopt.file);
|
2006-05-20 13:40:29 +00:00
|
|
|
}
|
2020-11-04 19:28:34 +00:00
|
|
|
if (output_directory)
|
2016-06-22 15:01:59 +00:00
|
|
|
fclose(rev.diffopt.file);
|
2006-04-21 20:19:58 +00:00
|
|
|
}
|
2017-08-10 18:32:55 +00:00
|
|
|
stop_progress(&progress);
|
2006-04-21 20:19:58 +00:00
|
|
|
free(list);
|
2011-09-22 03:32:28 +00:00
|
|
|
free(branch_name);
|
2010-03-07 22:46:46 +00:00
|
|
|
string_list_clear(&extra_to, 0);
|
|
|
|
string_list_clear(&extra_cc, 0);
|
|
|
|
string_list_clear(&extra_hdr, 0);
|
2007-04-10 00:01:27 +00:00
|
|
|
if (ignore_if_in_upstream)
|
|
|
|
free_patch_ids(&ids);
|
2018-07-22 09:57:05 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
oid_array_clear(&idiff_prev);
|
2018-07-22 09:57:06 +00:00
|
|
|
strbuf_release(&idiff_title);
|
2018-07-22 09:57:13 +00:00
|
|
|
strbuf_release(&rdiff1);
|
|
|
|
strbuf_release(&rdiff2);
|
2018-07-22 09:57:15 +00:00
|
|
|
strbuf_release(&rdiff_title);
|
2022-04-13 20:01:33 +00:00
|
|
|
free(to_free);
|
|
|
|
if (rev.ref_message_ids)
|
|
|
|
string_list_clear(rev.ref_message_ids, 0);
|
|
|
|
free(rev.ref_message_ids);
|
revisions API users: use release_revisions() in builtin/log.c
In preparation for having the "log" family of functions make wider use
of release_revisions() let's have them call it just before
exiting. This changes the "log", "whatchanged", "show",
"format-patch", etc. commands, all of which live in this file.
The release_revisions() API still only frees the "pending" member, but
will learn to release more members of "struct rev_info" in subsequent
commits.
In the case of "format-patch" revert the addition of UNLEAK() in
dee839a2633 (format-patch: mark rev_info with UNLEAK, 2021-12-16),
which will cause several tests that previously passed under
"TEST_PASSES_SANITIZE_LEAK=true" to start failing.
In subsequent commits we'll now be able to use those tests to check
whether that part of the API is really leaking memory, and will fix
all of those memory leaks. Removing the UNLEAK() allows us to make
incremental progress in that direction. See [1] for further details
about this approach.
Note that the release_revisions() will not be sufficient to deal with
the code in cmd_show() added in 5d7eeee2ac6 (git-show: grok blobs,
trees and tags, too, 2006-12-14) which clobbers the "pending" array in
the case of "OBJ_COMMIT". That will need to be dealt with by some
future follow-up work.
1. https://lore.kernel.org/git/220218.861r00ib86.gmgdl@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 20:01:42 +00:00
|
|
|
return cmd_log_deinit(0, &rev);
|
2006-04-21 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
2006-10-23 23:01:57 +00:00
|
|
|
static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
|
|
|
|
{
|
2016-09-05 20:07:55 +00:00
|
|
|
struct object_id oid;
|
|
|
|
if (get_oid(arg, &oid) == 0) {
|
2018-06-29 01:21:58 +00:00
|
|
|
struct commit *commit = lookup_commit_reference(the_repository,
|
|
|
|
&oid);
|
2006-10-23 23:01:57 +00:00
|
|
|
if (commit) {
|
|
|
|
commit->object.flags |= flags;
|
|
|
|
add_pending_object(revs, &commit->object, arg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-03-20 18:55:27 +00:00
|
|
|
static const char * const cherry_usage[] = {
|
2012-08-20 12:32:00 +00:00
|
|
|
N_("git cherry [-v] [<upstream> [<head> [<limit>]]]"),
|
2010-03-20 18:55:27 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2011-03-16 07:12:48 +00:00
|
|
|
static void print_commit(char sign, struct commit *commit, int verbose,
|
2016-06-22 15:01:59 +00:00
|
|
|
int abbrev, FILE *file)
|
2011-03-16 07:12:48 +00:00
|
|
|
{
|
|
|
|
if (!verbose) {
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(file, "%c %s\n", sign,
|
2018-03-12 02:27:30 +00:00
|
|
|
find_unique_abbrev(&commit->object.oid, abbrev));
|
2011-03-16 07:12:48 +00:00
|
|
|
} else {
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2011-05-31 19:19:11 +00:00
|
|
|
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
|
2016-06-22 15:01:59 +00:00
|
|
|
fprintf(file, "%c %s %s\n", sign,
|
2018-03-12 02:27:30 +00:00
|
|
|
find_unique_abbrev(&commit->object.oid, abbrev),
|
2011-03-16 07:12:48 +00:00
|
|
|
buf.buf);
|
|
|
|
strbuf_release(&buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-23 23:01:57 +00:00
|
|
|
int cmd_cherry(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
|
|
|
struct rev_info revs;
|
2007-04-10 00:01:27 +00:00
|
|
|
struct patch_ids ids;
|
2006-10-23 23:01:57 +00:00
|
|
|
struct commit *commit;
|
|
|
|
struct commit_list *list = NULL;
|
2008-12-29 17:45:20 +00:00
|
|
|
struct branch *current_branch;
|
2006-10-23 23:01:57 +00:00
|
|
|
const char *upstream;
|
|
|
|
const char *head = "HEAD";
|
|
|
|
const char *limit = NULL;
|
2010-03-20 18:55:27 +00:00
|
|
|
int verbose = 0, abbrev = 0;
|
2006-10-23 23:01:57 +00:00
|
|
|
|
2010-03-20 18:55:27 +00:00
|
|
|
struct option options[] = {
|
|
|
|
OPT__ABBREV(&abbrev),
|
2012-08-20 12:32:00 +00:00
|
|
|
OPT__VERBOSE(&verbose, N_("be verbose")),
|
2010-03-20 18:55:27 +00:00
|
|
|
OPT_END()
|
|
|
|
};
|
2006-10-23 23:01:57 +00:00
|
|
|
|
2010-03-20 18:55:27 +00:00
|
|
|
argc = parse_options(argc, argv, prefix, options, cherry_usage, 0);
|
2009-11-09 15:04:43 +00:00
|
|
|
|
2006-10-23 23:01:57 +00:00
|
|
|
switch (argc) {
|
|
|
|
case 3:
|
2010-03-20 18:55:27 +00:00
|
|
|
limit = argv[2];
|
2006-10-23 23:01:57 +00:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case 2:
|
2010-03-20 18:55:27 +00:00
|
|
|
head = argv[1];
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case 1:
|
|
|
|
upstream = argv[0];
|
2006-10-23 23:01:57 +00:00
|
|
|
break;
|
|
|
|
default:
|
2008-12-29 17:45:20 +00:00
|
|
|
current_branch = branch_get(NULL);
|
2015-05-21 04:45:32 +00:00
|
|
|
upstream = branch_get_upstream(current_branch, NULL);
|
2015-05-21 04:45:28 +00:00
|
|
|
if (!upstream) {
|
2011-02-22 23:41:57 +00:00
|
|
|
fprintf(stderr, _("Could not find a tracked"
|
2008-12-29 17:45:20 +00:00
|
|
|
" remote branch, please"
|
2011-02-22 23:41:57 +00:00
|
|
|
" specify <upstream> manually.\n"));
|
2010-03-20 18:55:27 +00:00
|
|
|
usage_with_options(cherry_usage, options);
|
2008-12-29 17:45:20 +00:00
|
|
|
}
|
2006-10-23 23:01:57 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, &revs, prefix);
|
2012-07-29 23:25:36 +00:00
|
|
|
revs.max_parents = 1;
|
2006-10-23 23:01:57 +00:00
|
|
|
|
|
|
|
if (add_pending_commit(head, &revs, 0))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("unknown commit %s"), head);
|
2006-10-23 23:01:57 +00:00
|
|
|
if (add_pending_commit(upstream, &revs, UNINTERESTING))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("unknown commit %s"), upstream);
|
2006-10-23 23:01:57 +00:00
|
|
|
|
|
|
|
/* Don't say anything if head and upstream are the same. */
|
|
|
|
if (revs.pending.nr == 2) {
|
|
|
|
struct object_array_entry *o = revs.pending.objects;
|
convert "oidcmp() == 0" to oideq()
Using the more restrictive oideq() should, in the long run,
give the compiler more opportunities to optimize these
callsites. For now, this conversion should be a complete
noop with respect to the generated code.
The result is also perhaps a little more readable, as it
avoids the "zero is equal" idiom. Since it's so prevalent in
C, I think seasoned programmers tend not to even notice it
anymore, but it can sometimes make for awkward double
negations (e.g., we can drop a few !!oidcmp() instances
here).
This patch was generated almost entirely by the included
coccinelle patch. This mechanical conversion should be
completely safe, because we check explicitly for cases where
oidcmp() is compared to 0, which is what oideq() is doing
under the hood. Note that we don't have to catch "!oidcmp()"
separately; coccinelle's standard isomorphisms make sure the
two are treated equivalently.
I say "almost" because I did hand-edit the coccinelle output
to fix up a few style violations (it mostly keeps the
original formatting, but sometimes unwraps long lines).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-28 21:22:40 +00:00
|
|
|
if (oideq(&o[0].item->oid, &o[1].item->oid))
|
2006-10-23 23:01:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-27 17:21:38 +00:00
|
|
|
get_patch_ids(&revs, &ids);
|
2006-10-23 23:01:57 +00:00
|
|
|
|
|
|
|
if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
|
2019-02-22 18:24:07 +00:00
|
|
|
die(_("unknown commit %s"), limit);
|
2006-10-23 23:01:57 +00:00
|
|
|
|
|
|
|
/* reverse the list of commits */
|
2008-02-18 07:31:56 +00:00
|
|
|
if (prepare_revision_walk(&revs))
|
2011-02-22 23:41:57 +00:00
|
|
|
die(_("revision walk setup failed"));
|
2006-10-23 23:01:57 +00:00
|
|
|
while ((commit = get_revision(&revs)) != NULL) {
|
|
|
|
commit_list_insert(commit, &list);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (list) {
|
|
|
|
char sign = '+';
|
|
|
|
|
|
|
|
commit = list->item;
|
2007-04-10 00:01:27 +00:00
|
|
|
if (has_commit_patch_id(commit, &ids))
|
2006-10-23 23:01:57 +00:00
|
|
|
sign = '-';
|
2016-06-22 15:01:59 +00:00
|
|
|
print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
|
2006-10-23 23:01:57 +00:00
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
2007-04-10 00:01:27 +00:00
|
|
|
free_patch_ids(&ids);
|
2006-10-23 23:01:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|