Skip to content

Commit fe4ab2e

Browse files
committed
Merge branch 'jt/index-fd-wo-repo-regression-fix-maint'
During Git 2.52 timeframe, we broke streaming computation of object hash outside a repository, which has been corrected. * jt/index-fd-wo-repo-regression-fix-maint: object-file: avoid ODB transaction when not writing objects
2 parents 37a4780 + 7d8727f commit fe4ab2e

2 files changed

Lines changed: 53 additions & 12 deletions

File tree

object-file.c

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,34 @@ static int index_blob_packfile_transaction(struct odb_transaction_files *transac
16421642
return 0;
16431643
}
16441644

1645+
static int hash_blob_stream(const struct git_hash_algo *hash_algo,
1646+
struct object_id *result_oid, int fd, size_t size)
1647+
{
1648+
unsigned char buf[16384];
1649+
struct git_hash_ctx ctx;
1650+
unsigned header_len;
1651+
1652+
header_len = format_object_header((char *)buf, sizeof(buf),
1653+
OBJ_BLOB, size);
1654+
hash_algo->init_fn(&ctx);
1655+
git_hash_update(&ctx, buf, header_len);
1656+
1657+
while (size) {
1658+
size_t rsize = size < sizeof(buf) ? size : sizeof(buf);
1659+
ssize_t read_result = read_in_full(fd, buf, rsize);
1660+
1661+
if ((read_result < 0) || ((size_t)read_result != rsize))
1662+
return -1;
1663+
1664+
git_hash_update(&ctx, buf, rsize);
1665+
size -= read_result;
1666+
}
1667+
1668+
git_hash_final_oid(result_oid, &ctx);
1669+
1670+
return 0;
1671+
}
1672+
16451673
int index_fd(struct index_state *istate, struct object_id *oid,
16461674
int fd, struct stat *st,
16471675
enum object_type type, const char *path, unsigned flags)
@@ -1663,18 +1691,23 @@ int index_fd(struct index_state *istate, struct object_id *oid,
16631691
ret = index_core(istate, oid, fd, xsize_t(st->st_size),
16641692
type, path, flags);
16651693
} else {
1666-
struct object_database *odb = the_repository->objects;
1667-
struct odb_transaction_files *files_transaction;
1668-
struct odb_transaction *transaction;
1669-
1670-
transaction = odb_transaction_begin(odb);
1671-
files_transaction = container_of(odb->transaction,
1672-
struct odb_transaction_files,
1673-
base);
1674-
ret = index_blob_packfile_transaction(files_transaction, oid, fd,
1675-
xsize_t(st->st_size),
1676-
path, flags);
1677-
odb_transaction_commit(transaction);
1694+
if (flags & INDEX_WRITE_OBJECT) {
1695+
struct object_database *odb = the_repository->objects;
1696+
struct odb_transaction_files *files_transaction;
1697+
struct odb_transaction *transaction;
1698+
1699+
transaction = odb_transaction_begin(odb);
1700+
files_transaction = container_of(odb->transaction,
1701+
struct odb_transaction_files,
1702+
base);
1703+
ret = index_blob_packfile_transaction(files_transaction, oid, fd,
1704+
xsize_t(st->st_size),
1705+
path, flags);
1706+
odb_transaction_commit(transaction);
1707+
} else {
1708+
ret = hash_blob_stream(the_repository->hash_algo, oid,
1709+
fd, xsize_t(st->st_size));
1710+
}
16781711
}
16791712

16801713
close(fd);

t/t1517-outside-repo.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ test_expect_success 'diff outside repository' '
9393
test_cmp expect actual
9494
'
9595

96+
test_expect_success 'hash object exceeding bigFileThreshold outside repository' '
97+
(
98+
cd non-repo &&
99+
echo foo >foo &&
100+
git -c core.bigFileThreshold=1 hash-object --stdin <foo
101+
)
102+
'
103+
96104
test_expect_success 'stripspace outside repository' '
97105
nongit git stripspace -s </dev/null
98106
'

0 commit comments

Comments
 (0)