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 | 1 + 4 files changed, 47 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 3e0e6d0165..247b131fd5 100644 --- a/external-odb.h +++ b/external-odb.h @@ -4,6 +4,7 @@ const char *external_odb_root(void); int external_odb_has_object(const unsigned char *sha1); int external_odb_get_object(const unsigned char *sha1); +int external_odb_get_direct(const unsigned char *sha1); 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 0603993057..b1f5464214 100644 --- a/odb-helper.c +++ b/odb-helper.c @@ -405,14 +405,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 318e0d48dc..f2fd2b7c9c 100644 --- a/odb-helper.h +++ b/odb-helper.h @@ -33,6 +33,7 @@ int odb_helper_init(struct odb_helper *o); int odb_helper_has_object(struct odb_helper *o, const unsigned char *sha1); int odb_helper_get_object(struct odb_helper *o, const unsigned char *sha1, int fd); +int odb_helper_get_direct(struct odb_helper *o, const unsigned char *sha1); int odb_helper_put_object(struct odb_helper *o, const void *buf, size_t len, const char *type, unsigned char *sha1); -- 2.14.0.rc1.52.gf02fb0ddac.dirty