This implements the 'get_direct' capability/instruction that makes it possible for external odb helper scripts to pass blobs to Git by directly writing them as loose objects files. It is better to call this a "direct" mode rather than a "fault-in" mode as we could have the same kind of mechanism to "put" objects into an external odb, where the odb helper would access blobs it wants to send to an external odb directly from files, but it would be strange to call that a fault-in mode too. Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx> --- external-odb.c | 21 ++++++++++++++++++++- external-odb.h | 1 + odb-helper.c | 27 +++++++++++++++++++++++++-- odb-helper.h | 2 ++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/external-odb.c b/external-odb.c index 52cb448d01..31d21bfe04 100644 --- a/external-odb.c +++ b/external-odb.c @@ -96,7 +96,8 @@ int external_odb_get_object(const unsigned char *sha1) int ret; int fd; - if (!odb_helper_has_object(o, sha1)) + if (!(o->supported_capabilities & ODB_HELPER_CAP_GET_RAW_OBJ) && + !(o->supported_capabilities & ODB_HELPER_CAP_GET_GIT_OBJ)) continue; fd = create_object_tmpfile(&tmpfile, path); @@ -122,6 +123,24 @@ int external_odb_get_object(const unsigned char *sha1) return -1; } +int external_odb_get_direct(const unsigned char *sha1) +{ + struct odb_helper *o; + + if (!external_odb_has_object(sha1)) + return -1; + + for (o = helpers; o; o = o->next) { + if (!(o->supported_capabilities & ODB_HELPER_CAP_GET_DIRECT)) + continue; + if (odb_helper_get_direct(o, sha1) < 0) + continue; + return 0; + } + + return -1; +} + int external_odb_put_object(const void *buf, size_t len, const char *type, unsigned char *sha1) { diff --git a/external-odb.h b/external-odb.h index d369dfdf6f..1fda08c0fb 100644 --- a/external-odb.h +++ b/external-odb.h @@ -4,6 +4,7 @@ extern const char *external_odb_root(void); extern int external_odb_has_object(const unsigned char *sha1); extern int external_odb_get_object(const unsigned char *sha1); +extern int external_odb_get_direct(const unsigned char *sha1); extern int external_odb_put_object(const void *buf, size_t len, const char *type, unsigned char *sha1); diff --git a/odb-helper.c b/odb-helper.c index 1f4666b349..3d940a3171 100644 --- a/odb-helper.c +++ b/odb-helper.c @@ -425,14 +425,37 @@ static int odb_helper_get_git_object(struct odb_helper *o, return 0; } +int odb_helper_get_direct(struct odb_helper *o, + const unsigned char *sha1) +{ + struct odb_helper_object *obj; + struct odb_helper_cmd cmd; + + obj = odb_helper_lookup(o, sha1); + if (!obj) + return -1; + + if (odb_helper_start(o, &cmd, 0, "get_direct %s", sha1_to_hex(sha1)) < 0) + return -1; + + if (odb_helper_finish(o, &cmd)) + return -1; + + return 0; +} + int odb_helper_get_object(struct odb_helper *o, const unsigned char *sha1, int fd) { + if (o->supported_capabilities & ODB_HELPER_CAP_GET_GIT_OBJ) + return odb_helper_get_git_object(o, sha1, fd); if (o->supported_capabilities & ODB_HELPER_CAP_GET_RAW_OBJ) return odb_helper_get_raw_object(o, sha1, fd); - else - return odb_helper_get_git_object(o, sha1, fd); + if (o->supported_capabilities & ODB_HELPER_CAP_GET_DIRECT) + return 0; + + BUG("invalid get capability (capabilities: '%d')", o->supported_capabilities); } int odb_helper_put_object(struct odb_helper *o, diff --git a/odb-helper.h b/odb-helper.h index 0571ba09cb..fbb6d333ee 100644 --- a/odb-helper.h +++ b/odb-helper.h @@ -35,6 +35,8 @@ extern int odb_helper_has_object(struct odb_helper *o, extern int odb_helper_get_object(struct odb_helper *o, const unsigned char *sha1, int fd); +extern int odb_helper_get_direct(struct odb_helper *o, + const unsigned char *sha1); extern int odb_helper_put_object(struct odb_helper *o, const void *buf, size_t len, const char *type, unsigned char *sha1); -- 2.14.1.576.g3f707d88cd