@@ -1433,18 +1433,18 @@ static int hash_blob_stream(const struct git_hash_algo *hash_algo,
14331433}
14341434
14351435/*
1436- * Read the contents from fd for size bytes , streaming it to the
1436+ * Read the contents from the stream provided , streaming it to the
14371437 * packfile in state while updating the hash in ctx.
14381438 */
14391439static void stream_blob_to_pack (struct transaction_packfile * state ,
1440- struct git_hash_ctx * ctx , int fd , size_t size ,
1441- const char * path )
1440+ struct git_hash_ctx * ctx , size_t size ,
1441+ struct odb_write_stream * stream )
14421442{
14431443 git_zstream s ;
1444- unsigned char ibuf [16384 ];
14451444 unsigned char obuf [16384 ];
14461445 unsigned hdrlen ;
14471446 int status = Z_OK ;
1447+ size_t total = 0 ;
14481448
14491449 git_deflate_init (& s , pack_compression_level );
14501450
@@ -1453,24 +1453,19 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
14531453 s .avail_out = sizeof (obuf ) - hdrlen ;
14541454
14551455 while (status != Z_STREAM_END ) {
1456- if (size && !s .avail_in ) {
1457- size_t rsize = size < sizeof (ibuf ) ? size : sizeof (ibuf );
1458- ssize_t read_result = read_in_full (fd , ibuf , rsize );
1459- if (read_result < 0 )
1460- die_errno ("failed to read from '%s'" , path );
1461- if ((size_t )read_result != rsize )
1462- die ("failed to read %u bytes from '%s'" ,
1463- (unsigned )rsize , path );
1456+ if (!stream -> is_finished && !s .avail_in ) {
1457+ unsigned long rsize ;
1458+ unsigned const char * buf = stream -> read (stream , & rsize );
14641459
14651460 if (rsize )
1466- git_hash_update (ctx , ibuf , rsize );
1461+ git_hash_update (ctx , buf , rsize );
14671462
1468- s .next_in = ibuf ;
1463+ s .next_in = ( unsigned char * ) buf ;
14691464 s .avail_in = rsize ;
1470- size - = rsize ;
1465+ total + = rsize ;
14711466 }
14721467
1473- status = git_deflate (& s , size ? 0 : Z_FINISH );
1468+ status = git_deflate (& s , stream -> is_finished ? Z_FINISH : 0 );
14741469
14751470 if (!s .avail_out || status == Z_STREAM_END ) {
14761471 size_t written = s .next_out - obuf ;
@@ -1490,6 +1485,10 @@ static void stream_blob_to_pack(struct transaction_packfile *state,
14901485 die ("unexpected deflate failure: %d" , status );
14911486 }
14921487 }
1488+
1489+ if (total != size )
1490+ die ("unexpected number of bytes read" );
1491+
14931492 git_deflate_end (& s );
14941493}
14951494
@@ -1543,6 +1542,40 @@ static void flush_packfile_transaction(struct odb_transaction_files *transaction
15431542 odb_reprepare (repo -> objects );
15441543}
15451544
1545+ struct read_object_fd_data {
1546+ int fd ;
1547+ size_t size ;
1548+ unsigned char buf [16384 ];
1549+ };
1550+
1551+ static const void * read_object_fd (struct odb_write_stream * stream ,
1552+ unsigned long * len )
1553+ {
1554+ struct read_object_fd_data * data = stream -> data ;
1555+ ssize_t read_result ;
1556+ size_t rsize ;
1557+
1558+ if (stream -> is_finished ) {
1559+ * len = 0 ;
1560+ return NULL ;
1561+ }
1562+
1563+ rsize = data -> size < sizeof (data -> buf ) ? data -> size : sizeof (data -> buf );
1564+ read_result = read_in_full (data -> fd , data -> buf , rsize );
1565+ if (read_result < 0 )
1566+ die_errno ("failed to read blob data" );
1567+ if ((size_t )read_result != rsize )
1568+ die ("failed to read %u bytes of blob data" , (unsigned )rsize );
1569+
1570+ data -> size -= rsize ;
1571+ if (!data -> size )
1572+ stream -> is_finished = 1 ;
1573+
1574+ * len = rsize ;
1575+
1576+ return data -> buf ;
1577+ }
1578+
15461579/*
15471580 * This writes the specified object to a packfile. Objects written here
15481581 * during the same transaction are written to the same packfile. The
@@ -1561,10 +1594,13 @@ static void flush_packfile_transaction(struct odb_transaction_files *transaction
15611594 * binary blobs, they generally do not want to get any conversion, and
15621595 * callers should avoid this code path when filters are requested.
15631596 */
1564- static int index_blob_packfile_transaction (struct odb_transaction_files * transaction ,
1565- struct object_id * result_oid , int fd ,
1566- size_t size , const char * path )
1597+ static int index_blob_packfile_transaction (struct odb_transaction * base ,
1598+ struct odb_write_stream * stream ,
1599+ size_t size , struct object_id * result_oid )
15671600{
1601+ struct odb_transaction_files * transaction = container_of (base ,
1602+ struct odb_transaction_files ,
1603+ base );
15681604 struct transaction_packfile * state = & transaction -> packfile ;
15691605 struct git_hash_ctx ctx ;
15701606 unsigned char obuf [16384 ];
@@ -1593,7 +1629,7 @@ static int index_blob_packfile_transaction(struct odb_transaction_files *transac
15931629 hashfile_checkpoint (state -> f , & checkpoint );
15941630 idx -> offset = state -> offset ;
15951631 crc32_begin (state -> f );
1596- stream_blob_to_pack (state , & ctx , fd , size , path );
1632+ stream_blob_to_pack (state , & ctx , size , stream );
15971633 git_hash_final_oid (result_oid , & ctx );
15981634
15991635 idx -> crc32 = crc32_end (state -> f );
@@ -1634,15 +1670,20 @@ int index_fd(struct index_state *istate, struct object_id *oid,
16341670 } else {
16351671 if (flags & INDEX_WRITE_OBJECT ) {
16361672 struct object_database * odb = the_repository -> objects ;
1637- struct odb_transaction_files * files_transaction ;
1638- struct odb_transaction * transaction ;
1639-
1640- transaction = odb_transaction_begin (odb );
1641- files_transaction = container_of (odb -> transaction ,
1642- struct odb_transaction_files ,
1643- base );
1644- ret = index_blob_packfile_transaction (files_transaction , oid , fd ,
1645- xsize_t (st -> st_size ), path );
1673+ struct odb_transaction * transaction = odb_transaction_begin (odb );
1674+ struct read_object_fd_data data = {
1675+ .fd = fd ,
1676+ .size = xsize_t (st -> st_size ),
1677+ };
1678+ struct odb_write_stream in_stream = {
1679+ .read = read_object_fd ,
1680+ .data = & data ,
1681+ };
1682+
1683+ ret = index_blob_packfile_transaction (odb -> transaction ,
1684+ & in_stream ,
1685+ xsize_t (st -> st_size ),
1686+ oid );
16461687 odb_transaction_commit (transaction );
16471688 } else {
16481689 if (hash_blob_stream (the_repository -> hash_algo , oid , fd ,
0 commit comments