Skip to content

Commit

Permalink
[PATCH] Diff overhaul, adding half of copy detection.
Browse files Browse the repository at this point in the history
This introduces the diff-core, the layer between the diff-tree
family and the external diff interface engine.  The calls to the
interface diff-tree family uses (diff_change and diff_addremove)
have not changed and will not change.  The purpose of the
diff-core layer is to provide an infrastructure to transform the
set of differences sent from the applications, before sending
them to the external diff interface.

The recently introduced rename detection code has been rewritten
to use the diff-core facility.  When applications send in
separate creates and deletes, matching ones are transformed into
a single rename-and-edit diff, and sent out to the external diff
interface as such.

This patch also enhances the rename detection code further to be
able to detect copies.  Currently this happens only as long as
copy sources appear as part of the modified files, but there
already is enough provision for callers to report unmodified
files to diff-core, so that they can be also used as copy source
candidates.  Extending the callers this way will be done in a
separate patch.

Please see and marvel at how well this works by trying out the
newly added t/t4003-diff-rename-1.sh test script.

Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Junio C Hamano authored and Linus Torvalds committed May 21, 2005
1 parent c8265ac commit 427dcb4
Show file tree
Hide file tree
Showing 16 changed files with 944 additions and 432 deletions.
5 changes: 4 additions & 1 deletion Documentation/git-diff-cache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ git-diff-cache - Compares content and mode of blobs between the cache and reposi

SYNOPSIS
--------
'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [--cached] <tree-ish>
'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [-C] [--cached] <tree-ish>

DESCRIPTION
-----------
Expand All @@ -36,6 +36,9 @@ OPTIONS
-M::
Detect renames; implies -p.

-C::
Detect copies as well as renames; implies -p.

-R::
Output diff in reverse.

Expand Down
5 changes: 4 additions & 1 deletion Documentation/git-diff-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ git-diff-files - Compares files in the working tree and the cache

SYNOPSIS
--------
'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-R] [<pattern>...]
'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-C] [-R] [<pattern>...]

DESCRIPTION
-----------
Expand All @@ -32,6 +32,9 @@ OPTIONS
-M::
Detect renames; implies -p.

-C::
Detect copies as well as renames; implies -p.

-r::
This flag does not mean anything. It is there only to match
git-diff-tree. Unlike git-diff-tree, git-diff-files always looks
Expand Down
4 changes: 3 additions & 1 deletion Documentation/git-diff-helper.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ git-diff-helper - Generates patch format output for git-diff-*

SYNOPSIS
--------
'git-diff-helper' [-z] [-R] [-M]
'git-diff-helper' [-z] [-R] [-M] [-C]

DESCRIPTION
-----------
Expand All @@ -34,6 +34,8 @@ OPTIONS
-M::
Detect renames.

-C::
Detect copies as well as renames.

See Also
--------
Expand Down
6 changes: 5 additions & 1 deletion Documentation/git-diff-tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object

SYNOPSIS
--------
'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-m] [-s] [-v] <tree-ish> <tree-ish> [<pattern>]\*
'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-m] [-s] [-v] <tree-ish> <tree-ish> [<pattern>]\*

DESCRIPTION
-----------
Expand All @@ -36,6 +36,10 @@ OPTIONS
-M::
Detect renames; implies -p, in turn implying also '-r'.

-C::
Detect copies as well as renames; implies -p, in turn
implying also '-r'.

-R::
Output diff in reverse.

Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ LIB_H += strbuf.h
LIB_OBJS += strbuf.o

LIB_H += diff.h
LIB_OBJS += diff.o
LIB_OBJS += diff.o diffcore-rename.o

LIB_OBJS += gitenv.o

Expand Down Expand Up @@ -121,9 +121,10 @@ object.o: $(LIB_H)
read-cache.o: $(LIB_H)
sha1_file.o: $(LIB_H)
usage.o: $(LIB_H)
diff.o: $(LIB_H)
strbuf.o: $(LIB_H)
gitenv.o: $(LIB_H)
diff.o: $(LIB_H)
diffcore-rename.o : $(LIB_H)

test: all
make -C t/ all
Expand Down
8 changes: 7 additions & 1 deletion diff-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ static void mark_merge_entries(void)
}

static char *diff_cache_usage =
"git-diff-cache [-p] [-r] [-z] [-m] [-M] [-R] [--cached] <tree-ish>";
"git-diff-cache [-p] [-r] [-z] [-m] [-M] [-C] [-R] [--cached] <tree-ish>";

int main(int argc, char **argv)
{
Expand All @@ -180,6 +180,12 @@ int main(int argc, char **argv)
diff_score_opt = diff_scoreopt_parse(arg);
continue;
}
if (!strncmp(arg, "-C", 2)) {
generate_patch = 1;
detect_rename = 2;
diff_score_opt = diff_scoreopt_parse(arg);
continue;
}
if (!strcmp(arg, "-z")) {
line_termination = '\0';
continue;
Expand Down
7 changes: 6 additions & 1 deletion diff-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "diff.h"

static const char *diff_files_usage =
"git-diff-files [-p] [-q] [-r] [-z] [-M] [-R] [paths...]";
"git-diff-files [-p] [-q] [-r] [-z] [-M] [-C] [-R] [paths...]";

static int generate_patch = 0;
static int line_termination = '\n';
Expand Down Expand Up @@ -71,6 +71,11 @@ int main(int argc, char **argv)
diff_score_opt = diff_scoreopt_parse(argv[1]);
detect_rename = generate_patch = 1;
}
else if (!strncmp(argv[1], "-C", 2)) {
diff_score_opt = diff_scoreopt_parse(argv[1]);
detect_rename = 2;
generate_patch = 1;
}
else
usage(diff_files_usage);
argv++; argc--;
Expand Down
25 changes: 19 additions & 6 deletions diff-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

static int detect_rename = 0;
static int diff_score_opt = 0;
static int generate_patch = 1;

static int parse_oneside_change(const char *cp, int *mode,
unsigned char *sha1, char *path)
Expand All @@ -20,7 +21,8 @@ static int parse_oneside_change(const char *cp, int *mode,
cp++;
}
*mode = m;
if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6) &&
strncmp(cp, "\ttree\t", 6) && strncmp(cp, " tree ", 6))
return -1;
cp += 6;
if (get_sha1_hex(cp, sha1))
Expand All @@ -44,11 +46,13 @@ static int parse_diff_raw_output(const char *buf)
diff_unmerge(cp + 1);
break;
case '+':
parse_oneside_change(cp, &new_mode, new_sha1, path);
if (parse_oneside_change(cp, &new_mode, new_sha1, path))
return -1;
diff_addremove('+', new_mode, new_sha1, path, NULL);
break;
case '-':
parse_oneside_change(cp, &old_mode, old_sha1, path);
if (parse_oneside_change(cp, &old_mode, old_sha1, path))
return -1;
diff_addremove('-', old_mode, old_sha1, path, NULL);
break;
case '*':
Expand All @@ -64,7 +68,8 @@ static int parse_diff_raw_output(const char *buf)
new_mode = (new_mode << 3) | (ch - '0');
cp++;
}
if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6) &&
strncmp(cp, "\ttree\t", 6) && strncmp(cp, " tree ", 6))
return -1;
cp += 6;
if (get_sha1_hex(cp, old_sha1))
Expand All @@ -88,7 +93,7 @@ static int parse_diff_raw_output(const char *buf)
}

static const char *diff_helper_usage =
"git-diff-helper [-z] [-R] [-M] paths...";
"git-diff-helper [-z] [-R] [-M] [-C] paths...";

int main(int ac, const char **av) {
struct strbuf sb;
Expand All @@ -102,17 +107,25 @@ int main(int ac, const char **av) {
reverse = 1;
else if (av[1][1] == 'z')
line_termination = 0;
else if (av[1][1] == 'p') /* hidden from the help */
generate_patch = 0;
else if (av[1][1] == 'M') {
detect_rename = 1;
diff_score_opt = diff_scoreopt_parse(av[1]);
}
else if (av[1][1] == 'C') {
detect_rename = 2;
diff_score_opt = diff_scoreopt_parse(av[1]);
}
else
usage(diff_helper_usage);
ac--; av++;
}
/* the remaining parameters are paths patterns */

diff_setup(detect_rename, diff_score_opt, reverse, -1, av+1, ac-1);
diff_setup(detect_rename, diff_score_opt, reverse,
(generate_patch ? -1 : line_termination),
av+1, ac-1);

while (1) {
int status;
Expand Down
8 changes: 7 additions & 1 deletion diff-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ static int diff_tree_stdin(char *line)
}

static char *diff_tree_usage =
"git-diff-tree [-p] [-r] [-z] [--stdin] [-M] [-R] [-m] [-s] [-v] <tree-ish> <tree-ish>";
"git-diff-tree [-p] [-r] [-z] [--stdin] [-M] [-C] [-R] [-m] [-s] [-v] <tree-ish> <tree-ish>";

int main(int argc, char **argv)
{
Expand Down Expand Up @@ -478,6 +478,12 @@ int main(int argc, char **argv)
diff_score_opt = diff_scoreopt_parse(arg);
continue;
}
if (!strncmp(arg, "-C", 2)) {
detect_rename = 2;
recursive = generate_patch = 1;
diff_score_opt = diff_scoreopt_parse(arg);
continue;
}
if (!strcmp(arg, "-z")) {
line_termination = '\0';
continue;
Expand Down
Loading

0 comments on commit 427dcb4

Please sign in to comment.