Skip to content

Commit 266c1a0

Browse files
dschoGit for Windows Build Agent
authored andcommitted
Support loose 4GB+ objects (#6353)
When I merged the massive amount of work in #6289, I thought that that was the end of it. But simply staging and unpacking loose blobs that are 4GB or larger _still_ does not work. This PR addresses that. This fixes #6012
2 parents 6daf4de + 69f1bf3 commit 266c1a0

8 files changed

Lines changed: 56 additions & 19 deletions

File tree

‎object-file.c‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ int format_object_header(char *str, size_t size, enum object_type type,
111111
}
112112

113113
int check_object_signature(struct repository *r, const struct object_id *oid,
114-
void *buf, unsigned long size,
114+
void *buf, size_t size,
115115
enum object_type type)
116116
{
117117
const struct git_hash_algo *algo =
@@ -155,7 +155,7 @@ int stream_object_signature(struct repository *r,
155155
* Map and close the given loose object fd. The path argument is used for
156156
* error reporting.
157157
*/
158-
static void *map_fd(int fd, const char *path, unsigned long *size)
158+
static void *map_fd(int fd, const char *path, size_t *size)
159159
{
160160
void *map = NULL;
161161
struct stat st;
@@ -176,9 +176,9 @@ static void *map_fd(int fd, const char *path, unsigned long *size)
176176

177177
enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
178178
unsigned char *map,
179-
unsigned long mapsize,
179+
size_t mapsize,
180180
void *buffer,
181-
unsigned long bufsiz)
181+
size_t bufsiz)
182182
{
183183
int status;
184184

@@ -209,7 +209,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
209209
}
210210

211211
void *unpack_loose_rest(git_zstream *stream,
212-
void *buffer, unsigned long size,
212+
void *buffer, size_t size,
213213
const struct object_id *oid)
214214
{
215215
size_t bytes = strlen(buffer) + 1, n;
@@ -1199,7 +1199,7 @@ int read_loose_object(struct repository *repo,
11991199
int ret = -1;
12001200
int fd;
12011201
void *map = NULL;
1202-
unsigned long mapsize;
1202+
size_t mapsize;
12031203
git_zstream stream;
12041204
char hdr[MAX_HEADER_LEN];
12051205
size_t *size = oi->sizep;

‎object-file.h‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ int format_object_header(char *str, size_t size, enum object_type type,
9292
* what we expected, but it might also indicate another error.
9393
*/
9494
int check_object_signature(struct repository *r, const struct object_id *oid,
95-
void *map, unsigned long size,
95+
void *map, size_t size,
9696
enum object_type type);
9797

9898
/**
@@ -157,11 +157,11 @@ enum unpack_loose_header_result {
157157
*/
158158
enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
159159
unsigned char *map,
160-
unsigned long mapsize,
160+
size_t mapsize,
161161
void *buffer,
162-
unsigned long bufsiz);
162+
size_t bufsiz);
163163
void *unpack_loose_rest(git_zstream *stream,
164-
void *buffer, unsigned long size,
164+
void *buffer, size_t size,
165165
const struct object_id *oid);
166166

167167
int parse_loose_header(const char *hdr, struct object_info *oi);

‎odb.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ void odb_assert_oid_type(struct object_database *odb,
971971
}
972972

973973
int odb_write_object_ext(struct object_database *odb,
974-
const void *buf, unsigned long len,
974+
const void *buf, size_t len,
975975
enum object_type type,
976976
struct object_id *oid,
977977
const struct object_id *compat_oid_in,

‎odb.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,14 +676,14 @@ enum odb_write_object_flags {
676676
* Returns 0 on success, a negative error code otherwise.
677677
*/
678678
int odb_write_object_ext(struct object_database *odb,
679-
const void *buf, unsigned long len,
679+
const void *buf, size_t len,
680680
enum object_type type,
681681
struct object_id *oid,
682682
const struct object_id *compat_oid,
683683
enum odb_write_object_flags flags);
684684

685685
static inline int odb_write_object(struct object_database *odb,
686-
const void *buf, unsigned long len,
686+
const void *buf, size_t len,
687687
enum object_type type,
688688
struct object_id *oid)
689689
{

‎odb/source-loose.c‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static int read_object_info_from_path(struct odb_source_loose *loose,
7373
{
7474
int ret;
7575
int fd;
76-
unsigned long mapsize;
76+
size_t mapsize;
7777
void *map = NULL;
7878
git_zstream stream, *stream_to_end = NULL;
7979
char hdr[MAX_HEADER_LEN];
@@ -260,7 +260,7 @@ static int open_loose_object(struct odb_source_loose *loose,
260260

261261
static void *odb_source_loose_map_object(struct odb_source_loose *loose,
262262
const struct object_id *oid,
263-
unsigned long *size)
263+
size_t *size)
264264
{
265265
const char *p;
266266
int fd = open_loose_object(loose, oid, &p);
@@ -295,7 +295,7 @@ struct odb_loose_read_stream {
295295
ODB_LOOSE_READ_STREAM_ERROR,
296296
} z_state;
297297
void *mapped;
298-
unsigned long mapsize;
298+
size_t mapsize;
299299
char hdr[32];
300300
int hdr_avail;
301301
int hdr_used;
@@ -366,7 +366,7 @@ static int odb_source_loose_read_object_stream(struct odb_stream **out,
366366
struct odb_source_loose *loose = odb_source_loose_downcast(source);
367367
struct object_info oi = OBJECT_INFO_INIT;
368368
struct odb_loose_read_stream *st;
369-
unsigned long mapsize;
369+
size_t mapsize;
370370
void *mapped;
371371

372372
mapped = odb_source_loose_map_object(loose, oid, &mapsize);
@@ -770,7 +770,7 @@ static int end_loose_object_common(struct odb_source_loose *loose,
770770

771771
static int write_loose_object(struct odb_source_loose *loose,
772772
const struct object_id *oid, char *hdr,
773-
int hdrlen, const void *buf, unsigned long len,
773+
int hdrlen, const void *buf, size_t len,
774774
const time_t *mtime, unsigned flags)
775775
{
776776
int fd, ret;

‎odb/source.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ static inline int odb_source_freshen_object(struct odb_source *source,
504504
* object ID and the compatibility object ID, if non-NULL.
505505
*/
506506
static inline int odb_source_write_object(struct odb_source *source,
507-
const void *buf, unsigned long len,
507+
const void *buf, size_t len,
508508
enum object_type type,
509509
const struct object_id *oid,
510510
const struct object_id *compat_oid,

‎t/meson.build‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ integration_tests = [
441441
't3703-add-magic-pathspec.sh',
442442
't3704-add-pathspec-file.sh',
443443
't3705-add-sparse-checkout.sh',
444+
't3706-add-4gb-file.sh',
444445
't3800-mktag.sh',
445446
't3900-i18n-commit.sh',
446447
't3901-i18n-patch.sh',

‎t/t3706-add-4gb-file.sh‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2026 Johannes Schindelin
4+
#
5+
6+
test_description='add 4GB+ objects'
7+
8+
. ./test-lib.sh
9+
10+
if ! test_have_prereq EXPENSIVE,SIZE_T_IS_64BIT
11+
then
12+
skip_all='expensive 4GB blob test; enable on 64-bit with GIT_TEST_LONG=true'
13+
test_done
14+
fi
15+
16+
size_4gb=4294967296
17+
18+
test_expect_success 'set up a 4GB file' '
19+
test_atexit "rm -f large" &&
20+
# genrandom takes only an unsigned long...
21+
test-tool genrandom 123 $(($size_4gb-1)) >large &&
22+
printf 1 >>large
23+
'
24+
25+
test_expect_success 'add 4GB file' '
26+
git add large &&
27+
git cat-file -s :large >size-staged &&
28+
test $size_4gb = $(cat size-staged)
29+
'
30+
test_expect_success 'read 4GB loose object' '
31+
git -P show :large >read &&
32+
test_file_size read >size-read &&
33+
test $size_4gb = $(cat size-read)
34+
'
35+
36+
test_done

0 commit comments

Comments
 (0)