1
0
mirror of https://github.com/git/git synced 2024-07-05 00:58:49 +00:00

diff: make --dirstat binary-file safe

Instead of counting added and removed lines (and mixing the byte size
reported for binary files in the result), summarize the extent of damage
the same way as we count similarity for rename detection.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano 2008-02-12 17:06:58 -08:00
parent 2a5fe25458
commit c04a7155a0

83
diff.c
View File

@ -991,18 +991,23 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
} }
} }
struct diffstat_dir { struct dirstat_file {
struct diffstat_file **files; const char *name;
int nr, percent, cumulative; unsigned long changed;
}; };
static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen) struct dirstat_dir {
struct dirstat_file *files;
int alloc, nr, percent, cumulative;
};
static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long changed, const char *base, int baselen)
{ {
unsigned long this_dir = 0; unsigned long this_dir = 0;
unsigned int sources = 0; unsigned int sources = 0;
while (dir->nr) { while (dir->nr) {
struct diffstat_file *f = *dir->files; struct dirstat_file *f = dir->files;
int namelen = strlen(f->name); int namelen = strlen(f->name);
unsigned long this; unsigned long this;
char *slash; char *slash;
@ -1017,10 +1022,7 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c
this = gather_dirstat(file, dir, changed, f->name, newbaselen); this = gather_dirstat(file, dir, changed, f->name, newbaselen);
sources++; sources++;
} else { } else {
if (f->is_unmerged || f->is_binary) this = f->changed;
this = 0;
else
this = f->added + f->deleted;
dir->files++; dir->files++;
dir->nr--; dir->nr--;
sources += 2; sources += 2;
@ -1048,19 +1050,58 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c
return this_dir; return this_dir;
} }
static void show_dirstat(struct diffstat_t *data, struct diff_options *options) static void show_dirstat(struct diff_options *options)
{ {
int i; int i;
unsigned long changed; unsigned long changed;
struct diffstat_dir dir; struct dirstat_dir dir;
struct diff_queue_struct *q = &diff_queued_diff;
dir.files = NULL;
dir.alloc = 0;
dir.nr = 0;
dir.percent = options->dirstat_percent;
dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
/* Calculate total changes */
changed = 0; changed = 0;
for (i = 0; i < data->nr; i++) { for (i = 0; i < q->nr; i++) {
if (data->files[i]->is_binary || data->files[i]->is_unmerged) struct diff_filepair *p = q->queue[i];
const char *name;
unsigned long copied, added, damage;
name = p->one->path ? p->one->path : p->two->path;
if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
diff_populate_filespec(p->one, 0);
diff_populate_filespec(p->two, 0);
diffcore_count_changes(p->one, p->two, NULL, NULL, 0,
&copied, &added);
diff_free_filespec_data(p->one);
diff_free_filespec_data(p->two);
} else if (DIFF_FILE_VALID(p->one)) {
diff_populate_filespec(p->one, 1);
copied = added = 0;
diff_free_filespec_data(p->one);
} else if (DIFF_FILE_VALID(p->two)) {
diff_populate_filespec(p->two, 1);
copied = 0;
added = p->two->size;
diff_free_filespec_data(p->two);
} else
continue; continue;
changed += data->files[i]->added;
changed += data->files[i]->deleted; /*
* Original minus copied is the removed material,
* added is the new material. They are both damages
* made to the preimage.
*/
damage = (p->one->size - copied) + added;
ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc);
dir.files[dir.nr].name = name;
dir.files[dir.nr].changed = damage;
changed += damage;
dir.nr++;
} }
/* This can happen even with many files, if everything was renames */ /* This can happen even with many files, if everything was renames */
@ -1068,10 +1109,6 @@ static void show_dirstat(struct diffstat_t *data, struct diff_options *options)
return; return;
/* Show all directories with more than x% of the changes */ /* Show all directories with more than x% of the changes */
dir.files = data->files;
dir.nr = data->nr;
dir.percent = options->dirstat_percent;
dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
gather_dirstat(options->file, &dir, changed, "", 0); gather_dirstat(options->file, &dir, changed, "", 0);
} }
@ -3095,7 +3132,7 @@ void diff_flush(struct diff_options *options)
separator++; separator++;
} }
if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIRSTAT)) { if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) {
struct diffstat_t diffstat; struct diffstat_t diffstat;
memset(&diffstat, 0, sizeof(struct diffstat_t)); memset(&diffstat, 0, sizeof(struct diffstat_t));
@ -3105,8 +3142,6 @@ void diff_flush(struct diff_options *options)
if (check_pair_status(p)) if (check_pair_status(p))
diff_flush_stat(p, options, &diffstat); diff_flush_stat(p, options, &diffstat);
} }
if (output_format & DIFF_FORMAT_DIRSTAT)
show_dirstat(&diffstat, options);
if (output_format & DIFF_FORMAT_NUMSTAT) if (output_format & DIFF_FORMAT_NUMSTAT)
show_numstat(&diffstat, options); show_numstat(&diffstat, options);
if (output_format & DIFF_FORMAT_DIFFSTAT) if (output_format & DIFF_FORMAT_DIFFSTAT)
@ -3116,6 +3151,8 @@ void diff_flush(struct diff_options *options)
free_diffstat_info(&diffstat); free_diffstat_info(&diffstat);
separator++; separator++;
} }
if (output_format & DIFF_FORMAT_DIRSTAT)
show_dirstat(options);
if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) { if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
for (i = 0; i < q->nr; i++) for (i = 0; i < q->nr; i++)