2006-04-29 08:20:52 +02:00
|
|
|
/*
|
|
|
|
* Builtin "git diff"
|
|
|
|
*
|
|
|
|
* Copyright (c) 2006 Junio C Hamano
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
2008-02-18 08:26:03 +01:00
|
|
|
#include "color.h"
|
2006-04-29 08:20:52 +02:00
|
|
|
#include "commit.h"
|
|
|
|
#include "blob.h"
|
|
|
|
#include "tag.h"
|
|
|
|
#include "diff.h"
|
|
|
|
#include "diffcore.h"
|
|
|
|
#include "revision.h"
|
|
|
|
#include "log-tree.h"
|
|
|
|
#include "builtin.h"
|
|
|
|
|
|
|
|
struct blobinfo {
|
|
|
|
unsigned char sha1[20];
|
|
|
|
const char *name;
|
2007-04-22 18:44:00 +02:00
|
|
|
unsigned mode;
|
2006-04-29 08:20:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const char builtin_diff_usage[] =
|
2008-07-13 15:36:15 +02:00
|
|
|
"git diff <options> <rev>{0,2} -- <path>*";
|
2006-04-29 08:20:52 +02:00
|
|
|
|
|
|
|
static void stuff_change(struct diff_options *opt,
|
|
|
|
unsigned old_mode, unsigned new_mode,
|
|
|
|
const unsigned char *old_sha1,
|
|
|
|
const unsigned char *new_sha1,
|
|
|
|
const char *old_name,
|
|
|
|
const char *new_name)
|
|
|
|
{
|
|
|
|
struct diff_filespec *one, *two;
|
|
|
|
|
2006-08-15 22:37:19 +02:00
|
|
|
if (!is_null_sha1(old_sha1) && !is_null_sha1(new_sha1) &&
|
2007-04-23 08:56:22 +02:00
|
|
|
!hashcmp(old_sha1, new_sha1) && (old_mode == new_mode))
|
2006-04-29 08:20:52 +02:00
|
|
|
return;
|
|
|
|
|
2007-11-10 20:05:14 +01:00
|
|
|
if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
|
2006-04-29 08:20:52 +02:00
|
|
|
unsigned tmp;
|
2006-05-07 16:50:47 +02:00
|
|
|
const unsigned char *tmp_u;
|
2006-04-29 08:20:52 +02:00
|
|
|
const char *tmp_c;
|
|
|
|
tmp = old_mode; old_mode = new_mode; new_mode = tmp;
|
|
|
|
tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u;
|
|
|
|
tmp_c = old_name; old_name = new_name; new_name = tmp_c;
|
|
|
|
}
|
diff --relative: output paths as relative to the current subdirectory
This adds --relative option to the diff family. When you start
from a subdirectory:
$ git diff --relative
shows only the diff that is inside your current subdirectory,
and without $prefix part. People who usually live in
subdirectories may like it.
There are a few things I should also mention about the change:
- This works not just with diff but also works with the log
family of commands, but the history pruning is not affected.
In other words, if you go to a subdirectory, you can say:
$ git log --relative -p
but it will show the log message even for commits that do not
touch the current directory. You can limit it by giving
pathspec yourself:
$ git log --relative -p .
This originally was not a conscious design choice, but we
have a way to affect diff pathspec and pruning pathspec
independently. IOW "git log --full-diff -p ." tells it to
prune history to commits that affect the current subdirectory
but show the changes with full context. I think it makes
more sense to leave pruning independent from --relative than
the obvious alternative of always pruning with the current
subdirectory, which would break the symmetry.
- Because this works also with the log family, you could
format-patch a single change, limiting the effect to your
subdirectory, like so:
$ cd gitk-git
$ git format-patch -1 --relative 911f1eb
But because that is a special purpose usage, this option will
never become the default, with or without repository or user
preference configuration. The risk of producing a partial
patch and sending it out by mistake is too great if we did
so.
- This is inherently incompatible with --no-index, which is a
bolted-on hack that does not have much to do with git
itself. I didn't bother checking and erroring out on the
combined use of the options, but probably I should.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-12 23:26:02 +01:00
|
|
|
|
|
|
|
if (opt->prefix &&
|
|
|
|
(strncmp(old_name, opt->prefix, opt->prefix_length) ||
|
|
|
|
strncmp(new_name, opt->prefix, opt->prefix_length)))
|
|
|
|
return;
|
|
|
|
|
2006-04-29 08:20:52 +02:00
|
|
|
one = alloc_filespec(old_name);
|
|
|
|
two = alloc_filespec(new_name);
|
|
|
|
fill_filespec(one, old_sha1, old_mode);
|
|
|
|
fill_filespec(two, new_sha1, new_mode);
|
|
|
|
|
|
|
|
diff_queue(&diff_queued_diff, one, two);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int builtin_diff_b_f(struct rev_info *revs,
|
|
|
|
int argc, const char **argv,
|
|
|
|
struct blobinfo *blob,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
/* Blob vs file in the working tree*/
|
|
|
|
struct stat st;
|
|
|
|
|
2006-06-24 19:23:06 +02:00
|
|
|
if (argc > 1)
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
|
2006-04-29 08:20:52 +02:00
|
|
|
if (lstat(path, &st))
|
|
|
|
die("'%s': %s", path, strerror(errno));
|
|
|
|
if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
|
|
|
|
die("'%s': not a regular file or symlink", path);
|
2007-04-22 18:44:00 +02:00
|
|
|
|
|
|
|
if (blob[0].mode == S_IFINVALID)
|
|
|
|
blob[0].mode = canon_mode(st.st_mode);
|
|
|
|
|
2006-04-29 08:20:52 +02:00
|
|
|
stuff_change(&revs->diffopt,
|
2007-04-22 18:44:00 +02:00
|
|
|
blob[0].mode, canon_mode(st.st_mode),
|
2006-04-29 08:20:52 +02:00
|
|
|
blob[0].sha1, null_sha1,
|
2006-05-18 23:35:37 +02:00
|
|
|
path, path);
|
2006-04-29 08:20:52 +02:00
|
|
|
diffcore_std(&revs->diffopt);
|
|
|
|
diff_flush(&revs->diffopt);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int builtin_diff_blobs(struct rev_info *revs,
|
|
|
|
int argc, const char **argv,
|
|
|
|
struct blobinfo *blob)
|
|
|
|
{
|
|
|
|
unsigned mode = canon_mode(S_IFREG | 0644);
|
|
|
|
|
2006-06-24 19:23:06 +02:00
|
|
|
if (argc > 1)
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
|
2007-04-22 18:44:00 +02:00
|
|
|
if (blob[0].mode == S_IFINVALID)
|
|
|
|
blob[0].mode = mode;
|
|
|
|
|
|
|
|
if (blob[1].mode == S_IFINVALID)
|
|
|
|
blob[1].mode = mode;
|
|
|
|
|
2006-04-29 08:20:52 +02:00
|
|
|
stuff_change(&revs->diffopt,
|
2007-04-22 18:44:00 +02:00
|
|
|
blob[0].mode, blob[1].mode,
|
2006-08-03 20:50:10 +02:00
|
|
|
blob[0].sha1, blob[1].sha1,
|
2006-08-03 20:57:11 +02:00
|
|
|
blob[0].name, blob[1].name);
|
2006-04-29 08:20:52 +02:00
|
|
|
diffcore_std(&revs->diffopt);
|
|
|
|
diff_flush(&revs->diffopt);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int builtin_diff_index(struct rev_info *revs,
|
|
|
|
int argc, const char **argv)
|
|
|
|
{
|
|
|
|
int cached = 0;
|
|
|
|
while (1 < argc) {
|
|
|
|
const char *arg = argv[1];
|
2006-12-13 10:33:43 +01:00
|
|
|
if (!strcmp(arg, "--cached"))
|
2006-04-29 08:20:52 +02:00
|
|
|
cached = 1;
|
|
|
|
else
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
argv++; argc--;
|
|
|
|
}
|
2008-08-28 15:02:12 +02:00
|
|
|
if (!cached)
|
|
|
|
setup_work_tree();
|
2006-04-29 08:20:52 +02:00
|
|
|
/*
|
|
|
|
* Make sure there is one revision (i.e. pending object),
|
|
|
|
* and there is no revision filtering parameters.
|
|
|
|
*/
|
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 02:42:35 +02:00
|
|
|
if (revs->pending.nr != 1 ||
|
2006-04-29 08:20:52 +02:00
|
|
|
revs->max_count != -1 || revs->min_age != -1 ||
|
|
|
|
revs->max_age != -1)
|
|
|
|
usage(builtin_diff_usage);
|
2007-02-10 03:51:40 +01:00
|
|
|
if (read_cache() < 0) {
|
|
|
|
perror("read_cache");
|
|
|
|
return -1;
|
|
|
|
}
|
2006-04-29 08:20:52 +02:00
|
|
|
return run_diff_index(revs, cached);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int builtin_diff_tree(struct rev_info *revs,
|
|
|
|
int argc, const char **argv,
|
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 02:42:35 +02:00
|
|
|
struct object_array_entry *ent)
|
2006-04-29 08:20:52 +02:00
|
|
|
{
|
|
|
|
const unsigned char *(sha1[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 02:42:35 +02:00
|
|
|
int swap = 0;
|
2006-06-24 19:23:06 +02:00
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
usage(builtin_diff_usage);
|
2006-04-29 10:24:49 +02:00
|
|
|
|
|
|
|
/* We saw two trees, ent[0] and ent[1].
|
2006-07-10 07:50:18 +02:00
|
|
|
* if ent[1] is uninteresting, they are swapped
|
2006-04-29 10:24:49 +02: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 02:42:35 +02:00
|
|
|
if (ent[1].item->flags & UNINTERESTING)
|
|
|
|
swap = 1;
|
2006-04-29 08:20:52 +02:00
|
|
|
sha1[swap] = ent[0].item->sha1;
|
|
|
|
sha1[1-swap] = ent[1].item->sha1;
|
|
|
|
diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
|
|
|
|
log_tree_diff_flush(revs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-04-29 10:24:49 +02:00
|
|
|
static int builtin_diff_combined(struct rev_info *revs,
|
|
|
|
int argc, const char **argv,
|
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 02:42:35 +02:00
|
|
|
struct object_array_entry *ent,
|
2006-04-29 10:24:49 +02:00
|
|
|
int ents)
|
|
|
|
{
|
|
|
|
const unsigned char (*parent)[20];
|
|
|
|
int i;
|
|
|
|
|
2006-06-24 19:23:06 +02:00
|
|
|
if (argc > 1)
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
|
2006-04-29 10:24:49 +02:00
|
|
|
if (!revs->dense_combined_merges && !revs->combine_merges)
|
|
|
|
revs->dense_combined_merges = revs->combine_merges = 1;
|
|
|
|
parent = xmalloc(ents * sizeof(*parent));
|
|
|
|
/* Again, the revs are all reverse */
|
|
|
|
for (i = 0; i < ents; i++)
|
2007-02-23 05:20:32 +01:00
|
|
|
hashcpy((unsigned char *)(parent + i),
|
|
|
|
ent[ents - 1 - i].item->sha1);
|
2006-04-29 10:24:49 +02:00
|
|
|
diff_tree_combined(parent[0], parent + 1, ents - 1,
|
|
|
|
revs->dense_combined_merges, revs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-31 22:13:42 +02:00
|
|
|
static void refresh_index_quietly(void)
|
|
|
|
{
|
|
|
|
struct lock_file *lock_file;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
lock_file = xcalloc(1, sizeof(struct lock_file));
|
|
|
|
fd = hold_locked_index(lock_file, 0);
|
|
|
|
if (fd < 0)
|
|
|
|
return;
|
|
|
|
discard_cache();
|
|
|
|
read_cache();
|
|
|
|
refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
|
2007-11-09 01:24:00 +01:00
|
|
|
|
|
|
|
if (active_cache_changed &&
|
2008-01-16 20:12:46 +01:00
|
|
|
!write_cache(fd, active_cache, active_nr))
|
2007-11-09 01:24:00 +01:00
|
|
|
commit_locked_index(lock_file);
|
|
|
|
|
2007-08-31 22:13:42 +02:00
|
|
|
rollback_lock_file(lock_file);
|
|
|
|
}
|
|
|
|
|
2008-05-24 07:28:56 +02:00
|
|
|
static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
unsigned int options = 0;
|
|
|
|
|
|
|
|
while (1 < argc && argv[1][0] == '-') {
|
|
|
|
if (!strcmp(argv[1], "--base"))
|
|
|
|
revs->max_count = 1;
|
|
|
|
else if (!strcmp(argv[1], "--ours"))
|
|
|
|
revs->max_count = 2;
|
|
|
|
else if (!strcmp(argv[1], "--theirs"))
|
|
|
|
revs->max_count = 3;
|
|
|
|
else if (!strcmp(argv[1], "-q"))
|
|
|
|
options |= DIFF_SILENT_ON_REMOVED;
|
|
|
|
else
|
|
|
|
return error("invalid option: %s", argv[1]);
|
|
|
|
argv++; argc--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (revs->max_count == -1 &&
|
|
|
|
(revs->diffopt.output_format & DIFF_FORMAT_PATCH))
|
|
|
|
revs->combine_merges = revs->dense_combined_merges = 1;
|
|
|
|
|
2008-08-28 15:02:12 +02:00
|
|
|
setup_work_tree();
|
2008-05-24 07:28:56 +02:00
|
|
|
if (read_cache() < 0) {
|
|
|
|
perror("read_cache");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
result = run_diff_files(revs, options);
|
|
|
|
return diff_result_code(&revs->diffopt, result);
|
|
|
|
}
|
|
|
|
|
2006-07-29 07:44:25 +02:00
|
|
|
int cmd_diff(int argc, const char **argv, const char *prefix)
|
2006-04-29 08:20:52 +02: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 02:42:35 +02:00
|
|
|
int i;
|
2006-04-29 08:20:52 +02:00
|
|
|
struct rev_info rev;
|
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 02:42:35 +02:00
|
|
|
struct object_array_entry ent[100];
|
2006-04-29 08:20:52 +02:00
|
|
|
int ents = 0, blobs = 0, paths = 0;
|
2006-07-29 07:44:25 +02:00
|
|
|
const char *path = NULL;
|
2006-04-29 08:20:52 +02:00
|
|
|
struct blobinfo blob[2];
|
2008-03-25 22:06:26 +01:00
|
|
|
int nongit;
|
2007-03-14 01:17:04 +01:00
|
|
|
int result = 0;
|
2006-04-29 08:20:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We could get N tree-ish in the rev.pending_objects list.
|
|
|
|
* Also there could be M blobs there, and P pathspecs.
|
|
|
|
*
|
|
|
|
* N=0, M=0:
|
|
|
|
* cache vs files (diff-files)
|
|
|
|
* N=0, M=2:
|
|
|
|
* compare two random blobs. P must be zero.
|
|
|
|
* N=0, M=1, P=1:
|
|
|
|
* compare a blob with a working tree file.
|
|
|
|
*
|
|
|
|
* N=1, M=0:
|
|
|
|
* tree vs cache (diff-index --cached)
|
|
|
|
*
|
|
|
|
* N=2, M=0:
|
|
|
|
* tree vs tree (diff-tree)
|
|
|
|
*
|
2008-05-24 07:28:56 +02:00
|
|
|
* N=0, M=0, P=2:
|
|
|
|
* compare two filesystem entities (aka --no-index).
|
|
|
|
*
|
2006-04-29 08:20:52 +02:00
|
|
|
* Other cases are errors.
|
|
|
|
*/
|
2006-05-04 08:54:34 +02:00
|
|
|
|
2007-02-22 21:50:10 +01:00
|
|
|
prefix = setup_git_directory_gently(&nongit);
|
2008-05-14 19:46:53 +02:00
|
|
|
git_config(git_diff_ui_config, NULL);
|
2008-02-18 08:26:03 +01:00
|
|
|
|
|
|
|
if (diff_use_color_default == -1)
|
|
|
|
diff_use_color_default = git_use_color_default;
|
|
|
|
|
2006-07-29 06:21:48 +02:00
|
|
|
init_revisions(&rev, prefix);
|
2008-05-24 07:28:56 +02:00
|
|
|
|
|
|
|
/* If this is a no-index diff, just run it and exit there. */
|
|
|
|
diff_no_index(&rev, argc, argv, nongit, prefix);
|
|
|
|
|
|
|
|
/* Otherwise, we are doing the usual "git" diff */
|
2007-08-31 22:13:42 +02:00
|
|
|
rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
|
2006-04-29 08:20:52 +02:00
|
|
|
|
2008-05-24 07:28:56 +02:00
|
|
|
if (nongit)
|
|
|
|
die("Not a git repository");
|
|
|
|
argc = setup_revisions(argc, argv, &rev, NULL);
|
2006-07-02 07:15:40 +02:00
|
|
|
if (!rev.diffopt.output_format) {
|
2006-06-24 19:24:14 +02:00
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
|
2006-08-09 21:45:27 +02:00
|
|
|
if (diff_setup_done(&rev.diffopt) < 0)
|
|
|
|
die("diff_setup_done failed");
|
2006-07-02 07:15:40 +02:00
|
|
|
}
|
2007-11-10 20:05:14 +01:00
|
|
|
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
|
|
|
|
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
|
2006-06-24 19:24:14 +02:00
|
|
|
|
2007-12-14 08:40:27 +01:00
|
|
|
/*
|
|
|
|
* If the user asked for our exit code then don't start a
|
2007-08-12 19:46:55 +02:00
|
|
|
* pager or we would end up reporting its exit code instead.
|
|
|
|
*/
|
2008-07-21 23:28:49 +02:00
|
|
|
if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS) &&
|
|
|
|
check_pager_config("diff") != 0)
|
2007-08-12 19:46:55 +02:00
|
|
|
setup_pager();
|
|
|
|
|
2008-05-24 07:28:56 +02:00
|
|
|
/*
|
|
|
|
* Do we have --cached and not have a pending object, then
|
2006-04-29 08:20:52 +02:00
|
|
|
* default to HEAD by hand. Eek.
|
|
|
|
*/
|
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 02:42:35 +02:00
|
|
|
if (!rev.pending.nr) {
|
2006-04-29 08:20:52 +02:00
|
|
|
int i;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
const char *arg = argv[i];
|
|
|
|
if (!strcmp(arg, "--"))
|
|
|
|
break;
|
|
|
|
else if (!strcmp(arg, "--cached")) {
|
2007-12-11 19:09:04 +01:00
|
|
|
add_head_to_pending(&rev);
|
2007-02-25 07:26:33 +01:00
|
|
|
if (!rev.pending.nr)
|
|
|
|
die("No HEAD commit to compare with (yet)");
|
2006-04-29 08:20:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 02:42:35 +02:00
|
|
|
for (i = 0; i < rev.pending.nr; i++) {
|
|
|
|
struct object_array_entry *list = rev.pending.objects+i;
|
2006-04-29 08:20:52 +02:00
|
|
|
struct object *obj = list->item;
|
|
|
|
const char *name = list->name;
|
|
|
|
int flags = (obj->flags & UNINTERESTING);
|
|
|
|
if (!obj->parsed)
|
|
|
|
obj = parse_object(obj->sha1);
|
|
|
|
obj = deref_tag(obj, NULL, 0);
|
|
|
|
if (!obj)
|
|
|
|
die("invalid object '%s' given.", name);
|
2006-07-12 05:45:31 +02:00
|
|
|
if (obj->type == OBJ_COMMIT)
|
2006-04-29 08:20:52 +02:00
|
|
|
obj = &((struct commit *)obj)->tree->object;
|
2006-07-12 05:45:31 +02:00
|
|
|
if (obj->type == OBJ_TREE) {
|
2006-04-29 10:24:49 +02:00
|
|
|
if (ARRAY_SIZE(ent) <= ents)
|
|
|
|
die("more than %d trees given: '%s'",
|
2006-04-30 09:26:41 +02:00
|
|
|
(int) ARRAY_SIZE(ent), name);
|
2006-04-29 08:20:52 +02:00
|
|
|
obj->flags |= flags;
|
|
|
|
ent[ents].item = obj;
|
|
|
|
ent[ents].name = name;
|
|
|
|
ents++;
|
|
|
|
continue;
|
|
|
|
}
|
2006-07-12 05:45:31 +02:00
|
|
|
if (obj->type == OBJ_BLOB) {
|
2006-04-29 08:20:52 +02:00
|
|
|
if (2 <= blobs)
|
|
|
|
die("more than two blobs given: '%s'", name);
|
2006-08-23 08:49:00 +02:00
|
|
|
hashcpy(blob[blobs].sha1, obj->sha1);
|
2006-04-29 08:20:52 +02:00
|
|
|
blob[blobs].name = name;
|
2007-04-22 18:44:00 +02:00
|
|
|
blob[blobs].mode = list->mode;
|
2006-04-29 08:20:52 +02:00
|
|
|
blobs++;
|
|
|
|
continue;
|
2006-05-04 08:54:34 +02:00
|
|
|
|
2006-04-29 08:20:52 +02:00
|
|
|
}
|
|
|
|
die("unhandled object '%s' given.", name);
|
|
|
|
}
|
|
|
|
if (rev.prune_data) {
|
|
|
|
const char **pathspec = rev.prune_data;
|
|
|
|
while (*pathspec) {
|
|
|
|
if (!path)
|
|
|
|
path = *pathspec;
|
|
|
|
paths++;
|
|
|
|
pathspec++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, do the arguments look reasonable?
|
|
|
|
*/
|
|
|
|
if (!ents) {
|
|
|
|
switch (blobs) {
|
|
|
|
case 0:
|
2008-05-24 07:28:56 +02:00
|
|
|
result = builtin_diff_files(&rev, argc, argv);
|
2006-04-29 08:20:52 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (paths != 1)
|
|
|
|
usage(builtin_diff_usage);
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_b_f(&rev, argc, argv, blob, path);
|
2006-04-29 08:20:52 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2006-04-29 10:24:49 +02:00
|
|
|
if (paths)
|
|
|
|
usage(builtin_diff_usage);
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_blobs(&rev, argc, argv, blob);
|
2006-04-29 08:20:52 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (blobs)
|
|
|
|
usage(builtin_diff_usage);
|
|
|
|
else if (ents == 1)
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_index(&rev, argc, argv);
|
2006-04-29 08:20:52 +02:00
|
|
|
else if (ents == 2)
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_tree(&rev, argc, argv, ent);
|
2006-07-17 09:34:44 +02:00
|
|
|
else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) {
|
|
|
|
/* diff A...B where there is one sane merge base between
|
|
|
|
* A and B. We have ent[0] == merge-base, ent[1] == A,
|
|
|
|
* and ent[2] == B. Show diff between the base and B.
|
|
|
|
*/
|
2006-08-10 09:50:15 +02:00
|
|
|
ent[1] = ent[2];
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_tree(&rev, argc, argv, ent);
|
2006-07-17 09:34:44 +02:00
|
|
|
}
|
2006-04-29 10:24:49 +02:00
|
|
|
else
|
2007-03-14 01:17:04 +01:00
|
|
|
result = builtin_diff_combined(&rev, argc, argv,
|
2006-07-17 09:34:44 +02:00
|
|
|
ent, ents);
|
2007-12-14 08:40:27 +01:00
|
|
|
result = diff_result_code(&rev.diffopt, result);
|
2007-08-31 22:13:42 +02:00
|
|
|
if (1 < rev.diffopt.skip_stat_unmatch)
|
|
|
|
refresh_index_quietly();
|
2007-03-14 01:17:04 +01:00
|
|
|
return result;
|
2006-04-29 08:20:52 +02:00
|
|
|
}
|