2006-04-21 17:27:34 +00:00
|
|
|
/*
|
|
|
|
* Builtin "git log" and related commands (show, whatchanged)
|
|
|
|
*
|
|
|
|
* (C) Copyright 2006 Linus Torvalds
|
|
|
|
* 2006 Junio Hamano
|
|
|
|
*/
|
2019-01-24 08:29:12 +00:00
|
|
|
#define USE_THE_INDEX_COMPATIBILITY_MACROS
|
2006-04-21 17:27:34 +00:00
|
|
|
#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"
|
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;
|
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;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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 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
|
|
|
static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
|
2020-04-16 14:15:49 +00:00
|
|
|
static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
|
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
|
|
|
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
|
|
|
|
struct decoration_filter decoration_filter = {&decorate_refs_include,
|
2020-04-16 14:15:49 +00:00
|
|
|
&decorate_refs_exclude,
|
|
|
|
&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"),
|
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,
|
|
|
|
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
|
|
|
|
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) {
|
|
|
|
rev->mailmap = xcalloc(1, sizeof(struct string_list));
|
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
|
|
|
|
2009-08-15 14:23:12 +00:00
|
|
|
if (decoration_style) {
|
2020-04-16 14:15:49 +00:00
|
|
|
const struct string_list *config_exclude =
|
|
|
|
repo_config_get_value_multi(the_repository,
|
|
|
|
"log.excludeDecoration");
|
|
|
|
|
|
|
|
if (config_exclude) {
|
|
|
|
struct string_list_item *item;
|
|
|
|
for_each_string_list_item(item, config_exclude)
|
|
|
|
string_list_append(&decorate_refs_exclude_config,
|
|
|
|
item->string);
|
|
|
|
}
|
|
|
|
|
2009-08-15 14:23:12 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2016-06-22 15:01:28 +00:00
|
|
|
int i = revs->early_output, close_file = revs->diffopt.close_file;
|
2007-11-04 20:12:05 +00:00
|
|
|
int show_header = 1;
|
2007-11-03 18:11:10 +00:00
|
|
|
|
2016-06-22 15:01:28 +00:00
|
|
|
revs->diffopt.close_file = 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:
|
2016-06-22 15:01:28 +00:00
|
|
|
if (close_file)
|
|
|
|
fclose(revs->diffopt.file);
|
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) {
|
|
|
|
if (close_file)
|
|
|
|
fclose(revs->diffopt.file);
|
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
|
|
|
}
|
|
|
|
|
2006-06-25 12:39:35 +00:00
|
|
|
static int cmd_log_walk(struct rev_info *rev)
|
|
|
|
{
|
|
|
|
struct commit *commit;
|
2011-01-06 21:50:06 +00:00
|
|
|
int saved_nrl = 0;
|
2016-06-22 15:01:28 +00:00
|
|
|
int saved_dcctc = 0, close_file = rev->diffopt.close_file;
|
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
|
|
|
*/
|
2016-06-22 15:01:28 +00:00
|
|
|
rev->diffopt.close_file = 0;
|
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;
|
2016-06-22 15:01:28 +00:00
|
|
|
if (close_file)
|
|
|
|
fclose(rev->diffopt.file);
|
2011-01-06 21:50:06 +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
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
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
|
|
|
|
2012-10-09 23:49:57 +00:00
|
|
|
if (grep_config(var, value, cb) < 0)
|
|
|
|
return -1;
|
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);
|
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;
|
|
|
|
return cmd_log_walk(&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;
|
|
|
|
}
|
|
|
|
|
2018-03-12 02:27:26 +00:00
|
|
|
static int show_tree_object(const struct object_id *oid,
|
2014-11-30 09:05:00 +00:00
|
|
|
struct strbuf *base,
|
2008-07-14 19:22:12 +00:00
|
|
|
const char *pathname, unsigned mode, int stage, 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;
|
2006-12-14 10:31:05 +00:00
|
|
|
struct object_array_entry *objects;
|
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;
|
2006-12-14 10:31:05 +00:00
|
|
|
int i, count, 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
|
|
|
|
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);
|
2006-04-21 17:27:34 +00:00
|
|
|
rev.diff = 1;
|
|
|
|
rev.always_show_header = 1;
|
teach log --no-walk=unsorted, which avoids sorting
When 'git log' is passed the --no-walk option, no revision walk takes
place, naturally. Perhaps somewhat surprisingly, however, the provided
revisions still get sorted by commit date. So e.g 'git log --no-walk
HEAD HEAD~1' and 'git log --no-walk HEAD~1 HEAD' give the same result
(unless the two revisions share the commit date, in which case they
will retain the order given on the command line). As the commit that
introduced --no-walk (8e64006 (Teach revision machinery about
--no-walk, 2007-07-24)) points out, the sorting is intentional, to
allow things like
git log --abbrev-commit --pretty=oneline --decorate --all --no-walk
to show all refs in order by commit date.
But there are also other cases where the sorting is not wanted, such
as
<command producing revisions in order> |
git log --oneline --no-walk --stdin
To accomodate both cases, leave the decision of whether or not to sort
up to the caller, by allowing --no-walk={sorted,unsorted}, defaulting
to 'sorted' for backward-compatibility reasons.
Signed-off-by: Martin von Zweigbergk <martinvonz@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-08-29 06:15:54 +00:00
|
|
|
rev.no_walk = REVISION_WALK_NO_WALK_SORTED;
|
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)
|
|
|
|
return cmd_log_walk(&rev);
|
|
|
|
|
2006-12-14 10:31:05 +00:00
|
|
|
count = rev.pending.nr;
|
|
|
|
objects = rev.pending.objects;
|
|
|
|
for (i = 0; i < count && !ret; i++) {
|
|
|
|
struct object *o = objects[i].item;
|
|
|
|
const char *name = objects[i].name;
|
|
|
|
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));
|
2008-12-15 08:36:56 +00:00
|
|
|
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));
|
2018-11-18 16:47:56 +00:00
|
|
|
read_tree_recursive(the_repository, (struct tree *)o, "",
|
|
|
|
0, 0, &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:
|
|
|
|
rev.pending.nr = rev.pending.alloc = 0;
|
|
|
|
rev.pending.objects = NULL;
|
|
|
|
add_object_array(o, name, &rev.pending);
|
|
|
|
ret = cmd_log_walk(&rev);
|
|
|
|
break;
|
|
|
|
default:
|
2019-02-22 18:24:07 +00:00
|
|
|
ret = error(_("unknown type: %d"), o->type);
|
2006-12-14 10:31:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(objects);
|
|
|
|
return ret;
|
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);
|
|
|
|
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
|
|
|
|
|
|
|
return cmd_log_walk(&rev);
|
|
|
|
}
|
|
|
|
|
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);
|
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);
|
2006-06-25 12:39:35 +00:00
|
|
|
return cmd_log_walk(&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;
|
|
|
|
}
|
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;
|
|
|
|
}
|
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
|
|
|
|
2017-05-03 10:16:56 +00:00
|
|
|
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
|
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;
|
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;
|
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);
|
2018-07-22 09:57:13 +00:00
|
|
|
show_range_diff(rev->rdiff1, rev->rdiff2,
|
2019-11-20 21:18:47 +00:00
|
|
|
rev->creation_factor, 1, &opts, &other_arg);
|
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;
|
2019-04-26 23:51:57 +00:00
|
|
|
if (commit_patch_id(commit, &diffopt, &oid, 0, 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
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-07-22 09:57:06 +00:00
|
|
|
static const char *diff_title(struct strbuf *sb, int reroll_count,
|
|
|
|
const char *generic, const char *rerolled)
|
|
|
|
{
|
|
|
|
if (reroll_count <= 0)
|
|
|
|
strbuf_addstr(sb, generic);
|
|
|
|
else /* RFC may be v0, so allow -v1 to diff against v0 */
|
|
|
|
strbuf_addf(sb, rerolled, reroll_count - 1);
|
|
|
|
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);
|
2020-09-08 07:16:10 +00:00
|
|
|
int prev_is_range = !!strstr(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;
|
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;
|
2012-12-22 08:21:23 +00:00
|
|
|
int reroll_count = -1;
|
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")),
|
2013-01-02 22:19:05 +00:00
|
|
|
OPT_INTEGER('v', "reroll-count", &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")),
|
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;
|
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);
|
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;
|
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,
|
2009-11-26 19:11:59 +00:00
|
|
|
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
|
|
|
|
PARSE_OPT_KEEP_DASHDASH);
|
2006-05-05 01:33:32 +00:00
|
|
|
|
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);
|
|
|
|
|
2012-12-22 08:21:23 +00:00
|
|
|
if (0 < reroll_count) {
|
|
|
|
struct strbuf sprefix = STRBUF_INIT;
|
|
|
|
strbuf_addf(&sprefix, "%s v%d",
|
|
|
|
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');
|
|
|
|
}
|
|
|
|
|
2009-06-18 17:28:43 +00:00
|
|
|
rev.extra_headers = 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)
|
2018-07-21 07:49:19 +00:00
|
|
|
die(_("-n and -k are mutually exclusive"));
|
2007-04-11 23:58:07 +00:00
|
|
|
if (keep_subject && subject_prefix)
|
2018-07-21 07:49:19 +00:00
|
|
|
die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
|
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"));
|
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
|
|
|
|
format-patch: support --output option
We've never intended to support diff's --output option in format-patch.
And until baa4adc66a (parse-options: disable option abbreviation with
PARSE_OPT_KEEP_UNKNOWN, 2019-01-27), it was impossible to trigger. We
first parse the format-patch options before handing the remainder off to
setup_revisions(). Before that commit, we'd accept "--output=foo" as an
abbreviation for "--output-directory=foo". But afterwards, we don't
check abbreviations, and --output gets passed to the diff code.
This results in nonsense behavior and bugs. The diff code will have
opened a filehandle at rev.diffopt.file, but we'll overwrite that with
our own handles that we open for each individual patch file. So the
--output file will always just be empty. But worse, the diff code also
sets rev.diffopt.close_file, so log_tree_commit() will close the
filehandle itself. And then the main loop in cmd_format_patch() will try
to close it again, resulting in a double-free.
The simplest solution would be to just disallow --output with
format-patch, as nobody ever intended it to work. However, we have
accidentally documented it (because format-patch includes diff-options).
And it does work with "git log", which writes the whole output to the
specified file. It's easy enough to make that work for format-patch,
too: it's really the same as --stdout, but pointed at a specific file.
We can detect the use of the --output option by the "close_file" flag
(note that we can't use rev.diffopt.file, since the diff setup will
otherwise set it to stdout). So we just need to unset that flag, but
don't have to do anything else. Our situation is otherwise exactly like
--stdout (note that we don't fclose() the file, but nor does the stdout
case; exiting the program takes care of that for us).
Reported-by: Johannes Postler <johannes.postler@txture.io>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-04 19:28:36 +00:00
|
|
|
if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
|
|
|
|
die(_("--stdout, --output, and --output-directory are mutually exclusive"));
|
2016-01-13 13:20:11 +00:00
|
|
|
|
2020-11-04 19:28:31 +00:00
|
|
|
if (use_stdout) {
|
2010-11-23 03:16:30 +00:00
|
|
|
setup_pager();
|
format-patch: support --output option
We've never intended to support diff's --output option in format-patch.
And until baa4adc66a (parse-options: disable option abbreviation with
PARSE_OPT_KEEP_UNKNOWN, 2019-01-27), it was impossible to trigger. We
first parse the format-patch options before handing the remainder off to
setup_revisions(). Before that commit, we'd accept "--output=foo" as an
abbreviation for "--output-directory=foo". But afterwards, we don't
check abbreviations, and --output gets passed to the diff code.
This results in nonsense behavior and bugs. The diff code will have
opened a filehandle at rev.diffopt.file, but we'll overwrite that with
our own handles that we open for each individual patch file. So the
--output file will always just be empty. But worse, the diff code also
sets rev.diffopt.close_file, so log_tree_commit() will close the
filehandle itself. And then the main loop in cmd_format_patch() will try
to close it again, resulting in a double-free.
The simplest solution would be to just disallow --output with
format-patch, as nobody ever intended it to work. However, we have
accidentally documented it (because format-patch includes diff-options).
And it does work with "git log", which writes the whole output to the
specified file. It's easy enough to make that work for format-patch,
too: it's really the same as --stdout, but pointed at a specific file.
We can detect the use of the --output option by the "close_file" flag
(note that we can't use rev.diffopt.file, since the diff setup will
otherwise set it to stdout). So we just need to unset that flag, but
don't have to do anything else. Our situation is otherwise exactly like
--stdout (note that we don't fclose() the file, but nor does the stdout
case; exiting the program takes care of that for us).
Reported-by: Johannes Postler <johannes.postler@txture.io>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-04 19:28:36 +00:00
|
|
|
} else if (rev.diffopt.close_file) {
|
|
|
|
/*
|
|
|
|
* The diff code parsed --output; it has already opened the
|
|
|
|
* file, but but we must instruct it not to close after each
|
|
|
|
* diff.
|
|
|
|
*/
|
|
|
|
rev.diffopt.close_file = 0;
|
2020-11-04 19:28:31 +00:00
|
|
|
} else {
|
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)
|
|
|
|
die(_("--creation-factor requires --range-diff"));
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-02-19 21:26:31 +00:00
|
|
|
if (in_reply_to || thread || cover_letter)
|
|
|
|
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
|
|
|
|
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);
|
2006-04-21 20:19:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|