@@ -991,18 +991,23 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
991
991
}
992
992
}
993
993
994
- struct diffstat_dir {
995
- struct diffstat_file * * files ;
996
- int nr , percent , cumulative ;
994
+ struct dirstat_file {
995
+ const char * name ;
996
+ unsigned long changed ;
997
997
};
998
998
999
- static long gather_dirstat (FILE * file , struct diffstat_dir * dir , unsigned long changed , const char * base , int baselen )
999
+ struct dirstat_dir {
1000
+ struct dirstat_file * files ;
1001
+ int alloc , nr , percent , cumulative ;
1002
+ };
1003
+
1004
+ static long gather_dirstat (FILE * file , struct dirstat_dir * dir , unsigned long changed , const char * base , int baselen )
1000
1005
{
1001
1006
unsigned long this_dir = 0 ;
1002
1007
unsigned int sources = 0 ;
1003
1008
1004
1009
while (dir -> nr ) {
1005
- struct diffstat_file * f = * dir -> files ;
1010
+ struct dirstat_file * f = dir -> files ;
1006
1011
int namelen = strlen (f -> name );
1007
1012
unsigned long this ;
1008
1013
char * slash ;
@@ -1017,10 +1022,7 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c
1017
1022
this = gather_dirstat (file , dir , changed , f -> name , newbaselen );
1018
1023
sources ++ ;
1019
1024
} else {
1020
- if (f -> is_unmerged || f -> is_binary )
1021
- this = 0 ;
1022
- else
1023
- this = f -> added + f -> deleted ;
1025
+ this = f -> changed ;
1024
1026
dir -> files ++ ;
1025
1027
dir -> nr -- ;
1026
1028
sources += 2 ;
@@ -1048,30 +1050,65 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c
1048
1050
return this_dir ;
1049
1051
}
1050
1052
1051
- static void show_dirstat (struct diffstat_t * data , struct diff_options * options )
1053
+ static void show_dirstat (struct diff_options * options )
1052
1054
{
1053
1055
int i ;
1054
1056
unsigned long changed ;
1055
- struct diffstat_dir dir ;
1057
+ struct dirstat_dir dir ;
1058
+ struct diff_queue_struct * q = & diff_queued_diff ;
1059
+
1060
+ dir .files = NULL ;
1061
+ dir .alloc = 0 ;
1062
+ dir .nr = 0 ;
1063
+ dir .percent = options -> dirstat_percent ;
1064
+ dir .cumulative = options -> output_format & DIFF_FORMAT_CUMULATIVE ;
1056
1065
1057
- /* Calculate total changes */
1058
1066
changed = 0 ;
1059
- for (i = 0 ; i < data -> nr ; i ++ ) {
1060
- if (data -> files [i ]-> is_binary || data -> files [i ]-> is_unmerged )
1067
+ for (i = 0 ; i < q -> nr ; i ++ ) {
1068
+ struct diff_filepair * p = q -> queue [i ];
1069
+ const char * name ;
1070
+ unsigned long copied , added , damage ;
1071
+
1072
+ name = p -> one -> path ? p -> one -> path : p -> two -> path ;
1073
+
1074
+ if (DIFF_FILE_VALID (p -> one ) && DIFF_FILE_VALID (p -> two )) {
1075
+ diff_populate_filespec (p -> one , 0 );
1076
+ diff_populate_filespec (p -> two , 0 );
1077
+ diffcore_count_changes (p -> one , p -> two , NULL , NULL , 0 ,
1078
+ & copied , & added );
1079
+ diff_free_filespec_data (p -> one );
1080
+ diff_free_filespec_data (p -> two );
1081
+ } else if (DIFF_FILE_VALID (p -> one )) {
1082
+ diff_populate_filespec (p -> one , 1 );
1083
+ copied = added = 0 ;
1084
+ diff_free_filespec_data (p -> one );
1085
+ } else if (DIFF_FILE_VALID (p -> two )) {
1086
+ diff_populate_filespec (p -> two , 1 );
1087
+ copied = 0 ;
1088
+ added = p -> two -> size ;
1089
+ diff_free_filespec_data (p -> two );
1090
+ } else
1061
1091
continue ;
1062
- changed += data -> files [i ]-> added ;
1063
- changed += data -> files [i ]-> deleted ;
1092
+
1093
+ /*
1094
+ * Original minus copied is the removed material,
1095
+ * added is the new material. They are both damages
1096
+ * made to the preimage.
1097
+ */
1098
+ damage = (p -> one -> size - copied ) + added ;
1099
+
1100
+ ALLOC_GROW (dir .files , dir .nr + 1 , dir .alloc );
1101
+ dir .files [dir .nr ].name = name ;
1102
+ dir .files [dir .nr ].changed = damage ;
1103
+ changed += damage ;
1104
+ dir .nr ++ ;
1064
1105
}
1065
1106
1066
1107
/* This can happen even with many files, if everything was renames */
1067
1108
if (!changed )
1068
1109
return ;
1069
1110
1070
1111
/* Show all directories with more than x% of the changes */
1071
- dir .files = data -> files ;
1072
- dir .nr = data -> nr ;
1073
- dir .percent = options -> dirstat_percent ;
1074
- dir .cumulative = options -> output_format & DIFF_FORMAT_CUMULATIVE ;
1075
1112
gather_dirstat (options -> file , & dir , changed , "" , 0 );
1076
1113
}
1077
1114
@@ -3095,7 +3132,7 @@ void diff_flush(struct diff_options *options)
3095
3132
separator ++ ;
3096
3133
}
3097
3134
3098
- if (output_format & (DIFF_FORMAT_DIFFSTAT |DIFF_FORMAT_SHORTSTAT |DIFF_FORMAT_NUMSTAT | DIFF_FORMAT_DIRSTAT )) {
3135
+ if (output_format & (DIFF_FORMAT_DIFFSTAT |DIFF_FORMAT_SHORTSTAT |DIFF_FORMAT_NUMSTAT )) {
3099
3136
struct diffstat_t diffstat ;
3100
3137
3101
3138
memset (& diffstat , 0 , sizeof (struct diffstat_t ));
@@ -3105,8 +3142,6 @@ void diff_flush(struct diff_options *options)
3105
3142
if (check_pair_status (p ))
3106
3143
diff_flush_stat (p , options , & diffstat );
3107
3144
}
3108
- if (output_format & DIFF_FORMAT_DIRSTAT )
3109
- show_dirstat (& diffstat , options );
3110
3145
if (output_format & DIFF_FORMAT_NUMSTAT )
3111
3146
show_numstat (& diffstat , options );
3112
3147
if (output_format & DIFF_FORMAT_DIFFSTAT )
@@ -3116,6 +3151,8 @@ void diff_flush(struct diff_options *options)
3116
3151
free_diffstat_info (& diffstat );
3117
3152
separator ++ ;
3118
3153
}
3154
+ if (output_format & DIFF_FORMAT_DIRSTAT )
3155
+ show_dirstat (options );
3119
3156
3120
3157
if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty (q )) {
3121
3158
for (i = 0 ; i < q -> nr ; i ++ )
0 commit comments