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 ,
@@ -742,8 +776,8 @@ static int pass_blame_to_parent(struct scoreboard *sb,
742
776
if (last_in_target < 0 )
743
777
return 1 ; /* nothing remains for this target */
744
778
745
- fill_origin_blob (parent , & file_p );
746
- fill_origin_blob (target , & file_o );
779
+ fill_origin_blob (& sb -> revs -> diffopt , parent , & file_p );
780
+ fill_origin_blob (& sb -> revs -> diffopt , target , & file_o );
747
781
num_get_patch ++ ;
748
782
749
783
memset (& xpp , 0 , sizeof (xpp ));
@@ -924,7 +958,7 @@ static int find_move_in_parent(struct scoreboard *sb,
924
958
if (last_in_target < 0 )
925
959
return 1 ; /* nothing remains for this target */
926
960
927
- fill_origin_blob (parent , & file_p );
961
+ fill_origin_blob (& sb -> revs -> diffopt , parent , & file_p );
928
962
if (!file_p .ptr )
929
963
return 0 ;
930
964
@@ -1065,7 +1099,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
1065
1099
1066
1100
norigin = get_origin (sb , parent , p -> one -> path );
1067
1101
hashcpy (norigin -> blob_sha1 , p -> one -> sha1 );
1068
- fill_origin_blob (norigin , & file_p );
1102
+ fill_origin_blob (& sb -> revs -> diffopt , norigin , & file_p );
1069
1103
if (!file_p .ptr )
1070
1104
continue ;
1071
1105
@@ -1985,14 +2019,26 @@ static int git_blame_config(const char *var, const char *value, void *cb)
1985
2019
blame_date_mode = parse_date_format (value );
1986
2020
return 0 ;
1987
2021
}
2022
+
2023
+ switch (userdiff_config (var , value )) {
2024
+ case 0 :
2025
+ break ;
2026
+ case -1 :
2027
+ return -1 ;
2028
+ default :
2029
+ return 0 ;
2030
+ }
2031
+
1988
2032
return git_default_config (var , value , cb );
1989
2033
}
1990
2034
1991
2035
/*
1992
2036
* Prepare a dummy commit that represents the work tree (or staged) item.
1993
2037
* Note that annotating work tree item never works in the reverse.
1994
2038
*/
1995
- static struct commit * fake_working_tree_commit (const char * path , const char * contents_from )
2039
+ static struct commit * fake_working_tree_commit (struct diff_options * opt ,
2040
+ const char * path ,
2041
+ const char * contents_from )
1996
2042
{
1997
2043
struct commit * commit ;
1998
2044
struct origin * origin ;
@@ -2020,6 +2066,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
2020
2066
if (!contents_from || strcmp ("-" , contents_from )) {
2021
2067
struct stat st ;
2022
2068
const char * read_from ;
2069
+ unsigned long buf_len ;
2023
2070
2024
2071
if (contents_from ) {
2025
2072
if (stat (contents_from , & st ) < 0 )
@@ -2032,9 +2079,13 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
2032
2079
read_from = path ;
2033
2080
}
2034
2081
mode = canon_mode (st .st_mode );
2082
+
2035
2083
switch (st .st_mode & S_IFMT ) {
2036
2084
case S_IFREG :
2037
- if (strbuf_read_file (& buf , read_from , st .st_size ) != st .st_size )
2085
+ if (DIFF_OPT_TST (opt , ALLOW_TEXTCONV ) &&
2086
+ textconv_object (read_from , null_sha1 , & buf .buf , & buf_len ))
2087
+ buf .len = buf_len ;
2088
+ else if (strbuf_read_file (& buf , read_from , st .st_size ) != st .st_size )
2038
2089
die_errno ("cannot open or read '%s'" , read_from );
2039
2090
break ;
2040
2091
case S_IFLNK :
@@ -2250,6 +2301,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2250
2301
git_config (git_blame_config , NULL );
2251
2302
init_revisions (& revs , NULL );
2252
2303
revs .date_mode = blame_date_mode ;
2304
+ DIFF_OPT_SET (& revs .diffopt , ALLOW_TEXTCONV );
2253
2305
2254
2306
save_commit_buffer = 0 ;
2255
2307
dashdash_pos = 0 ;
@@ -2386,7 +2438,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2386
2438
* or "--contents".
2387
2439
*/
2388
2440
setup_work_tree ();
2389
- sb .final = fake_working_tree_commit (path , contents_from );
2441
+ sb .final = fake_working_tree_commit (& sb .revs -> diffopt ,
2442
+ path , contents_from );
2390
2443
add_pending_object (& revs , & (sb .final -> object ), ":" );
2391
2444
}
2392
2445
else if (contents_from )
@@ -2413,8 +2466,14 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2413
2466
if (fill_blob_sha1 (o ))
2414
2467
die ("no such path %s in %s" , path , final_commit_name );
2415
2468
2416
- sb .final_buf = read_sha1_file (o -> blob_sha1 , & type ,
2417
- & sb .final_buf_size );
2469
+ if (DIFF_OPT_TST (& sb .revs -> diffopt , ALLOW_TEXTCONV ) &&
2470
+ textconv_object (path , o -> blob_sha1 , (char * * ) & sb .final_buf ,
2471
+ & sb .final_buf_size ))
2472
+ ;
2473
+ else
2474
+ sb .final_buf = read_sha1_file (o -> blob_sha1 , & type ,
2475
+ & sb .final_buf_size );
2476
+
2418
2477
if (!sb .final_buf )
2419
2478
die ("Cannot read blob %s for path %s" ,
2420
2479
sha1_to_hex (o -> blob_sha1 ),
0 commit comments