20
20
#include "mailmap.h"
21
21
#include "parse-options.h"
22
22
#include "utf8.h"
23
+ #include "userdiff.h"
23
24
24
25
static char blame_usage [] = "git blame [options] [rev-opts] [rev] [--] file" ;
25
26
@@ -85,17 +86,51 @@ struct origin {
85
86
char path [FLEX_ARRAY ];
86
87
};
87
88
89
+ /*
90
+ * Prepare diff_filespec and convert it using diff textconv API
91
+ * if the textconv driver exists.
92
+ * Return 1 if the conversion succeeds, 0 otherwise.
93
+ */
94
+ static int textconv_object (const char * path ,
95
+ const unsigned char * sha1 ,
96
+ char * * buf ,
97
+ unsigned long * buf_size )
98
+ {
99
+ struct diff_filespec * df ;
100
+ struct userdiff_driver * textconv ;
101
+
102
+ df = alloc_filespec (path );
103
+ fill_filespec (df , sha1 , S_IFREG | 0664 );
104
+ textconv = get_textconv (df );
105
+ if (!textconv ) {
106
+ free_filespec (df );
107
+ return 0 ;
108
+ }
109
+
110
+ * buf_size = fill_textconv (textconv , df , buf );
111
+ free_filespec (df );
112
+ return 1 ;
113
+ }
114
+
88
115
/*
89
116
* Given an origin, prepare mmfile_t structure to be used by the
90
117
* diff machinery
91
118
*/
92
- static void fill_origin_blob (struct origin * o , mmfile_t * file )
119
+ static void fill_origin_blob (struct diff_options * opt ,
120
+ struct origin * o , mmfile_t * file )
93
121
{
94
122
if (!o -> file .ptr ) {
95
123
enum object_type type ;
124
+ unsigned long file_size ;
125
+
96
126
num_read_blob ++ ;
97
- file -> ptr = read_sha1_file (o -> blob_sha1 , & type ,
98
- (unsigned long * )(& (file -> size )));
127
+ if (DIFF_OPT_TST (opt , ALLOW_TEXTCONV ) &&
128
+ textconv_object (o -> path , o -> blob_sha1 , & file -> ptr , & file_size ))
129
+ ;
130
+ else
131
+ file -> ptr = read_sha1_file (o -> blob_sha1 , & type , & file_size );
132
+ file -> size = file_size ;
133
+
99
134
if (!file -> ptr )
100
135
die ("Cannot read blob %s for path %s" ,
101
136
sha1_to_hex (o -> blob_sha1 ),
@@ -282,7 +317,6 @@ static struct origin *get_origin(struct scoreboard *sb,
282
317
static int fill_blob_sha1 (struct origin * origin )
283
318
{
284
319
unsigned mode ;
285
-
286
320
if (!is_null_sha1 (origin -> blob_sha1 ))
287
321
return 0 ;
288
322
if (get_tree_entry (origin -> commit -> object .sha1 ,
@@ -741,8 +775,8 @@ static int pass_blame_to_parent(struct scoreboard *sb,
741
775
if (last_in_target < 0 )
742
776
return 1 ; /* nothing remains for this target */
743
777
744
- fill_origin_blob (parent , & file_p );
745
- fill_origin_blob (target , & file_o );
778
+ fill_origin_blob (& sb -> revs -> diffopt , parent , & file_p );
779
+ fill_origin_blob (& sb -> revs -> diffopt , target , & file_o );
746
780
num_get_patch ++ ;
747
781
748
782
memset (& xpp , 0 , sizeof (xpp ));
@@ -922,7 +956,7 @@ static int find_move_in_parent(struct scoreboard *sb,
922
956
if (last_in_target < 0 )
923
957
return 1 ; /* nothing remains for this target */
924
958
925
- fill_origin_blob (parent , & file_p );
959
+ fill_origin_blob (& sb -> revs -> diffopt , parent , & file_p );
926
960
if (!file_p .ptr )
927
961
return 0 ;
928
962
@@ -1063,7 +1097,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
1063
1097
1064
1098
norigin = get_origin (sb , parent , p -> one -> path );
1065
1099
hashcpy (norigin -> blob_sha1 , p -> one -> sha1 );
1066
- fill_origin_blob (norigin , & file_p );
1100
+ fill_origin_blob (& sb -> revs -> diffopt , norigin , & file_p );
1067
1101
if (!file_p .ptr )
1068
1102
continue ;
1069
1103
@@ -1983,14 +2017,26 @@ static int git_blame_config(const char *var, const char *value, void *cb)
1983
2017
blame_date_mode = parse_date_format (value );
1984
2018
return 0 ;
1985
2019
}
2020
+
2021
+ switch (userdiff_config (var , value )) {
2022
+ case 0 :
2023
+ break ;
2024
+ case -1 :
2025
+ return -1 ;
2026
+ default :
2027
+ return 0 ;
2028
+ }
2029
+
1986
2030
return git_default_config (var , value , cb );
1987
2031
}
1988
2032
1989
2033
/*
1990
2034
* Prepare a dummy commit that represents the work tree (or staged) item.
1991
2035
* Note that annotating work tree item never works in the reverse.
1992
2036
*/
1993
- static struct commit * fake_working_tree_commit (const char * path , const char * contents_from )
2037
+ static struct commit * fake_working_tree_commit (struct diff_options * opt ,
2038
+ const char * path ,
2039
+ const char * contents_from )
1994
2040
{
1995
2041
struct commit * commit ;
1996
2042
struct origin * origin ;
@@ -2018,6 +2064,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
2018
2064
if (!contents_from || strcmp ("-" , contents_from )) {
2019
2065
struct stat st ;
2020
2066
const char * read_from ;
2067
+ unsigned long buf_len ;
2021
2068
2022
2069
if (contents_from ) {
2023
2070
if (stat (contents_from , & st ) < 0 )
@@ -2030,9 +2077,13 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
2030
2077
read_from = path ;
2031
2078
}
2032
2079
mode = canon_mode (st .st_mode );
2080
+
2033
2081
switch (st .st_mode & S_IFMT ) {
2034
2082
case S_IFREG :
2035
- if (strbuf_read_file (& buf , read_from , st .st_size ) != st .st_size )
2083
+ if (DIFF_OPT_TST (opt , ALLOW_TEXTCONV ) &&
2084
+ textconv_object (read_from , null_sha1 , & buf .buf , & buf_len ))
2085
+ buf .len = buf_len ;
2086
+ else if (strbuf_read_file (& buf , read_from , st .st_size ) != st .st_size )
2036
2087
die_errno ("cannot open or read '%s'" , read_from );
2037
2088
break ;
2038
2089
case S_IFLNK :
@@ -2248,6 +2299,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2248
2299
git_config (git_blame_config , NULL );
2249
2300
init_revisions (& revs , NULL );
2250
2301
revs .date_mode = blame_date_mode ;
2302
+ DIFF_OPT_SET (& revs .diffopt , ALLOW_TEXTCONV );
2251
2303
2252
2304
save_commit_buffer = 0 ;
2253
2305
dashdash_pos = 0 ;
@@ -2384,7 +2436,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2384
2436
* or "--contents".
2385
2437
*/
2386
2438
setup_work_tree ();
2387
- sb .final = fake_working_tree_commit (path , contents_from );
2439
+ sb .final = fake_working_tree_commit (& sb .revs -> diffopt ,
2440
+ path , contents_from );
2388
2441
add_pending_object (& revs , & (sb .final -> object ), ":" );
2389
2442
}
2390
2443
else if (contents_from )
@@ -2411,8 +2464,14 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2411
2464
if (fill_blob_sha1 (o ))
2412
2465
die ("no such path %s in %s" , path , final_commit_name );
2413
2466
2414
- sb .final_buf = read_sha1_file (o -> blob_sha1 , & type ,
2415
- & sb .final_buf_size );
2467
+ if (DIFF_OPT_TST (& sb .revs -> diffopt , ALLOW_TEXTCONV ) &&
2468
+ textconv_object (path , o -> blob_sha1 , (char * * ) & sb .final_buf ,
2469
+ & sb .final_buf_size ))
2470
+ ;
2471
+ else
2472
+ sb .final_buf = read_sha1_file (o -> blob_sha1 , & type ,
2473
+ & sb .final_buf_size );
2474
+
2416
2475
if (!sb .final_buf )
2417
2476
die ("Cannot read blob %s for path %s" ,
2418
2477
sha1_to_hex (o -> blob_sha1 ),
0 commit comments