Skip to content

Commit 6bf3b81

Browse files
pcloudsgitster
authored andcommitted
diff --stat: mark any file larger than core.bigfilethreshold binary
Too large files may lead to failure to allocate memory. If it happens here, it could impact quite a few commands that involve diff. Moreover, too large files are inefficient to compare anyway (and most likely non-text), so mark them binary and skip looking at their content. Noticed-by: Dale R. Worley <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8e5dd3d commit 6bf3b81

File tree

5 files changed

+27
-11
lines changed

5 files changed

+27
-11
lines changed

Documentation/config.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ core.bigFileThreshold::
499499
Files larger than this size are stored deflated, without
500500
attempting delta compression. Storing large files without
501501
delta compression avoids excessive memory usage, at the
502-
slight expense of increased disk usage.
502+
slight expense of increased disk usage. Additionally files
503+
larger than this size are always treated as binary.
503504
+
504505
Default is 512 MiB on all platforms. This should be reasonable
505506
for most projects as source code and other text files can still

Documentation/gitattributes.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,8 @@ Unspecified::
440440

441441
A path to which the `diff` attribute is unspecified
442442
first gets its contents inspected, and if it looks like
443-
text, it is treated as text. Otherwise it would
444-
generate `Binary files differ`.
443+
text and is smaller than core.bigFileThreshold, it is treated
444+
as text. Otherwise it would generate `Binary files differ`.
445445

446446
String::
447447

diff.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,8 +2188,8 @@ int diff_filespec_is_binary(struct diff_filespec *one)
21882188
one->is_binary = one->driver->binary;
21892189
else {
21902190
if (!one->data && DIFF_FILE_VALID(one))
2191-
diff_populate_filespec(one, 0);
2192-
if (one->data)
2191+
diff_populate_filespec(one, CHECK_BINARY);
2192+
if (one->is_binary == -1 && one->data)
21932193
one->is_binary = buffer_is_binary(one->data,
21942194
one->size);
21952195
if (one->is_binary == -1)
@@ -2725,6 +2725,11 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
27252725
}
27262726
if (size_only)
27272727
return 0;
2728+
if ((flags & CHECK_BINARY) &&
2729+
s->size > big_file_threshold && s->is_binary == -1) {
2730+
s->is_binary = 1;
2731+
return 0;
2732+
}
27282733
fd = open(s->path, O_RDONLY);
27292734
if (fd < 0)
27302735
goto err_empty;
@@ -2746,16 +2751,21 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
27462751
}
27472752
else {
27482753
enum object_type type;
2749-
if (size_only) {
2754+
if (size_only || (flags & CHECK_BINARY)) {
27502755
type = sha1_object_info(s->sha1, &s->size);
27512756
if (type < 0)
27522757
die("unable to read %s", sha1_to_hex(s->sha1));
2753-
} else {
2754-
s->data = read_sha1_file(s->sha1, &type, &s->size);
2755-
if (!s->data)
2756-
die("unable to read %s", sha1_to_hex(s->sha1));
2757-
s->should_free = 1;
2758+
if (size_only)
2759+
return 0;
2760+
if (s->size > big_file_threshold && s->is_binary == -1) {
2761+
s->is_binary = 1;
2762+
return 0;
2763+
}
27582764
}
2765+
s->data = read_sha1_file(s->sha1, &type, &s->size);
2766+
if (!s->data)
2767+
die("unable to read %s", sha1_to_hex(s->sha1));
2768+
s->should_free = 1;
27592769
}
27602770
return 0;
27612771
}

diffcore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extern void fill_filespec(struct diff_filespec *, const unsigned char *,
5656
int, unsigned short);
5757

5858
#define CHECK_SIZE_ONLY 1
59+
#define CHECK_BINARY 2
5960
extern int diff_populate_filespec(struct diff_filespec *, unsigned int);
6061
extern void diff_free_filespec_data(struct diff_filespec *);
6162
extern void diff_free_filespec_blob(struct diff_filespec *);

t/t1050-large.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ test_expect_success 'diff --raw' '
112112
git diff --raw HEAD^
113113
'
114114

115+
test_expect_success 'diff --stat' '
116+
git diff --stat HEAD^ HEAD
117+
'
118+
115119
test_expect_success 'hash-object' '
116120
git hash-object large1
117121
'

0 commit comments

Comments
 (0)