Skip to content

Commit 4d384d6

Browse files
author
Edward Thomson
committed
Merge pull request libgit2#3759 from libgit2/cmn/faster-header
odb: avoid inflating the full delta to read the header
2 parents d24425f + a97b769 commit 4d384d6

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

src/delta-apply.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,37 @@ int git__delta_read_header(
4949
return 0;
5050
}
5151

52+
#define DELTA_HEADER_BUFFER_LEN 16
53+
int git__delta_read_header_fromstream(size_t *base_sz, size_t *res_sz, git_packfile_stream *stream)
54+
{
55+
static const size_t buffer_len = DELTA_HEADER_BUFFER_LEN;
56+
unsigned char buffer[DELTA_HEADER_BUFFER_LEN];
57+
const unsigned char *delta, *delta_end;
58+
size_t len;
59+
ssize_t read;
60+
61+
len = read = 0;
62+
while (len < buffer_len) {
63+
read = git_packfile_stream_read(stream, &buffer[len], buffer_len - len);
64+
65+
if (read == 0)
66+
break;
67+
68+
if (read == GIT_EBUFS)
69+
continue;
70+
71+
len += read;
72+
}
73+
74+
delta = buffer;
75+
delta_end = delta + len;
76+
if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
77+
(hdr_sz(res_sz, &delta, delta_end) < 0))
78+
return -1;
79+
80+
return 0;
81+
}
82+
5283
int git__delta_apply(
5384
git_rawobj *out,
5485
const unsigned char *base,

src/delta-apply.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define INCLUDE_delta_apply_h__
99

1010
#include "odb.h"
11+
#include "pack.h"
1112

1213
/**
1314
* Apply a git binary delta to recover the original content.
@@ -47,4 +48,15 @@ extern int git__delta_read_header(
4748
size_t *base_sz,
4849
size_t *res_sz);
4950

51+
/**
52+
* Read the header of a git binary delta
53+
*
54+
* This variant reads just enough from the packfile stream to read the
55+
* delta header.
56+
*/
57+
extern int git__delta_read_header_fromstream(
58+
size_t *base_sz,
59+
size_t *res_sz,
60+
git_packfile_stream *stream);
61+
5062
#endif

src/pack.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -499,15 +499,14 @@ int git_packfile_resolve_header(
499499

500500
if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
501501
size_t base_size;
502-
git_rawobj delta;
502+
git_packfile_stream stream;
503+
503504
base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
504505
git_mwindow_close(&w_curs);
505-
error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
506-
git_mwindow_close(&w_curs);
507-
if (error < 0)
506+
if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
508507
return error;
509-
error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
510-
git__free(delta.data);
508+
error = git__delta_read_header_fromstream(&base_size, size_p, &stream);
509+
git_packfile_stream_free(&stream);
511510
if (error < 0)
512511
return error;
513512
} else

0 commit comments

Comments
 (0)