1+ /*
2+ * Copyright (C) 2005 Junio C Hamano
3+ */
14#include "cache.h"
25#include "strbuf.h"
36#include "diff.h"
@@ -17,15 +20,22 @@ static int matches_pathspec(const char *name, char **spec, int cnt)
1720 return 0 ;
1821}
1922
20- static int parse_oneside_change (const char * cp , unsigned char * sha1 ,
21- char * path ) {
23+ static int parse_oneside_change (const char * cp , struct diff_spec * one ,
24+ char * path )
25+ {
2226 int ch ;
23- while ((ch = * cp ) && '0' <= ch && ch <= '7' )
24- cp ++ ; /* skip mode bits */
27+
28+ one -> file_valid = one -> sha1_valid = 1 ;
29+ one -> mode = 0 ;
30+ while ((ch = * cp ) && '0' <= ch && ch <= '7' ) {
31+ one -> mode = (one -> mode << 3 ) | (ch - '0' );
32+ cp ++ ;
33+ }
34+
2535 if (strncmp (cp , "\tblob\t" , 6 ))
2636 return -1 ;
2737 cp += 6 ;
28- if (get_sha1_hex (cp , sha1 ))
38+ if (get_sha1_hex (cp , one -> u . sha1 ))
2939 return -1 ;
3040 cp += 40 ;
3141 if (* cp ++ != '\t' )
@@ -34,223 +44,57 @@ static int parse_oneside_change(const char *cp, unsigned char *sha1,
3444 return 0 ;
3545}
3646
37- #define STATUS_CACHED 0 /* cached and sha1 valid */
38- #define STATUS_ABSENT 1 /* diff-tree says old removed or new added */
39- #define STATUS_UNCACHED 2 /* diff-cache output: read from working tree */
40-
4147static int parse_diff_tree_output (const char * buf ,
42- unsigned char * old_sha1 ,
43- int * old_status ,
44- unsigned char * new_sha1 ,
45- int * new_status ,
48+ struct diff_spec * old ,
49+ struct diff_spec * new ,
4650 char * path ) {
4751 const char * cp = buf ;
4852 int ch ;
49- static unsigned char null_sha [20 ] = { 0 , };
5053
5154 switch (* cp ++ ) {
5255 case '+' :
53- * old_status = STATUS_ABSENT ;
54- * new_status = (memcmp (new_sha1 , null_sha , sizeof (null_sha )) ?
55- STATUS_CACHED : STATUS_UNCACHED );
56- return parse_oneside_change (cp , new_sha1 , path );
56+ old -> file_valid = 0 ;
57+ return parse_oneside_change (cp , new , path );
5758 case '-' :
58- * new_status = STATUS_ABSENT ;
59- * old_status = (memcmp (old_sha1 , null_sha , sizeof (null_sha )) ?
60- STATUS_CACHED : STATUS_UNCACHED );
61- return parse_oneside_change (cp , old_sha1 , path );
59+ new -> file_valid = 0 ;
60+ return parse_oneside_change (cp , old , path );
6261 case '*' :
6362 break ;
6463 default :
6564 return -1 ;
6665 }
6766
6867 /* This is for '*' entries */
69- while ((ch = * cp ) && ('0' <= ch && ch <= '7' ))
70- cp ++ ; /* skip mode bits */
68+ old -> file_valid = old -> sha1_valid = 1 ;
69+ new -> file_valid = new -> sha1_valid = 1 ;
70+
71+ old -> mode = new -> mode = 0 ;
72+ while ((ch = * cp ) && ('0' <= ch && ch <= '7' )) {
73+ old -> mode = (old -> mode << 3 ) | (ch - '0' );
74+ cp ++ ;
75+ }
7176 if (strncmp (cp , "->" , 2 ))
7277 return -1 ;
7378 cp += 2 ;
74- while ((ch = * cp ) && ('0' <= ch && ch <= '7' ))
75- cp ++ ; /* skip mode bits */
79+ while ((ch = * cp ) && ('0' <= ch && ch <= '7' )) {
80+ new -> mode = (new -> mode << 3 ) | (ch - '0' );
81+ cp ++ ;
82+ }
7683 if (strncmp (cp , "\tblob\t" , 6 ))
7784 return -1 ;
7885 cp += 6 ;
79- if (get_sha1_hex (cp , old_sha1 ))
86+ if (get_sha1_hex (cp , old -> u . sha1 ))
8087 return -1 ;
8188 cp += 40 ;
8289 if (strncmp (cp , "->" , 2 ))
8390 return -1 ;
8491 cp += 2 ;
85- if (get_sha1_hex (cp , new_sha1 ))
92+ if (get_sha1_hex (cp , new -> u . sha1 ))
8693 return -1 ;
8794 cp += 40 ;
8895 if (* cp ++ != '\t' )
8996 return -1 ;
9097 strcpy (path , cp );
91- * old_status = (memcmp (old_sha1 , null_sha , sizeof (null_sha )) ?
92- STATUS_CACHED : STATUS_UNCACHED );
93- * new_status = (memcmp (new_sha1 , null_sha , sizeof (null_sha )) ?
94- STATUS_CACHED : STATUS_UNCACHED );
95- return 0 ;
96- }
97-
98- static int sha1err (const char * path , const unsigned char * sha1 )
99- {
100- return error ("diff-tree-helper: unable to read sha1 file of %s (%s)" ,
101- path , sha1_to_hex (sha1 ));
102- }
103-
104- static int fserr (const char * path )
105- {
106- return error ("diff-tree-helper: unable to read file %s" , path );
107- }
108-
109- static char * map_whole_file (const char * path , unsigned long * size ) {
110- int fd ;
111- struct stat st ;
112- void * buf ;
113-
114- if ((fd = open (path , O_RDONLY )) < 0 ) {
115- error ("diff-tree-helper: unable to read file %s" , path );
116- return 0 ;
117- }
118- if (fstat (fd , & st ) < 0 ) {
119- close (fd );
120- error ("diff-tree-helper: unable to stat file %s" , path );
121- return 0 ;
122- }
123- * size = st .st_size ;
124- buf = mmap (NULL , st .st_size , PROT_READ , MAP_PRIVATE , fd , 0 );
125- close (fd );
126- return buf ;
127- }
128-
129- static int show_diff (const unsigned char * old_sha1 , int old_status ,
130- const unsigned char * new_sha1 , int new_status ,
131- const char * path , int reverse_diff )
132- {
133- char other [PATH_MAX ];
134- unsigned long size ;
135- char type [20 ];
136- int fd ;
137- int reverse ;
138- void * blob = 0 ;
139- const char * fs = 0 ;
140- int need_unmap = 0 ;
141- int need_unlink = 0 ;
142-
143-
144- switch (old_status ) {
145- case STATUS_CACHED :
146- blob = read_sha1_file (old_sha1 , type , & size );
147- if (! blob )
148- return sha1err (path , old_sha1 );
149-
150- switch (new_status ) {
151- case STATUS_CACHED :
152- strcpy (other , ".diff_tree_helper_XXXXXX" );
153- fd = mkstemp (other );
154- if (fd < 0 )
155- die ("unable to create temp-file" );
156- if (write (fd , blob , size ) != size )
157- die ("unable to write temp-file" );
158- close (fd );
159- free (blob );
160-
161- blob = read_sha1_file (new_sha1 , type , & size );
162- if (! blob )
163- return sha1err (path , new_sha1 );
164-
165- need_unlink = 1 ;
166- /* new = blob, old = fs */
167- reverse = !reverse_diff ;
168- fs = other ;
169- break ;
170-
171- case STATUS_ABSENT :
172- case STATUS_UNCACHED :
173- fs = ((new_status == STATUS_ABSENT ) ?
174- "/dev/null" : path );
175- reverse = reverse_diff ;
176- break ;
177-
178- default :
179- reverse = reverse_diff ;
180- }
181- break ;
182-
183- case STATUS_ABSENT :
184- switch (new_status ) {
185- case STATUS_CACHED :
186- blob = read_sha1_file (new_sha1 , type , & size );
187- if (! blob )
188- return sha1err (path , new_sha1 );
189- /* old = fs, new = blob */
190- fs = "/dev/null" ;
191- reverse = !reverse_diff ;
192- break ;
193-
194- case STATUS_ABSENT :
195- return error ("diff-tree-helper: absent from both old and new?" );
196- case STATUS_UNCACHED :
197- fs = path ;
198- blob = strdup ("" );
199- size = 0 ;
200- /* old = blob, new = fs */
201- reverse = reverse_diff ;
202- break ;
203- default :
204- reverse = reverse_diff ;
205- }
206- break ;
207-
208- case STATUS_UNCACHED :
209- fs = path ; /* old = fs, new = blob */
210- reverse = !reverse_diff ;
211-
212- switch (new_status ) {
213- case STATUS_CACHED :
214- blob = read_sha1_file (new_sha1 , type , & size );
215- if (! blob )
216- return sha1err (path , new_sha1 );
217- break ;
218-
219- case STATUS_ABSENT :
220- blob = strdup ("" );
221- size = 0 ;
222- break ;
223-
224- case STATUS_UNCACHED :
225- /* old = fs */
226- blob = map_whole_file (path , & size );
227- if (! blob )
228- return fserr (path );
229- need_unmap = 1 ;
230- break ;
231- default :
232- reverse = reverse_diff ;
233- }
234- break ;
235-
236- default :
237- reverse = reverse_diff ;
238- }
239-
240- if (fs )
241- show_differences (fs ,
242- path , /* label */
243- blob ,
244- size ,
245- reverse /* 0: diff blob fs
246- 1: diff fs blob */ );
247-
248- if (need_unlink )
249- unlink (other );
250- if (need_unmap && blob )
251- munmap (blob , size );
252- else
253- free (blob );
25498 return 0 ;
25599}
256100
@@ -275,28 +119,20 @@ int main(int ac, char **av) {
275119 }
276120 /* the remaining parameters are paths patterns */
277121
278- prepare_diff_cmd ();
279-
280122 while (1 ) {
281- int old_status , new_status ;
282- unsigned char old_sha1 [20 ], new_sha1 [20 ];
123+ struct diff_spec old , new ;
283124 char path [PATH_MAX ];
284125 read_line (& sb , stdin , line_termination );
285126 if (sb .eof )
286127 break ;
287- if (parse_diff_tree_output (sb .buf ,
288- old_sha1 , & old_status ,
289- new_sha1 , & new_status ,
290- path )) {
128+ if (parse_diff_tree_output (sb .buf , & old , & new , path )) {
291129 fprintf (stderr , "cannot parse %s\n" , sb .buf );
292130 continue ;
293131 }
294- if (1 < ac && ! matches_pathspec (path , av + 1 , ac - 1 ))
132+ if (1 < ac && !matches_pathspec (path , av + 1 , ac - 1 ))
295133 continue ;
296134
297- show_diff (old_sha1 , old_status ,
298- new_sha1 , new_status ,
299- path , reverse_diff );
135+ run_external_diff (path , & old , & new );
300136 }
301137 return 0 ;
302138}
0 commit comments