Skip to content

Commit 441bca0

Browse files
torvaldsgitster
authored andcommitted
Fix '--dirstat' with cross-directory renaming
The dirstat code depends on the fact that we always generate diffs with the names sorted, since it then just does a single-pass walk-over of the sorted list of names and how many changes there were. The sorting means that all files are nicely grouped by directory. That all works fine. Except when we have rename detection, and suddenly the nicely sorted list of pathnames isn't all that sorted at all. And now the single-pass dirstat walk gets all confused, and you can get results like this: [torvalds@nehalem linux]$ git diff --dirstat=2 -M v2.6.27-rc4..v2.6.27-rc5 3.0% arch/powerpc/configs/ 6.8% arch/arm/configs/ 2.7% arch/powerpc/configs/ 4.2% arch/arm/configs/ 5.6% arch/powerpc/configs/ 8.4% arch/arm/configs/ 5.5% arch/powerpc/configs/ 23.3% arch/arm/configs/ 8.6% arch/powerpc/configs/ 4.0% arch/ 4.4% drivers/usb/musb/ 4.0% drivers/watchdog/ 7.6% drivers/ 3.5% fs/ The trivial fix is to add a sorting pass, fixing it to: [torvalds@nehalem linux]$ git diff --dirstat=2 -M v2.6.27-rc4..v2.6.27-rc5 43.0% arch/arm/configs/ 25.5% arch/powerpc/configs/ 5.3% arch/ 4.4% drivers/usb/musb/ 4.0% drivers/watchdog/ 7.6% drivers/ 3.5% fs/ Spot the difference. In case anybody wonders: it's because of a ton of renames from {include/asm-blackfin => arch/blackfin/include/asm} that just totally messed up the file ordering in between arch/arm and arch/powerpc. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 114ef90 commit 441bca0

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

diff.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,13 @@ static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long ch
10541054
return this_dir;
10551055
}
10561056

1057+
static int dirstat_compare(const void *_a, const void *_b)
1058+
{
1059+
const struct dirstat_file *a = _a;
1060+
const struct dirstat_file *b = _b;
1061+
return strcmp(a->name, b->name);
1062+
}
1063+
10571064
static void show_dirstat(struct diff_options *options)
10581065
{
10591066
int i;
@@ -1113,6 +1120,7 @@ static void show_dirstat(struct diff_options *options)
11131120
return;
11141121

11151122
/* Show all directories with more than x% of the changes */
1123+
qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
11161124
gather_dirstat(options->file, &dir, changed, "", 0);
11171125
}
11181126

0 commit comments

Comments
 (0)