@@ -83,6 +83,7 @@ struct origin {
83
83
struct commit * commit ;
84
84
mmfile_t file ;
85
85
unsigned char blob_sha1 [20 ];
86
+ unsigned mode ;
86
87
char path [FLEX_ARRAY ];
87
88
};
88
89
@@ -92,6 +93,7 @@ struct origin {
92
93
* Return 1 if the conversion succeeds, 0 otherwise.
93
94
*/
94
95
int textconv_object (const char * path ,
96
+ unsigned mode ,
95
97
const unsigned char * sha1 ,
96
98
char * * buf ,
97
99
unsigned long * buf_size )
@@ -100,7 +102,7 @@ int textconv_object(const char *path,
100
102
struct userdiff_driver * textconv ;
101
103
102
104
df = alloc_filespec (path );
103
- fill_filespec (df , sha1 , S_IFREG | 0664 );
105
+ fill_filespec (df , sha1 , mode );
104
106
textconv = get_textconv (df );
105
107
if (!textconv ) {
106
108
free_filespec (df );
@@ -125,7 +127,7 @@ static void fill_origin_blob(struct diff_options *opt,
125
127
126
128
num_read_blob ++ ;
127
129
if (DIFF_OPT_TST (opt , ALLOW_TEXTCONV ) &&
128
- textconv_object (o -> path , o -> blob_sha1 , & file -> ptr , & file_size ))
130
+ textconv_object (o -> path , o -> mode , o -> blob_sha1 , & file -> ptr , & file_size ))
129
131
;
130
132
else
131
133
file -> ptr = read_sha1_file (o -> blob_sha1 , & type , & file_size );
@@ -313,21 +315,23 @@ static struct origin *get_origin(struct scoreboard *sb,
313
315
* for an origin is also used to pass the blame for the entire file to
314
316
* the parent to detect the case where a child's blob is identical to
315
317
* that of its parent's.
318
+ *
319
+ * This also fills origin->mode for corresponding tree path.
316
320
*/
317
- static int fill_blob_sha1 (struct origin * origin )
321
+ static int fill_blob_sha1_and_mode (struct origin * origin )
318
322
{
319
- unsigned mode ;
320
323
if (!is_null_sha1 (origin -> blob_sha1 ))
321
324
return 0 ;
322
325
if (get_tree_entry (origin -> commit -> object .sha1 ,
323
326
origin -> path ,
324
- origin -> blob_sha1 , & mode ))
327
+ origin -> blob_sha1 , & origin -> mode ))
325
328
goto error_out ;
326
329
if (sha1_object_info (origin -> blob_sha1 , NULL ) != OBJ_BLOB )
327
330
goto error_out ;
328
331
return 0 ;
329
332
error_out :
330
333
hashclr (origin -> blob_sha1 );
334
+ origin -> mode = S_IFINVALID ;
331
335
return -1 ;
332
336
}
333
337
@@ -360,12 +364,14 @@ static struct origin *find_origin(struct scoreboard *sb,
360
364
/*
361
365
* If the origin was newly created (i.e. get_origin
362
366
* would call make_origin if none is found in the
363
- * scoreboard), it does not know the blob_sha1,
367
+ * scoreboard), it does not know the blob_sha1/mode ,
364
368
* so copy it. Otherwise porigin was in the
365
- * scoreboard and already knows blob_sha1.
369
+ * scoreboard and already knows blob_sha1/mode .
366
370
*/
367
- if (porigin -> refcnt == 1 )
371
+ if (porigin -> refcnt == 1 ) {
368
372
hashcpy (porigin -> blob_sha1 , cached -> blob_sha1 );
373
+ porigin -> mode = cached -> mode ;
374
+ }
369
375
return porigin ;
370
376
}
371
377
/* otherwise it was not very useful; free it */
@@ -400,6 +406,7 @@ static struct origin *find_origin(struct scoreboard *sb,
400
406
/* The path is the same as parent */
401
407
porigin = get_origin (sb , parent , origin -> path );
402
408
hashcpy (porigin -> blob_sha1 , origin -> blob_sha1 );
409
+ porigin -> mode = origin -> mode ;
403
410
} else {
404
411
/*
405
412
* Since origin->path is a pathspec, if the parent
@@ -425,6 +432,7 @@ static struct origin *find_origin(struct scoreboard *sb,
425
432
case 'M' :
426
433
porigin = get_origin (sb , parent , origin -> path );
427
434
hashcpy (porigin -> blob_sha1 , p -> one -> sha1 );
435
+ porigin -> mode = p -> one -> mode ;
428
436
break ;
429
437
case 'A' :
430
438
case 'T' :
@@ -444,6 +452,7 @@ static struct origin *find_origin(struct scoreboard *sb,
444
452
445
453
cached = make_origin (porigin -> commit , porigin -> path );
446
454
hashcpy (cached -> blob_sha1 , porigin -> blob_sha1 );
455
+ cached -> mode = porigin -> mode ;
447
456
parent -> util = cached ;
448
457
}
449
458
return porigin ;
@@ -486,6 +495,7 @@ static struct origin *find_rename(struct scoreboard *sb,
486
495
!strcmp (p -> two -> path , origin -> path )) {
487
496
porigin = get_origin (sb , parent , p -> one -> path );
488
497
hashcpy (porigin -> blob_sha1 , p -> one -> sha1 );
498
+ porigin -> mode = p -> one -> mode ;
489
499
break ;
490
500
}
491
501
}
@@ -1099,6 +1109,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
1099
1109
1100
1110
norigin = get_origin (sb , parent , p -> one -> path );
1101
1111
hashcpy (norigin -> blob_sha1 , p -> one -> sha1 );
1112
+ norigin -> mode = p -> one -> mode ;
1102
1113
fill_origin_blob (& sb -> revs -> diffopt , norigin , & file_p );
1103
1114
if (!file_p .ptr )
1104
1115
continue ;
@@ -2083,7 +2094,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
2083
2094
switch (st .st_mode & S_IFMT ) {
2084
2095
case S_IFREG :
2085
2096
if (DIFF_OPT_TST (opt , ALLOW_TEXTCONV ) &&
2086
- textconv_object (read_from , null_sha1 , & buf .buf , & buf_len ))
2097
+ textconv_object (read_from , mode , null_sha1 , & buf .buf , & buf_len ))
2087
2098
buf .len = buf_len ;
2088
2099
else if (strbuf_read_file (& buf , read_from , st .st_size ) != st .st_size )
2089
2100
die_errno ("cannot open or read '%s'" , read_from );
@@ -2463,11 +2474,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2463
2474
}
2464
2475
else {
2465
2476
o = get_origin (& sb , sb .final , path );
2466
- if (fill_blob_sha1 (o ))
2477
+ if (fill_blob_sha1_and_mode (o ))
2467
2478
die ("no such path %s in %s" , path , final_commit_name );
2468
2479
2469
2480
if (DIFF_OPT_TST (& sb .revs -> diffopt , ALLOW_TEXTCONV ) &&
2470
- textconv_object (path , o -> blob_sha1 , (char * * ) & sb .final_buf ,
2481
+ textconv_object (path , o -> mode , o -> blob_sha1 , (char * * ) & sb .final_buf ,
2471
2482
& sb .final_buf_size ))
2472
2483
;
2473
2484
else
0 commit comments