Skip to content

Commit

Permalink
Fix '--dirstat' with cross-directory renaming
Browse files Browse the repository at this point in the history
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 <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Linus Torvalds authored and Junio C Hamano committed Aug 29, 2008
1 parent 114ef90 commit 441bca0
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,13 @@ static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long ch
return this_dir;
}

static int dirstat_compare(const void *_a, const void *_b)
{
const struct dirstat_file *a = _a;
const struct dirstat_file *b = _b;
return strcmp(a->name, b->name);
}

static void show_dirstat(struct diff_options *options)
{
int i;
Expand Down Expand Up @@ -1113,6 +1120,7 @@ static void show_dirstat(struct diff_options *options)
return;

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

Expand Down

0 comments on commit 441bca0

Please sign in to comment.