Skip to content

Commit b6d8f30

Browse files
Junio C HamanoLinus Torvalds
authored andcommitted
[PATCH] diff-raw format update take #2.
This changes the diff-raw format again, following the mailing list discussion. The new format explicitly expresses which one is a rename and which one is a copy. The documentation and tests are updated to match this change. Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent a4acb0e commit b6d8f30

13 files changed

+494
-366
lines changed

Documentation/diff-format.txt

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,34 @@ git-diff-files [<pattern>...]::
1919

2020
An output line is formatted this way:
2121

22-
':' <mode> ' ' <mode> ' ' <sha1> ' ' <sha1> I <path> I <path> L
23-
24-
By default, I and L are '\t' and '\n' respectively. When '-z'
25-
flag is in effect, both I and L are '\0'.
26-
27-
In each <mode>, <sha1> and <path> pair, left hand side describes
28-
the left hand side of what is being compared (<tree-ish> in
29-
git-diff-cache, <tree-ish-1> in git-diff-tree, cache contents in
30-
git-diff-files). Non-existence is shown by having 000000 in the
31-
<mode> column. That is, 000000 appears as the first <mode> for
32-
newly created files, and as the second <mode> for deleted files.
33-
34-
Usually two <path> are the same. When rename/copy detection is
35-
used, however, an "create" and another "delete" records can be
36-
merged into a single record that has two <path>, old name and
37-
new name.
22+
in-place edit :100644 100644 bcd1234... 0123456... M file0
23+
copy-edit :100644 100644 abcd123... 1234567... C68 file1 file2
24+
rename-edit :100644 100644 abcd123... 1234567... R86 file1 file3
25+
create :000000 100644 0000000... 1234567... N file4
26+
delete :100644 000000 1234567... 0000000... D file5
27+
unmerged :000000 000000 0000000... 0000000... U file6
28+
29+
That is, from the left to the right:
30+
31+
(1) a colon.
32+
(2) mode for "src"; 000000 if creation or unmerged.
33+
(3) a space.
34+
(4) mode for "dst"; 000000 if deletion or unmerged.
35+
(5) a space.
36+
(6) sha1 for "src"; 0{40} if creation or unmerged.
37+
(7) a space.
38+
(8) sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree".
39+
(9) status, followed by similarlity index number only for C and R.
40+
(10) a tab or a NUL when '-z' option is used.
41+
(11) path for "src"
42+
(12) a tab or a NUL when '-z' option is used; only exists for C or R.
43+
(13) path for "dst"; only exists for C or R.
44+
(14) an LF or a NUL when '-z' option is used, to terminate the record.
3845

3946
<sha1> is shown as all 0's if new is a file on the filesystem
4047
and it is out of sync with the cache. Example:
4148

42-
:100644 100644 5be4a4...... 000000...... file.c file.c
43-
49+
:100644 100644 5be4a4...... 000000...... M file.c
4450

4551
Generating patches with -p
4652
--------------------------

Documentation/git-diff-helper.txt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-diff-helper - Generates patch format output for git-diff-*
99

1010
SYNOPSIS
1111
--------
12-
'git-diff-helper' [-z] [-R] [-M] [-C] [-S<string>]
12+
'git-diff-helper' [-z] [-S<string>]
1313

1414
DESCRIPTION
1515
-----------
@@ -21,22 +21,6 @@ OPTIONS
2121
-z::
2222
\0 line termination on input
2323

24-
-R::
25-
Output diff in reverse. This is useful for displaying output from
26-
"git-diff-cache" which always compares tree with cache or working
27-
file. E.g.
28-
29-
git-diff-cache <tree> | git-diff-helper -R file.c
30-
31-
would show a diff to bring the working file back to what
32-
is in the <tree>.
33-
34-
-M::
35-
Detect renames.
36-
37-
-C::
38-
Detect copies as well as renames.
39-
4024
-S<string>::
4125
Look for differences that contains the change in <string>.
4226

diff-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,6 @@ int main(int argc, const char **argv)
234234
diffcore_pickaxe(pickaxe);
235235
if (2 <= argc)
236236
diffcore_pathspec(argv + 1);
237-
diff_flush(diff_output_format);
237+
diff_flush(diff_output_format, 1);
238238
return ret;
239239
}

diff-files.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,6 @@ int main(int argc, const char **argv)
120120
diffcore_pickaxe(pickaxe);
121121
if (1 < argc)
122122
diffcore_pathspec(argv + 1);
123-
diff_flush(diff_output_format);
123+
diff_flush(diff_output_format, 1);
124124
return 0;
125125
}

diff-helper.c

Lines changed: 103 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,84 +5,21 @@
55
#include "strbuf.h"
66
#include "diff.h"
77

8-
static int detect_rename = 0;
9-
static int diff_score_opt = 0;
108
static const char *pickaxe = NULL;
11-
static int diff_output_style = DIFF_FORMAT_PATCH;
129
static int line_termination = '\n';
1310
static int inter_name_termination = '\t';
1411

15-
static int parse_diff_raw(char *buf1, char *buf2, char *buf3)
16-
{
17-
char old_path[PATH_MAX];
18-
unsigned char old_sha1[20], new_sha1[20];
19-
char *ep;
20-
char *cp = buf1;
21-
int ch, old_mode, new_mode;
22-
23-
old_mode = new_mode = 0;
24-
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
25-
old_mode = (old_mode << 3) | (ch - '0');
26-
cp++;
27-
}
28-
if (*cp++ != ' ')
29-
return -1;
30-
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
31-
new_mode = (new_mode << 3) | (ch - '0');
32-
cp++;
33-
}
34-
if (*cp++ != ' ')
35-
return -1;
36-
if (get_sha1_hex(cp, old_sha1))
37-
return -1;
38-
cp += 40;
39-
if (*cp++ != ' ')
40-
return -1;
41-
if (get_sha1_hex(cp, new_sha1))
42-
return -1;
43-
cp += 40;
44-
if (*cp++ != inter_name_termination)
45-
return -1;
46-
if (buf2)
47-
cp = buf2;
48-
ep = strchr(cp, inter_name_termination);
49-
if (!ep)
50-
return -1;
51-
*ep++ = 0;
52-
strcpy(old_path, cp);
53-
diff_guif(old_mode, new_mode, old_sha1, new_sha1,
54-
old_path, buf3 ? buf3 : ep);
55-
return 0;
56-
}
57-
5812
static const char *diff_helper_usage =
59-
"git-diff-helper [-z] [-R] [-M] [-C] [-S<string>] paths...";
13+
"git-diff-helper [-z] [-S<string>] paths...";
6014

6115
int main(int ac, const char **av) {
62-
struct strbuf sb1, sb2, sb3;
63-
int reverse_diff = 0;
16+
struct strbuf sb;
6417

65-
strbuf_init(&sb1);
66-
strbuf_init(&sb2);
67-
strbuf_init(&sb3);
18+
strbuf_init(&sb);
6819

6920
while (1 < ac && av[1][0] == '-') {
70-
if (av[1][1] == 'R')
71-
reverse_diff = 1;
72-
else if (av[1][1] == 'z')
21+
if (av[1][1] == 'z')
7322
line_termination = inter_name_termination = 0;
74-
else if (av[1][1] == 'p') /* hidden from the help */
75-
diff_output_style = DIFF_FORMAT_HUMAN;
76-
else if (av[1][1] == 'P') /* hidden from the help */
77-
diff_output_style = DIFF_FORMAT_MACHINE;
78-
else if (av[1][1] == 'M') {
79-
detect_rename = DIFF_DETECT_RENAME;
80-
diff_score_opt = diff_scoreopt_parse(av[1]);
81-
}
82-
else if (av[1][1] == 'C') {
83-
detect_rename = DIFF_DETECT_COPY;
84-
diff_score_opt = diff_scoreopt_parse(av[1]);
85-
}
8623
else if (av[1][1] == 'S') {
8724
pickaxe = av[1] + 2;
8825
}
@@ -92,45 +29,114 @@ int main(int ac, const char **av) {
9229
}
9330
/* the remaining parameters are paths patterns */
9431

95-
diff_setup(reverse_diff);
32+
diff_setup(0);
9633
while (1) {
97-
int status;
98-
read_line(&sb1, stdin, line_termination);
99-
if (sb1.eof)
34+
unsigned old_mode, new_mode;
35+
unsigned char old_sha1[20], new_sha1[20];
36+
char old_path[PATH_MAX];
37+
int status, score, two_paths;
38+
char new_path[PATH_MAX];
39+
40+
int ch;
41+
char *cp, *ep;
42+
43+
read_line(&sb, stdin, line_termination);
44+
if (sb.eof)
10045
break;
101-
switch (sb1.buf[0]) {
102-
case 'U':
103-
diff_unmerge(sb1.buf + 2);
104-
continue;
46+
switch (sb.buf[0]) {
10547
case ':':
106-
break;
107-
default:
108-
goto unrecognized;
109-
}
110-
if (!line_termination) {
111-
read_line(&sb2, stdin, line_termination);
112-
if (sb2.eof)
48+
/* parse the first part up to the status */
49+
cp = sb.buf + 1;
50+
old_mode = new_mode = 0;
51+
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
52+
old_mode = (old_mode << 3) | (ch - '0');
53+
cp++;
54+
}
55+
if (*cp++ != ' ')
11356
break;
114-
read_line(&sb3, stdin, line_termination);
115-
if (sb3.eof)
57+
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
58+
new_mode = (new_mode << 3) | (ch - '0');
59+
cp++;
60+
}
61+
if (*cp++ != ' ')
11662
break;
117-
status = parse_diff_raw(sb1.buf+1, sb2.buf, sb3.buf);
118-
}
119-
else
120-
status = parse_diff_raw(sb1.buf+1, NULL, NULL);
121-
if (status) {
122-
unrecognized:
123-
diff_flush(diff_output_style);
124-
printf("%s\n", sb1.buf);
63+
if (get_sha1_hex(cp, old_sha1))
64+
break;
65+
cp += 40;
66+
if (*cp++ != ' ')
67+
break;
68+
if (get_sha1_hex(cp, new_sha1))
69+
break;
70+
cp += 40;
71+
if (*cp++ != ' ')
72+
break;
73+
status = *cp++;
74+
if (!strchr("MCRNDU", status))
75+
break;
76+
two_paths = score = 0;
77+
if (status == 'R' || status == 'C') {
78+
two_paths = 1;
79+
sscanf(cp, "%d", &score);
80+
if (line_termination) {
81+
cp = strchr(cp,
82+
inter_name_termination);
83+
if (!cp)
84+
break;
85+
}
86+
}
87+
88+
if (*cp++ != inter_name_termination)
89+
break;
90+
91+
/* first pathname */
92+
if (!line_termination) {
93+
read_line(&sb, stdin, line_termination);
94+
if (sb.eof)
95+
break;
96+
strcpy(old_path, sb.buf);
97+
}
98+
else if (!two_paths)
99+
strcpy(old_path, cp);
100+
else {
101+
ep = strchr(cp, inter_name_termination);
102+
if (!ep)
103+
break;
104+
strncpy(old_path, cp, ep-cp);
105+
old_path[ep-cp] = 0;
106+
cp = ep + 1;
107+
}
108+
109+
/* second pathname */
110+
if (!two_paths)
111+
strcpy(new_path, old_path);
112+
else {
113+
if (!line_termination) {
114+
read_line(&sb, stdin,
115+
line_termination);
116+
if (sb.eof)
117+
break;
118+
strcpy(new_path, sb.buf);
119+
}
120+
else
121+
strcpy(new_path, cp);
122+
}
123+
diff_helper_input(old_mode, new_mode,
124+
old_sha1, new_sha1,
125+
old_path, status, score,
126+
new_path);
127+
continue;
125128
}
129+
if (pickaxe)
130+
diffcore_pickaxe(pickaxe);
131+
if (1 < ac)
132+
diffcore_pathspec(av + 1);
133+
diff_flush(DIFF_FORMAT_PATCH, 0);
134+
printf("%s\n", sb.buf);
126135
}
127-
if (detect_rename)
128-
diffcore_rename(detect_rename, diff_score_opt);
129-
diffcore_prune();
130136
if (pickaxe)
131137
diffcore_pickaxe(pickaxe);
132-
if (ac)
138+
if (1 < ac)
133139
diffcore_pathspec(av + 1);
134-
diff_flush(diff_output_style);
140+
diff_flush(DIFF_FORMAT_PATCH, 0);
135141
return 0;
136142
}

diff-tree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ static int call_diff_flush(void)
270270
if (pickaxe) {
271271
diffcore_pickaxe(pickaxe);
272272
if (diff_queue_is_empty()) {
273-
diff_flush(DIFF_FORMAT_NO_OUTPUT);
273+
diff_flush(DIFF_FORMAT_NO_OUTPUT, 0);
274274
return 0;
275275
}
276276
}
@@ -291,7 +291,7 @@ static int call_diff_flush(void)
291291
}
292292
header = NULL;
293293
}
294-
diff_flush(diff_output_format);
294+
diff_flush(diff_output_format, 1);
295295
return 1;
296296
}
297297

0 commit comments

Comments
 (0)