Skip to content

Commit 45a75d6

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 d4c92e2 commit 45a75d6

1 file changed

Lines changed: 30 additions & 26 deletions

File tree

object-file.c

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,18 +1447,19 @@ static int hash_blob_stream(struct odb_write_stream *stream,
14471447
}
14481448

14491449
/*
1450-
* Read the contents from fd for size bytes, streaming it to the
1450+
* Read the contents from the stream provided, streaming it to the
14511451
* packfile in state while updating the hash in ctx.
14521452
*/
14531453
static void stream_blob_to_pack(struct transaction_packfile *state,
1454-
struct git_hash_ctx *ctx, int fd, size_t size,
1455-
const char *path)
1454+
struct git_hash_ctx *ctx, size_t size,
1455+
struct odb_write_stream *stream)
14561456
{
14571457
git_zstream s;
14581458
unsigned char ibuf[16384];
14591459
unsigned char obuf[16384];
14601460
unsigned hdrlen;
14611461
int status = Z_OK;
1462+
size_t bytes_read = 0;
14621463

14631464
git_deflate_init(&s, pack_compression_level);
14641465

@@ -1467,23 +1468,21 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
14671468
s.avail_out = sizeof(obuf) - hdrlen;
14681469

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

14791478
git_hash_update(ctx, ibuf, rsize);
14801479

14811480
s.next_in = ibuf;
14821481
s.avail_in = rsize;
1483-
size -= rsize;
1482+
bytes_read += rsize;
14841483
}
14851484

1486-
status = git_deflate(&s, size ? 0 : Z_FINISH);
1485+
status = git_deflate(&s, stream->is_finished ? Z_FINISH : 0);
14871486

14881487
if (!s.avail_out || status == Z_STREAM_END) {
14891488
size_t written = s.next_out - obuf;
@@ -1503,6 +1502,11 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
15031502
die("unexpected deflate failure: %d", status);
15041503
}
15051504
}
1505+
1506+
if (bytes_read != size)
1507+
die("read %" PRIuMAX " bytes of blob data, but expected %" PRIuMAX " bytes",
1508+
(uintmax_t)bytes_read, (uintmax_t)size);
1509+
15061510
git_deflate_end(&s);
15071511
}
15081512

@@ -1574,10 +1578,13 @@ static void flush_packfile_transaction(struct odb_transaction_files *transaction
15741578
* binary blobs, they generally do not want to get any conversion, and
15751579
* callers should avoid this code path when filters are requested.
15761580
*/
1577-
static int index_blob_packfile_transaction(struct odb_transaction_files *transaction,
1578-
struct object_id *result_oid, int fd,
1579-
size_t size, const char *path)
1581+
static int index_blob_packfile_transaction(struct odb_transaction *base,
1582+
struct odb_write_stream *stream,
1583+
size_t size, struct object_id *result_oid)
15801584
{
1585+
struct odb_transaction_files *transaction = container_of(base,
1586+
struct odb_transaction_files,
1587+
base);
15811588
struct transaction_packfile *state = &transaction->packfile;
15821589
struct git_hash_ctx ctx;
15831590
unsigned char obuf[16384];
@@ -1611,7 +1618,7 @@ static int index_blob_packfile_transaction(struct odb_transaction_files *transac
16111618
hashfile_checkpoint(state->f, &checkpoint);
16121619
idx->offset = state->offset;
16131620
crc32_begin(state->f);
1614-
stream_blob_to_pack(state, &ctx, fd, size, path);
1621+
stream_blob_to_pack(state, &ctx, size, stream);
16151622
git_hash_final_oid(result_oid, &ctx);
16161623

16171624
idx->crc32 = crc32_end(state->f);
@@ -1655,15 +1662,12 @@ int index_fd(struct index_state *istate, struct object_id *oid,
16551662

16561663
if (flags & INDEX_WRITE_OBJECT) {
16571664
struct object_database *odb = the_repository->objects;
1658-
struct odb_transaction_files *files_transaction;
1659-
struct odb_transaction *transaction;
1660-
1661-
transaction = odb_transaction_begin(odb);
1662-
files_transaction = container_of(odb->transaction,
1663-
struct odb_transaction_files,
1664-
base);
1665-
ret = index_blob_packfile_transaction(files_transaction, oid, fd,
1666-
xsize_t(st->st_size), path);
1665+
struct odb_transaction *transaction = odb_transaction_begin(odb);
1666+
1667+
ret = index_blob_packfile_transaction(odb->transaction,
1668+
&stream,
1669+
xsize_t(st->st_size),
1670+
oid);
16671671
odb_transaction_commit(transaction);
16681672
} else {
16691673
ret = hash_blob_stream(&stream,

0 commit comments

Comments
 (0)