2022-11-19 13:07:38 +00:00
|
|
|
#define USE_THE_INDEX_VARIABLE
|
2023-05-16 06:33:57 +00:00
|
|
|
#include "builtin.h"
|
2017-06-14 18:07:36 +00:00
|
|
|
#include "config.h"
|
2005-04-27 16:21:00 +00:00
|
|
|
#include "diff.h"
|
2005-06-01 15:34:23 +00:00
|
|
|
#include "commit.h"
|
2023-03-21 06:25:54 +00:00
|
|
|
#include "gettext.h"
|
2023-02-24 00:09:27 +00:00
|
|
|
#include "hex.h"
|
2006-04-09 08:11:11 +00:00
|
|
|
#include "log-tree.h"
|
2010-08-05 22:40:48 +00:00
|
|
|
#include "submodule.h"
|
2023-05-16 06:33:56 +00:00
|
|
|
#include "read-cache-ll.h"
|
2018-06-29 01:21:51 +00:00
|
|
|
#include "repository.h"
|
2023-05-16 06:33:58 +00:00
|
|
|
#include "revision.h"
|
2023-04-22 20:17:26 +00:00
|
|
|
#include "tree.h"
|
2005-04-09 20:00:54 +00:00
|
|
|
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-14 23:52:13 +00:00
|
|
|
static struct rev_info log_tree_opt;
|
2005-05-18 20:06:47 +00:00
|
|
|
|
2017-05-30 17:31:04 +00:00
|
|
|
static int diff_tree_commit_oid(const struct object_id *oid)
|
2006-02-06 07:00:41 +00:00
|
|
|
{
|
2018-06-29 01:21:58 +00:00
|
|
|
struct commit *commit = lookup_commit_reference(the_repository, oid);
|
2006-02-06 07:00:41 +00:00
|
|
|
if (!commit)
|
|
|
|
return -1;
|
2006-04-09 08:11:11 +00:00
|
|
|
return log_tree_commit(&log_tree_opt, commit);
|
2006-02-06 07:00:41 +00:00
|
|
|
}
|
|
|
|
|
2008-08-08 20:48:23 +00:00
|
|
|
/* Diff one or more commits. */
|
2017-02-21 23:47:21 +00:00
|
|
|
static int stdin_diff_commit(struct commit *commit, const char *p)
|
2005-05-18 20:06:47 +00:00
|
|
|
{
|
2017-02-21 23:47:21 +00:00
|
|
|
struct object_id oid;
|
|
|
|
struct commit_list **pptr = NULL;
|
|
|
|
|
|
|
|
/* Graft the fake parents locally to the commit */
|
|
|
|
while (isspace(*p++) && !parse_oid_hex(p, &oid, &p)) {
|
2018-06-29 01:21:59 +00:00
|
|
|
struct commit *parent = lookup_commit(the_repository, &oid);
|
2017-02-21 23:47:21 +00:00
|
|
|
if (!pptr) {
|
|
|
|
/* Free the real parent list */
|
|
|
|
free_commit_list(commit->parents);
|
|
|
|
commit->parents = NULL;
|
|
|
|
pptr = &(commit->parents);
|
|
|
|
}
|
|
|
|
if (parent) {
|
|
|
|
pptr = &commit_list_insert(parent, pptr)->next;
|
2006-02-06 07:00:41 +00:00
|
|
|
}
|
2005-05-18 20:06:47 +00:00
|
|
|
}
|
2006-04-09 08:11:11 +00:00
|
|
|
return log_tree_commit(&log_tree_opt, commit);
|
2005-05-06 17:03:17 +00:00
|
|
|
}
|
|
|
|
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
/* Diff two trees. */
|
2017-02-21 23:47:21 +00:00
|
|
|
static int stdin_diff_trees(struct tree *tree1, const char *p)
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
{
|
2017-02-21 23:47:21 +00:00
|
|
|
struct object_id oid;
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
struct tree *tree2;
|
2017-02-21 23:47:21 +00:00
|
|
|
if (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p)
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
return error("Need exactly two trees, separated by a space");
|
2018-06-29 01:21:56 +00:00
|
|
|
tree2 = lookup_tree(the_repository, &oid);
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
if (!tree2 || parse_tree(tree2))
|
|
|
|
return -1;
|
2015-11-10 02:22:28 +00:00
|
|
|
printf("%s %s\n", oid_to_hex(&tree1->object.oid),
|
|
|
|
oid_to_hex(&tree2->object.oid));
|
2017-05-30 17:31:03 +00:00
|
|
|
diff_tree_oid(&tree1->object.oid, &tree2->object.oid,
|
|
|
|
"", &log_tree_opt.diffopt);
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
log_tree_diff_flush(&log_tree_opt);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-08-08 20:48:23 +00:00
|
|
|
static int diff_tree_stdin(char *line)
|
|
|
|
{
|
|
|
|
int len = strlen(line);
|
2017-02-21 23:47:21 +00:00
|
|
|
struct object_id oid;
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
struct object *obj;
|
2017-02-21 23:47:21 +00:00
|
|
|
const char *p;
|
2008-08-08 20:48:23 +00:00
|
|
|
|
|
|
|
if (!len || line[len-1] != '\n')
|
|
|
|
return -1;
|
|
|
|
line[len-1] = 0;
|
2017-02-21 23:47:21 +00:00
|
|
|
if (parse_oid_hex(line, &oid, &p))
|
2008-08-08 20:48:23 +00:00
|
|
|
return -1;
|
2018-06-29 01:21:51 +00:00
|
|
|
obj = parse_object(the_repository, &oid);
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
if (!obj)
|
2008-08-08 20:48:23 +00:00
|
|
|
return -1;
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
if (obj->type == OBJ_COMMIT)
|
2017-02-21 23:47:21 +00:00
|
|
|
return stdin_diff_commit((struct commit *)obj, p);
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
if (obj->type == OBJ_TREE)
|
2017-02-21 23:47:21 +00:00
|
|
|
return stdin_diff_trees((struct tree *)obj, p);
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
error("Object %s is a %s, not a commit or tree",
|
2018-02-14 18:59:24 +00:00
|
|
|
oid_to_hex(&oid), type_name(obj->type));
|
Teach git diff-tree --stdin to diff trees
When feeding trees on the command line, you can give exactly two
trees, not three nor one; --stdin now supports this "two tree" form on
its input, in addition to accepting lines with one or more commits.
When diffing trees (either specified on the command line or from the
standard input), the -s, -v, --pretty, --abbrev-commit, --encoding,
--no-commit-id, and --always options are ignored, since they do not
apply to trees; and the -m, -c, and --cc options are ignored since
they would be meaningful only with three or more trees, which is not
supported (yet).
Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-10 16:12:58 +00:00
|
|
|
return -1;
|
2008-08-08 20:48:23 +00:00
|
|
|
}
|
|
|
|
|
2005-07-29 09:01:26 +00:00
|
|
|
static const char diff_tree_usage[] =
|
2022-10-13 15:39:22 +00:00
|
|
|
"git diff-tree [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]\n"
|
|
|
|
" [-t] [-r] [-c | --cc] [--combined-all-paths] [--root] [--merge-base]\n"
|
|
|
|
" [<common-diff-options>] <tree-ish> [<tree-ish>] [<path>...]\n"
|
2022-10-13 15:39:01 +00:00
|
|
|
"\n"
|
2005-10-28 17:04:49 +00:00
|
|
|
" -r diff recursively\n"
|
log,diff-tree: add --combined-all-paths option
The combined diff format for merges will only list one filename, even if
rename or copy detection is active. For example, with raw format one
might see:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM describe.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR phooey.c
This doesn't let us know what the original name of bar.sh was in the
first parent, and doesn't let us know what either of the original names
of phooey.c were in either of the parents. In contrast, for non-merge
commits, raw format does provide original filenames (and a rename score
to boot). In order to also provide original filenames for merge
commits, add a --combined-all-paths option (which must be used with
either -c or --cc, and is likely only useful with rename or copy
detection active) so that we can print tab-separated filenames when
renames are involved. This transforms the above output to:
::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c desc.c desc.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM foo.sh bar.sh bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR fooey.c fuey.c phooey.c
Further, in patch format, this changes the from/to headers so that
instead of just having one "from" header, we get one for each parent.
For example, instead of having
--- a/phooey.c
+++ b/phooey.c
we would see
--- a/fooey.c
--- a/fuey.c
+++ b/phooey.c
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-02-08 01:12:46 +00:00
|
|
|
" -c show combined diff for merge commits\n"
|
|
|
|
" --cc show combined diff for merge commits removing uninteresting hunks\n"
|
|
|
|
" --combined-all-paths\n"
|
|
|
|
" show name of file in all parents for combined diffs\n"
|
2005-10-28 17:04:49 +00:00
|
|
|
" --root include the initial commit as diff against /dev/null\n"
|
2005-07-13 19:52:35 +00:00
|
|
|
COMMON_DIFF_OPTIONS_HELP;
|
2005-06-13 00:44:21 +00:00
|
|
|
|
2023-07-03 06:44:16 +00:00
|
|
|
static void diff_tree_tweak_rev(struct rev_info *rev)
|
2010-03-09 07:27:25 +00:00
|
|
|
{
|
|
|
|
if (!rev->diffopt.output_format) {
|
|
|
|
if (rev->dense_combined_merges)
|
|
|
|
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
|
|
|
|
else
|
|
|
|
rev->diffopt.output_format = DIFF_FORMAT_RAW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-29 05:44:25 +00:00
|
|
|
int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
2005-04-10 21:03:58 +00:00
|
|
|
{
|
2005-05-06 17:03:17 +00:00
|
|
|
char line[1000];
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-14 23:52:13 +00:00
|
|
|
struct object *tree1, *tree2;
|
|
|
|
static struct rev_info *opt = &log_tree_opt;
|
2010-03-09 07:27:25 +00:00
|
|
|
struct setup_revision_opt s_r_opt;
|
diff-tree.c: load notes machinery when required
Since its introduction in 7249e91 (revision.c: support --notes
command-line option, 2011-03-29), combining '--notes' with any option
that causes us to format notes (e.g., '--pretty', '--format="%N"', etc)
results in a failed assertion at runtime.
$ git rev-list HEAD | git diff-tree --stdin --pretty=medium --notes
commit 8f3d9f354286745c751374f5f1fcafee6b3f3136
git: notes.c:1308: format_display_notes: Assertion `display_notes_trees' failed.
Aborted
This failure is due to diff-tree not calling 'load_display_notes' to
initialize the notes machinery.
Ordinarily, this failure isn't triggered, because it requires passing
both '--notes' and another of the above mentioned options. In the case
of '--pretty', for example, we set 'opt->verbose_header', causing
'show_log()' to eventually call 'format_display_notes()', which expects
a non-NULL 'display_note_trees'.
Without initializing the notes machinery, 'display_note_trees' remains
NULL, and thus triggers an assertion failure.
Fix this by initializing the notes machinery after parsing our options,
and harden this behavior against regression with a test in t4013. (Note
that the added ref in this test requires updating two unrelated tests
which use 'log --all', and thus need to learn about the new refs).
Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-21 00:13:15 +00:00
|
|
|
struct userformat_want w;
|
2006-04-09 08:11:11 +00:00
|
|
|
int read_stdin = 0;
|
2020-09-14 18:36:52 +00:00
|
|
|
int merge_base = 0;
|
2005-04-10 21:03:58 +00:00
|
|
|
|
2017-06-01 04:38:16 +00:00
|
|
|
if (argc == 2 && !strcmp(argv[1], "-h"))
|
|
|
|
usage(diff_tree_usage);
|
|
|
|
|
2017-05-08 16:03:37 +00:00
|
|
|
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
diff-tree: integrate with sparse index
The index is read in 'cmd_diff_tree' at two points:
1. The first index read was added in fd66bcc31ff (diff-tree: read the
index so attribute checks work in bare repositories, 2017-12-06) to deal
with reading '.gitattributes' content. 77efbb366ab (attr: be careful
about sparse directories, 2021-09-08) established that, in a sparse
index, we do _not_ try to load a '.gitattributes' file from within a
sparse directory.
2. The second index access point is involved in rename detection,
specifically when reading from stdin.This was initially added in
f0c6b2a2fd9 ([PATCH] Optimize diff-tree -[CM]--stdin, 2005-05-27), where
'setup' was set to 'DIFF_SETUP_USE_SIZE_CACHE |DIFF_SETUP_USE_CACHE'.
That assignment was later modified to drop the'DIFF_SETUP_USE_CACHE' in
ff7fe37b053 (diff.c: move read_index() code back to the caller,
2018-08-13).However, 'DIFF_SETUP_USE_SIZE_CACHE' seems to be unused as
of 6e0b8ed6d35 (diff.c: do not use a separate "size cache"., 2007-05-07)
and nothing about 'detect_rename' otherwise indicates index usage.
Hence we can just set the requires-full-index to false for "diff-tree".
Add tests that verify that 'git diff-tree' behaves correctly when the
sparse index is enabled and test to ensure the index is not expanded.
The `p2000` tests demonstrate a ~98% execution time reduction for
'git diff-tree' using a sparse index:
Test before after
-----------------------------------------------------------------------
2000.94: git diff-tree HEAD (full-v3) 0.05 0.04 -20.0%
2000.95: git diff-tree HEAD (full-v4) 0.06 0.05 -16.7%
2000.96: git diff-tree HEAD (sparse-v3) 0.59 0.01 -98.3%
2000.97: git diff-tree HEAD (sparse-v4) 0.61 0.01 -98.4%
2000.98: git diff-tree HEAD -- f2/f4/a (full-v3) 0.05 0.05 +0.0%
2000.99: git diff-tree HEAD -- f2/f4/a (full-v4) 0.05 0.04 -20.0%
2000.100: git diff-tree HEAD -- f2/f4/a (sparse-v3) 0.58 0.01 -98.3%
2000.101: git diff-tree HEAD -- f2/f4/a (sparse-v4) 0.55 0.01 -98.2%
Helped-by: Victoria Dye <vdye@github.com>
Signed-off-by: Shuqi Liang <cheskaqiqi@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-18 15:44:54 +00:00
|
|
|
|
|
|
|
prepare_repo_settings(the_repository);
|
|
|
|
the_repository->settings.command_requires_full_index = 0;
|
|
|
|
|
2018-09-21 15:57:38 +00:00
|
|
|
repo_init_revisions(the_repository, opt, prefix);
|
2022-11-19 13:07:38 +00:00
|
|
|
if (repo_read_index(the_repository) < 0)
|
2017-12-06 22:02:56 +00:00
|
|
|
die(_("index file corrupt"));
|
2006-04-15 05:19:38 +00:00
|
|
|
opt->abbrev = 0;
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-17 18:59:32 +00:00
|
|
|
opt->diff = 1;
|
2009-11-03 14:59:18 +00:00
|
|
|
opt->disable_stdin = 1;
|
2010-03-09 07:27:25 +00:00
|
|
|
memset(&s_r_opt, 0, sizeof(s_r_opt));
|
|
|
|
s_r_opt.tweak = diff_tree_tweak_rev;
|
2016-05-13 20:41:02 +00:00
|
|
|
|
MacOS: precompose_argv_prefix()
The following sequence leads to a "BUG" assertion running under MacOS:
DIR=git-test-restore-p
Adiarnfd=$(printf 'A\314\210')
DIRNAME=xx${Adiarnfd}yy
mkdir $DIR &&
cd $DIR &&
git init &&
mkdir $DIRNAME &&
cd $DIRNAME &&
echo "Initial" >file &&
git add file &&
echo "One more line" >>file &&
echo y | git restore -p .
Initialized empty Git repository in /tmp/git-test-restore-p/.git/
BUG: pathspec.c:495: error initializing pathspec_item
Cannot close git diff-index --cached --numstat
[snip]
The command `git restore` is run from a directory inside a Git repo.
Git needs to split the $CWD into 2 parts:
The path to the repo and "the rest", if any.
"The rest" becomes a "prefix" later used inside the pathspec code.
As an example, "/path/to/repo/dir-inside-repå" would determine
"/path/to/repo" as the root of the repo, the place where the
configuration file .git/config is found.
The rest becomes the prefix ("dir-inside-repå"), from where the
pathspec machinery expands the ".", more about this later.
If there is a decomposed form, (making the decomposing visible like this),
"dir-inside-rep°a" doesn't match "dir-inside-repå".
Git commands need to:
(a) read the configuration variable "core.precomposeunicode"
(b) precocompose argv[]
(c) precompose the prefix, if there was any
The first commit,
76759c7dff53 "git on Mac OS and precomposed unicode"
addressed (a) and (b).
The call to precompose_argv() was added into parse-options.c,
because that seemed to be a good place when the patch was written.
Commands that don't use parse-options need to do (a) and (b) themselfs.
The commands `diff-files`, `diff-index`, `diff-tree` and `diff`
learned (a) and (b) in
commit 90a78b83e0b8 "diff: run arguments through precompose_argv"
Branch names (or refs in general) using decomposed code points
resulting in decomposed file names had been fixed in
commit 8e712ef6fc97 "Honor core.precomposeUnicode in more places"
The bug report from above shows 2 things:
- more commands need to handle precomposed unicode
- (c) should be implemented for all commands using pathspecs
Solution:
precompose_argv() now handles the prefix (if needed), and is renamed into
precompose_argv_prefix().
Inside this function the config variable core.precomposeunicode is read
into the global variable precomposed_unicode, as before.
This reading is skipped if precomposed_unicode had been read before.
The original patch for preocomposed unicode, 76759c7dff53, placed
precompose_argv() into parse-options.c
Now add it into git.c::run_builtin() as well. Existing precompose
calls in diff-files.c and others may become redundant, and if we
audit the callflows that reach these places to make sure that they
can never be reached without going through the new call added to
run_builtin(), we might be able to remove these existing ones.
But in this commit, we do not bother to do so and leave these
precompose callsites as they are. Because precompose() is
idempotent and can be called on an already precomposed string
safely, this is safer than removing existing calls without fully
vetting the callflows.
There is certainly room for cleanups - this change intends to be a bug fix.
Cleanups needs more tests in e.g. t/t3910-mac-os-precompose.sh, and should
be done in future commits.
[1] git-bugreport-2021-01-06-1209.txt (git can't deal with special characters)
[2] https://lore.kernel.org/git/A102844A-9501-4A86-854D-E3B387D378AA@icloud.com/
Reported-by: Daniel Troger <random_n0body@icloud.com>
Helped-By: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-03 16:28:23 +00:00
|
|
|
prefix = precompose_argv_prefix(argc, argv, prefix);
|
2010-03-09 07:27:25 +00:00
|
|
|
argc = setup_revisions(argc, argv, opt, &s_r_opt);
|
2005-09-21 07:00:47 +00:00
|
|
|
|
diff-tree.c: load notes machinery when required
Since its introduction in 7249e91 (revision.c: support --notes
command-line option, 2011-03-29), combining '--notes' with any option
that causes us to format notes (e.g., '--pretty', '--format="%N"', etc)
results in a failed assertion at runtime.
$ git rev-list HEAD | git diff-tree --stdin --pretty=medium --notes
commit 8f3d9f354286745c751374f5f1fcafee6b3f3136
git: notes.c:1308: format_display_notes: Assertion `display_notes_trees' failed.
Aborted
This failure is due to diff-tree not calling 'load_display_notes' to
initialize the notes machinery.
Ordinarily, this failure isn't triggered, because it requires passing
both '--notes' and another of the above mentioned options. In the case
of '--pretty', for example, we set 'opt->verbose_header', causing
'show_log()' to eventually call 'format_display_notes()', which expects
a non-NULL 'display_note_trees'.
Without initializing the notes machinery, 'display_note_trees' remains
NULL, and thus triggers an assertion failure.
Fix this by initializing the notes machinery after parsing our options,
and harden this behavior against regression with a test in t4013. (Note
that the added ref in this test requires updating two unrelated tests
which use 'log --all', and thus need to learn about the new refs).
Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-21 00:13:15 +00:00
|
|
|
memset(&w, 0, sizeof(w));
|
|
|
|
userformat_find_requirements(NULL, &w);
|
|
|
|
|
|
|
|
if (!opt->show_notes_given && w.notes)
|
|
|
|
opt->show_notes = 1;
|
|
|
|
if (opt->show_notes)
|
|
|
|
load_display_notes(&opt->notes_opt);
|
|
|
|
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-14 23:52:13 +00:00
|
|
|
while (--argc > 0) {
|
|
|
|
const char *arg = *++argv;
|
2005-04-24 05:08:00 +00:00
|
|
|
|
2005-05-06 17:03:17 +00:00
|
|
|
if (!strcmp(arg, "--stdin")) {
|
|
|
|
read_stdin = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2020-09-14 18:36:52 +00:00
|
|
|
if (!strcmp(arg, "--merge-base")) {
|
|
|
|
merge_base = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2005-04-21 02:49:16 +00:00
|
|
|
usage(diff_tree_usage);
|
2005-04-10 21:03:58 +00:00
|
|
|
}
|
|
|
|
|
2020-09-14 18:36:52 +00:00
|
|
|
if (read_stdin && merge_base)
|
2022-01-05 20:02:14 +00:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
|
2020-09-14 18:36:52 +00:00
|
|
|
if (merge_base && opt->pending.nr != 2)
|
|
|
|
die(_("--merge-base only works with two commits"));
|
|
|
|
|
diff: --{rotate,skip}-to=<path>
In the implementation of "git difftool", there is a case where the
user wants to start viewing the diffs at a specific path and
continue on to the rest, optionally wrapping around to the
beginning. Since it is somewhat cumbersome to implement such a
feature as a post-processing step of "git diff" output, let's
support it internally with two new options.
- "git diff --rotate-to=C", when the resulting patch would show
paths A B C D E without the option, would "rotate" the paths to
shows patch to C D E A B instead. It is an error when there is
no patch for C is shown.
- "git diff --skip-to=C" would instead "skip" the paths before C,
and shows patch to C D E. Again, it is an error when there is no
patch for C is shown.
- "git log [-p]" also accepts these two options, but it is not an
error if there is no change to the specified path. Instead, the
set of output paths are rotated or skipped to the specified path
or the first path that sorts after the specified path.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 19:57:50 +00:00
|
|
|
opt->diffopt.rotate_to_strict = 1;
|
|
|
|
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-14 23:52:13 +00:00
|
|
|
/*
|
2017-06-02 02:34:15 +00:00
|
|
|
* NOTE! We expect "a..b" to expand to "^a b" but it is
|
|
|
|
* perfectly valid for revision range parser to yield "b ^a",
|
|
|
|
* which means the same thing. If we get the latter, i.e. the
|
|
|
|
* second one is marked UNINTERESTING, we recover the original
|
|
|
|
* order the user gave, i.e. "a..b", by swapping the trees.
|
Common option parsing for "git log --diff" and friends
This basically does a few things that are sadly somewhat interdependent,
and nontrivial to split out
- get rid of "struct log_tree_opt"
The fields in "log_tree_opt" are moved into "struct rev_info", and all
users of log_tree_opt are changed to use the rev_info struct instead.
- add the parsing for the log_tree_opt arguments to "setup_revision()"
- make setup_revision set a flag (revs->diff) if the diff-related
arguments were used. This allows "git log" to decide whether it wants
to show diffs or not.
- make setup_revision() also initialize the diffopt part of rev_info
(which we had from before, but we just didn't initialize it)
- make setup_revision() do all the "finishing touches" on it all (it will
do the proper flag combination logic, and call "diff_setup_done()")
Now, that was the easy and straightforward part.
The slightly more involved part is that some of the programs that want to
use the new-and-improved rev_info parsing don't actually want _commits_,
they may want tree'ish arguments instead. That meant that I had to change
setup_revision() to parse the arguments not into the "revs->commits" list,
but into the "revs->pending_objects" list.
Then, when we do "prepare_revision_walk()", we walk that list, and create
the sorted commit list from there.
This actually cleaned some stuff up, but it's the less obvious part of the
patch, and re-organized the "revision.c" logic somewhat. It actually paves
the way for splitting argument parsing _entirely_ out of "revision.c",
since now the argument parsing really is totally independent of the commit
walking: that didn't use to be true, since there was lots of overlap with
get_commit_reference() handling etc, now the _only_ overlap is the shared
(and trivial) "add_pending_object()" thing.
However, I didn't do that file split, just because I wanted the diff
itself to be smaller, and show the actual changes more clearly. If this
gets accepted, I'll do further cleanups then - that includes the file
split, but also using the new infrastructure to do a nicer "git diff" etc.
Even in this form, it actually ends up removing more lines than it adds.
It's nice to note how simple and straightforward this makes the built-in
"git log" command, even though it continues to support all the diff flags
too. It doesn't get much simpler that this.
I think this is worth merging soonish, because it does allow for future
cleanup and even more sharing of code. However, it obviously touches
"revision.c", which is subtle. I've tested that it passes all the tests we
have, and it passes my "looks sane" detector, but somebody else should
also give it a good look-over.
[jc: squashed the original and three "oops this too" updates, with
another fix-up.]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-14 23:52:13 +00:00
|
|
|
*/
|
2017-05-30 17:31:04 +00:00
|
|
|
switch (opt->pending.nr) {
|
2005-05-18 20:10:17 +00:00
|
|
|
case 0:
|
|
|
|
if (!read_stdin)
|
|
|
|
usage(diff_tree_usage);
|
|
|
|
break;
|
|
|
|
case 1:
|
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
|
|
|
tree1 = opt->pending.objects[0].item;
|
2017-05-30 17:31:04 +00:00
|
|
|
diff_tree_commit_oid(&tree1->oid);
|
2005-05-18 20:10:17 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
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
|
|
|
tree1 = opt->pending.objects[0].item;
|
|
|
|
tree2 = opt->pending.objects[1].item;
|
2020-09-14 18:36:52 +00:00
|
|
|
if (merge_base) {
|
|
|
|
struct object_id oid;
|
|
|
|
|
|
|
|
diff_get_merge_base(opt, &oid);
|
|
|
|
tree1 = lookup_object(the_repository, &oid);
|
|
|
|
} else if (tree2->flags & UNINTERESTING) {
|
2017-01-28 21:40:58 +00:00
|
|
|
SWAP(tree2, tree1);
|
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
|
|
|
}
|
2017-05-30 17:31:03 +00:00
|
|
|
diff_tree_oid(&tree1->oid, &tree2->oid, "", &opt->diffopt);
|
2006-04-09 08:11:11 +00:00
|
|
|
log_tree_diff_flush(opt);
|
2005-05-18 20:10:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-12-13 20:24:52 +00:00
|
|
|
if (read_stdin) {
|
2011-01-06 21:50:06 +00:00
|
|
|
int saved_nrl = 0;
|
|
|
|
int saved_dcctc = 0;
|
|
|
|
|
diff: --{rotate,skip}-to=<path>
In the implementation of "git difftool", there is a case where the
user wants to start viewing the diffs at a specific path and
continue on to the rest, optionally wrapping around to the
beginning. Since it is somewhat cumbersome to implement such a
feature as a post-processing step of "git diff" output, let's
support it internally with two new options.
- "git diff --rotate-to=C", when the resulting patch would show
paths A B C D E without the option, would "rotate" the paths to
shows patch to C D E A B instead. It is an error when there is
no patch for C is shown.
- "git diff --skip-to=C" would instead "skip" the paths before C,
and shows patch to C D E. Again, it is an error when there is no
patch for C is shown.
- "git log [-p]" also accepts these two options, but it is not an
error if there is no change to the specified path. Instead, the
set of output paths are rotated or skipped to the specified path
or the first path that sorts after the specified path.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-02-11 19:57:50 +00:00
|
|
|
opt->diffopt.rotate_to_strict = 0;
|
2.36 gitk/diff-tree --stdin regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
The diff_free() call is to be used after we completely finished with
a diffopt structure. After "git diff A B" finishes producing
output, calling it before process exit is fine. But there are
commands that prepares diff_options struct once, compares two sets
of paths, releases resources that were used to do the comparison,
then reuses the same diff_option struct to go on to compare the next
two sets of paths, like "git log -p".
After "git log -p" finishes showing a single commit, calling it
before it goes on to the next commit is NOT fine. There is a
mechanism, the .no_free member in diff_options struct, to help "git
log" to avoid calling diff_free() after showing each commit and
instead call it just one. When the mechanism was introduced in
e900d494 (diff: add an API for deferred freeing, 2021-02-11),
however, we forgot to do the same to "diff-tree --stdin", which *is*
a moral equivalent to "git log".
During 2.36 release cycle, we started clearing the pathspec in
diff_free(), so programs like gitk that runs
git diff-tree --stdin -- <pathspec>
downstream of a pipe, processing one commit after another, started
showing irrelevant comparison outside the given <pathspec> from the
second commit. The same commit, by forgetting to teach the .no_free
mechanism, broke "diff-tree --stdin -I<regexp>" and nobody noticed
it for over a year, presumably because it is so seldom used an
option.
But <pathspec> is a different story. The breakage was very
prominently visible and was reported immediately after 2.36 was
released.
Fix this breakage by mimicking how "git log" utilizes the .no_free
member so that "diff-tree --stdin" behaves more similarly to "log".
Protect the fix with a few new tests.
Reported-by: Matthias Aßhauer <mha1993@live.de>
Helped-by: René Scharfe <l.s.r@web.de>
Helped-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-26 16:11:44 +00:00
|
|
|
opt->diffopt.no_free = 1;
|
2018-08-13 16:14:18 +00:00
|
|
|
if (opt->diffopt.detect_rename) {
|
|
|
|
if (!the_index.cache)
|
2019-01-12 02:13:26 +00:00
|
|
|
repo_read_index(the_repository);
|
2018-08-13 16:14:18 +00:00
|
|
|
opt->diffopt.setup |= DIFF_SETUP_USE_SIZE_CACHE;
|
|
|
|
}
|
2007-12-13 20:24:52 +00:00
|
|
|
while (fgets(line, sizeof(line), stdin)) {
|
2017-02-21 23:47:21 +00:00
|
|
|
struct object_id oid;
|
2005-05-06 17:03:17 +00:00
|
|
|
|
2017-02-21 23:47:21 +00:00
|
|
|
if (get_oid_hex(line, &oid)) {
|
2007-12-13 20:24:52 +00:00
|
|
|
fputs(line, stdout);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
2011-01-06 21:50:06 +00:00
|
|
|
else {
|
2007-12-13 20:24:52 +00:00
|
|
|
diff_tree_stdin(line);
|
2011-01-06 21:50:06 +00:00
|
|
|
if (saved_nrl < opt->diffopt.needed_rename_limit)
|
|
|
|
saved_nrl = opt->diffopt.needed_rename_limit;
|
|
|
|
if (opt->diffopt.degraded_cc_to_c)
|
|
|
|
saved_dcctc = 1;
|
|
|
|
}
|
2006-05-30 02:01:38 +00:00
|
|
|
}
|
2011-01-06 21:50:06 +00:00
|
|
|
opt->diffopt.degraded_cc_to_c = saved_dcctc;
|
|
|
|
opt->diffopt.needed_rename_limit = saved_nrl;
|
2.36 gitk/diff-tree --stdin regression fix
This only surfaced as a regression after 2.36 release, but the
breakage was already there with us for at least a year.
The diff_free() call is to be used after we completely finished with
a diffopt structure. After "git diff A B" finishes producing
output, calling it before process exit is fine. But there are
commands that prepares diff_options struct once, compares two sets
of paths, releases resources that were used to do the comparison,
then reuses the same diff_option struct to go on to compare the next
two sets of paths, like "git log -p".
After "git log -p" finishes showing a single commit, calling it
before it goes on to the next commit is NOT fine. There is a
mechanism, the .no_free member in diff_options struct, to help "git
log" to avoid calling diff_free() after showing each commit and
instead call it just one. When the mechanism was introduced in
e900d494 (diff: add an API for deferred freeing, 2021-02-11),
however, we forgot to do the same to "diff-tree --stdin", which *is*
a moral equivalent to "git log".
During 2.36 release cycle, we started clearing the pathspec in
diff_free(), so programs like gitk that runs
git diff-tree --stdin -- <pathspec>
downstream of a pipe, processing one commit after another, started
showing irrelevant comparison outside the given <pathspec> from the
second commit. The same commit, by forgetting to teach the .no_free
mechanism, broke "diff-tree --stdin -I<regexp>" and nobody noticed
it for over a year, presumably because it is so seldom used an
option.
But <pathspec> is a different story. The breakage was very
prominently visible and was reported immediately after 2.36 was
released.
Fix this breakage by mimicking how "git log" utilizes the .no_free
member so that "diff-tree --stdin" behaves more similarly to "log".
Protect the fix with a few new tests.
Reported-by: Matthias Aßhauer <mha1993@live.de>
Helped-by: René Scharfe <l.s.r@web.de>
Helped-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-26 16:11:44 +00:00
|
|
|
opt->diffopt.no_free = 0;
|
|
|
|
diff_free(&opt->diffopt);
|
2006-05-30 02:01:38 +00:00
|
|
|
}
|
2007-12-14 07:40:27 +00:00
|
|
|
|
2023-08-21 20:20:46 +00:00
|
|
|
return diff_result_code(&opt->diffopt);
|
2005-04-09 20:00:54 +00:00
|
|
|
}
|