Skip to content

Commit 59ce984

Browse files
jltoblergitster
authored andcommitted
object-file: generalize packfile writes to use odb_write_stream
The `index_blob_packfile_transaction()` function streams blob data directly from an fd. This makes it difficult to reuse as part of a generic transactional object writing interface. Refactor the packfile write path to operate on a `struct odb_write_stream`, allowing callers to supply data from arbitrary sources. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent efb5dba commit 59ce984

1 file changed

Lines changed: 29 additions & 26 deletions

File tree

object-file.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,18 +1444,19 @@ static int hash_blob_stream(struct odb_write_stream *stream,
14441444
}
14451445

14461446
/*
1447-
* Read the contents from fd for size bytes, streaming it to the
1447+
* Read the contents from the stream provided, streaming it to the
14481448
* packfile in state while updating the hash in ctx.
14491449
*/
14501450
static void stream_blob_to_pack(struct transaction_packfile *state,
1451-
struct git_hash_ctx *ctx, int fd, size_t size,
1452-
const char *path)
1451+
struct git_hash_ctx *ctx, size_t size,
1452+
struct odb_write_stream *stream)
14531453
{
14541454
git_zstream s;
14551455
unsigned char ibuf[16384];
14561456
unsigned char obuf[16384];
14571457
unsigned hdrlen;
14581458
int status = Z_OK;
1459+
size_t total = 0;
14591460

14601461
git_deflate_init(&s, pack_compression_level);
14611462

@@ -1464,23 +1465,20 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
14641465
s.avail_out = sizeof(obuf) - hdrlen;
14651466

14661467
while (status != Z_STREAM_END) {
1467-
if (size && !s.avail_in) {
1468-
size_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
1469-
ssize_t read_result = read_in_full(fd, ibuf, rsize);
1470-
if (read_result < 0)
1471-
die_errno("failed to read from '%s'", path);
1472-
if ((size_t)read_result != rsize)
1473-
die("failed to read %u bytes from '%s'",
1474-
(unsigned)rsize, path);
1468+
if (!stream->is_finished && !s.avail_in) {
1469+
ssize_t rsize = stream->read(stream, ibuf, sizeof(ibuf));
1470+
1471+
if (rsize < 0)
1472+
die("failed to read blob data");
14751473

14761474
git_hash_update(ctx, ibuf, rsize);
14771475

14781476
s.next_in = ibuf;
14791477
s.avail_in = rsize;
1480-
size -= rsize;
1478+
total += rsize;
14811479
}
14821480

1483-
status = git_deflate(&s, size ? 0 : Z_FINISH);
1481+
status = git_deflate(&s, stream->is_finished ? Z_FINISH : 0);
14841482

14851483
if (!s.avail_out || status == Z_STREAM_END) {
14861484
size_t written = s.next_out - obuf;
@@ -1500,6 +1498,11 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
15001498
die("unexpected deflate failure: %d", status);
15011499
}
15021500
}
1501+
1502+
if (total != size)
1503+
die("read %" PRIuMAX " bytes of blob data, but expected %" PRIuMAX " bytes",
1504+
(uintmax_t)total, (uintmax_t)size);
1505+
15031506
git_deflate_end(&s);
15041507
}
15051508

@@ -1571,10 +1574,13 @@ static void flush_packfile_transaction(struct odb_transaction_files *transaction
15711574
* binary blobs, they generally do not want to get any conversion, and
15721575
* callers should avoid this code path when filters are requested.
15731576
*/
1574-
static int index_blob_packfile_transaction(struct odb_transaction_files *transaction,
1575-
struct object_id *result_oid, int fd,
1576-
size_t size, const char *path)
1577+
static int index_blob_packfile_transaction(struct odb_transaction *base,
1578+
struct odb_write_stream *stream,
1579+
size_t size, struct object_id *result_oid)
15771580
{
1581+
struct odb_transaction_files *transaction = container_of(base,
1582+
struct odb_transaction_files,
1583+
base);
15781584
struct transaction_packfile *state = &transaction->packfile;
15791585
struct git_hash_ctx ctx;
15801586
unsigned char obuf[16384];
@@ -1608,7 +1614,7 @@ static int index_blob_packfile_transaction(struct odb_transaction_files *transac
16081614
hashfile_checkpoint(state->f, &checkpoint);
16091615
idx->offset = state->offset;
16101616
crc32_begin(state->f);
1611-
stream_blob_to_pack(state, &ctx, fd, size, path);
1617+
stream_blob_to_pack(state, &ctx, size, stream);
16121618
git_hash_final_oid(result_oid, &ctx);
16131619

16141620
idx->crc32 = crc32_end(state->f);
@@ -1652,15 +1658,12 @@ int index_fd(struct index_state *istate, struct object_id *oid,
16521658

16531659
if (flags & INDEX_WRITE_OBJECT) {
16541660
struct object_database *odb = the_repository->objects;
1655-
struct odb_transaction_files *files_transaction;
1656-
struct odb_transaction *transaction;
1657-
1658-
transaction = odb_transaction_begin(odb);
1659-
files_transaction = container_of(odb->transaction,
1660-
struct odb_transaction_files,
1661-
base);
1662-
ret = index_blob_packfile_transaction(files_transaction, oid, fd,
1663-
xsize_t(st->st_size), path);
1661+
struct odb_transaction *transaction = odb_transaction_begin(odb);
1662+
1663+
ret = index_blob_packfile_transaction(odb->transaction,
1664+
&stream,
1665+
xsize_t(st->st_size),
1666+
oid);
16641667
odb_transaction_commit(transaction);
16651668
} else {
16661669
ret = hash_blob_stream(&stream,

0 commit comments

Comments
 (0)