Skip to content

Commit 258188d

Browse files
authored
Merge pull request libgit2#5340 from pks-t/pks/pack-zstream
Refactor packfile code to use zstream abstraction
2 parents ba64f50 + 2dc7b5e commit 258188d

File tree

5 files changed

+69
-94
lines changed

5 files changed

+69
-94
lines changed

src/pack.c

Lines changed: 55 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77

88
#include "pack.h"
99

10-
#include "odb.h"
1110
#include "delta.h"
12-
#include "sha1_lookup.h"
13-
#include "mwindow.h"
1411
#include "futils.h"
12+
#include "mwindow.h"
13+
#include "odb.h"
1514
#include "oid.h"
16-
17-
#include <zlib.h>
15+
#include "sha1_lookup.h"
1816

1917
/* Option to bypass checking existence of '.keep' files */
2018
bool git_disable_pack_keep_file_checks = false;
@@ -765,31 +763,13 @@ int git_packfile_unpack(
765763
return error;
766764
}
767765

768-
static void *use_git_alloc(void *opaq, unsigned int count, unsigned int size)
769-
{
770-
GIT_UNUSED(opaq);
771-
return git__calloc(count, size);
772-
}
773-
774-
static void use_git_free(void *opaq, void *ptr)
775-
{
776-
GIT_UNUSED(opaq);
777-
git__free(ptr);
778-
}
779-
780766
int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, off64_t curpos)
781767
{
782-
int st;
783-
784768
memset(obj, 0, sizeof(git_packfile_stream));
785769
obj->curpos = curpos;
786770
obj->p = p;
787-
obj->zstream.zalloc = use_git_alloc;
788-
obj->zstream.zfree = use_git_free;
789-
obj->zstream.next_in = Z_NULL;
790-
obj->zstream.next_out = Z_NULL;
791-
st = inflateInit(&obj->zstream);
792-
if (st != Z_OK) {
771+
772+
if (git_zstream_init(&obj->zstream, GIT_ZSTREAM_INFLATE) < 0) {
793773
git_error_set(GIT_ERROR_ZLIB, "failed to init packfile stream");
794774
return -1;
795775
}
@@ -799,110 +779,100 @@ int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p,
799779

800780
ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len)
801781
{
782+
unsigned int window_len;
802783
unsigned char *in;
803-
size_t written;
804-
int st;
784+
int error;
805785

806786
if (obj->done)
807787
return 0;
808788

809-
in = pack_window_open(obj->p, &obj->mw, obj->curpos, &obj->zstream.avail_in);
810-
if (in == NULL)
789+
if ((in = pack_window_open(obj->p, &obj->mw, obj->curpos, &window_len)) == NULL)
811790
return GIT_EBUFS;
812791

813-
obj->zstream.next_out = buffer;
814-
obj->zstream.avail_out = (unsigned int)len;
815-
obj->zstream.next_in = in;
816-
817-
st = inflate(&obj->zstream, Z_SYNC_FLUSH);
818-
git_mwindow_close(&obj->mw);
819-
820-
obj->curpos += obj->zstream.next_in - in;
821-
written = len - obj->zstream.avail_out;
822-
823-
if (st != Z_OK && st != Z_STREAM_END) {
792+
if ((error = git_zstream_set_input(&obj->zstream, in, window_len)) < 0 ||
793+
(error = git_zstream_get_output_chunk(buffer, &len, &obj->zstream)) < 0) {
794+
git_mwindow_close(&obj->mw);
824795
git_error_set(GIT_ERROR_ZLIB, "error reading from the zlib stream");
825796
return -1;
826797
}
827798

828-
if (st == Z_STREAM_END)
829-
obj->done = 1;
799+
git_mwindow_close(&obj->mw);
830800

801+
obj->curpos += window_len - obj->zstream.in_len;
802+
803+
if (git_zstream_eos(&obj->zstream))
804+
obj->done = 1;
831805

832806
/* If we didn't write anything out but we're not done, we need more data */
833-
if (!written && st != Z_STREAM_END)
807+
if (!len && !git_zstream_eos(&obj->zstream))
834808
return GIT_EBUFS;
835809

836-
return written;
810+
return len;
837811

838812
}
839813

840814
void git_packfile_stream_dispose(git_packfile_stream *obj)
841815
{
842-
inflateEnd(&obj->zstream);
816+
git_zstream_free(&obj->zstream);
843817
}
844818

845819
static int packfile_unpack_compressed(
846820
git_rawobj *obj,
847821
struct git_pack_file *p,
848-
git_mwindow **w_curs,
849-
off64_t *curpos,
822+
git_mwindow **mwindow,
823+
off64_t *position,
850824
size_t size,
851825
git_object_t type)
852826
{
853-
size_t buf_size;
854-
int st;
855-
z_stream stream;
856-
unsigned char *buffer, *in;
857-
858-
GIT_ERROR_CHECK_ALLOC_ADD(&buf_size, size, 1);
859-
buffer = git__calloc(1, buf_size);
860-
GIT_ERROR_CHECK_ALLOC(buffer);
861-
862-
memset(&stream, 0, sizeof(stream));
863-
stream.next_out = buffer;
864-
stream.avail_out = (uInt)buf_size;
865-
stream.zalloc = use_git_alloc;
866-
stream.zfree = use_git_free;
867-
868-
st = inflateInit(&stream);
869-
if (st != Z_OK) {
870-
git__free(buffer);
871-
git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack");
827+
git_zstream zstream = GIT_ZSTREAM_INIT;
828+
size_t buffer_len, total = 0;
829+
char *data = NULL;
830+
int error;
872831

873-
return -1;
832+
GIT_ERROR_CHECK_ALLOC_ADD(&buffer_len, size, 1);
833+
data = git__calloc(1, buffer_len);
834+
GIT_ERROR_CHECK_ALLOC(data);
835+
836+
if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0) {
837+
git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack");
838+
goto out;
874839
}
875840

876841
do {
877-
in = pack_window_open(p, w_curs, *curpos, &stream.avail_in);
878-
stream.next_in = in;
879-
st = inflate(&stream, Z_FINISH);
880-
git_mwindow_close(w_curs);
842+
size_t bytes = buffer_len - total;
843+
unsigned int window_len;
844+
unsigned char *in;
881845

882-
if (!stream.avail_out)
883-
break; /* the payload is larger than it should be */
846+
in = pack_window_open(p, mwindow, *position, &window_len);
884847

885-
if (st == Z_BUF_ERROR && in == NULL) {
886-
inflateEnd(&stream);
887-
git__free(buffer);
888-
return GIT_EBUFS;
848+
if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
849+
(error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
850+
git_mwindow_close(mwindow);
851+
goto out;
889852
}
890853

891-
*curpos += stream.next_in - in;
892-
} while (st == Z_OK || st == Z_BUF_ERROR);
854+
git_mwindow_close(mwindow);
893855

894-
inflateEnd(&stream);
856+
*position += window_len - zstream.in_len;
857+
total += bytes;
858+
} while (total < size);
895859

896-
if ((st != Z_STREAM_END) || stream.total_out != size) {
897-
git__free(buffer);
860+
if (total != size || !git_zstream_eos(&zstream)) {
898861
git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
899-
return -1;
862+
error = -1;
863+
goto out;
900864
}
901865

902866
obj->type = type;
903867
obj->len = size;
904-
obj->data = buffer;
905-
return 0;
868+
obj->data = data;
869+
870+
out:
871+
git_zstream_free(&zstream);
872+
if (error)
873+
git__free(data);
874+
875+
return error;
906876
}
907877

908878
/*

src/pack.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@
1010

1111
#include "common.h"
1212

13-
#include <zlib.h>
14-
1513
#include "git2/oid.h"
1614

15+
#include "array.h"
1716
#include "map.h"
1817
#include "mwindow.h"
1918
#include "odb.h"
2019
#include "offmap.h"
2120
#include "oidmap.h"
22-
#include "array.h"
21+
#include "zstream.h"
2322

2423
#define GIT_PACK_FILE_MODE 0444
2524

@@ -116,7 +115,7 @@ struct git_pack_entry {
116115
typedef struct git_packfile_stream {
117116
off64_t curpos;
118117
int done;
119-
z_stream zstream;
118+
git_zstream zstream;
120119
struct git_pack_file *p;
121120
git_mwindow *mw;
122121
} git_packfile_stream;

src/zstream.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ bool git_zstream_done(git_zstream *zstream)
7777
return (!zstream->in_len && zstream->zerr == Z_STREAM_END);
7878
}
7979

80+
bool git_zstream_eos(git_zstream *zstream)
81+
{
82+
return zstream->zerr == Z_STREAM_END;
83+
}
84+
8085
size_t git_zstream_suggest_output_len(git_zstream *zstream)
8186
{
8287
if (zstream->in_len > ZSTREAM_BUFFER_SIZE)

src/zstream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ int git_zstream_get_output_chunk(
4444
int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream);
4545

4646
bool git_zstream_done(git_zstream *zstream);
47+
bool git_zstream_eos(git_zstream *zstream);
4748

4849
void git_zstream_reset(git_zstream *zstream);
4950

tests/pack/packbuilder.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ void test_pack_packbuilder__get_hash(void)
145145

146146
seed_packbuilder();
147147

148-
git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL);
148+
cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL));
149149
git_oid_fmt(hex, git_packbuilder_hash(_packbuilder));
150150

151151
cl_assert_equal_s(hex, "7f5fa362c664d68ba7221259be1cbd187434b2f0");
@@ -158,7 +158,7 @@ static void test_write_pack_permission(mode_t given, mode_t expected)
158158

159159
seed_packbuilder();
160160

161-
git_packbuilder_write(_packbuilder, ".", given, NULL, NULL);
161+
cl_git_pass(git_packbuilder_write(_packbuilder, ".", given, NULL, NULL));
162162

163163
/* Windows does not return group/user bits from stat,
164164
* files are never executable.
@@ -197,7 +197,7 @@ void test_pack_packbuilder__permissions_readwrite(void)
197197
void test_pack_packbuilder__does_not_fsync_by_default(void)
198198
{
199199
seed_packbuilder();
200-
git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
200+
cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL));
201201
cl_assert_equal_sz(0, p_fsync__cnt);
202202
}
203203

@@ -215,7 +215,7 @@ void test_pack_packbuilder__fsync_global_setting(void)
215215
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 1));
216216
p_fsync__cnt = 0;
217217
seed_packbuilder();
218-
git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
218+
cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL));
219219
cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
220220
}
221221

@@ -224,7 +224,7 @@ void test_pack_packbuilder__fsync_repo_setting(void)
224224
cl_repo_set_bool(_repo, "core.fsyncObjectFiles", true);
225225
p_fsync__cnt = 0;
226226
seed_packbuilder();
227-
git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
227+
cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL));
228228
cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
229229
}
230230

0 commit comments

Comments
 (0)