Add support for a 'put_raw_obj' capability/instruction to send new objects to an external odb. Objects will be sent as they are (in their 'raw' format). They will not be converted to Git objects. For now any new Git object (blob, tree, commit, ...) would be sent if 'put_raw_obj' is supported by an odb helper. This is not a great default, but let's leave it to following commits to tweak that. Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx> --- external-odb.c | 15 +++++++++++++++ external-odb.h | 2 ++ odb-helper.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------ odb-helper.h | 3 +++ sha1_file.c | 2 ++ 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/external-odb.c b/external-odb.c index 192b09e843..806dc8e699 100644 --- a/external-odb.c +++ b/external-odb.c @@ -202,3 +202,18 @@ int external_odb_get_many_direct(const struct oid_array *to_get) return -1; } + +int external_odb_put_object(const void *buf, size_t len, + const char *type, unsigned char *sha1) +{ + struct odb_helper *o; + + external_odb_init(); + + for (o = helpers; o; o = o->next) { + int r = odb_helper_put_object(o, buf, len, type, sha1); + if (r <= 0) + return r; + } + return 1; +} diff --git a/external-odb.h b/external-odb.h index a4eda95b09..60da8ed3d4 100644 --- a/external-odb.h +++ b/external-odb.h @@ -18,5 +18,7 @@ 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_get_many_direct(const struct oid_array *to_get); +extern int external_odb_put_object(const void *buf, size_t len, + const char *type, unsigned char *sha1); #endif /* EXTERNAL_ODB_H */ diff --git a/odb-helper.c b/odb-helper.c index 30cfe689de..2734af793b 100644 --- a/odb-helper.c +++ b/odb-helper.c @@ -72,9 +72,10 @@ static void prepare_helper_command(struct argv_array *argv, const char *cmd, strbuf_release(&buf); } -__attribute__((format (printf,3,4))) +__attribute__((format (printf,4,5))) static int odb_helper_start(struct odb_helper *o, struct odb_helper_cmd *cmd, + int use_stdin, const char *fmt, ...) { va_list ap; @@ -91,7 +92,10 @@ static int odb_helper_start(struct odb_helper *o, cmd->child.argv = cmd->argv.argv; cmd->child.use_shell = 1; - cmd->child.no_stdin = 1; + if (use_stdin) + cmd->child.in = -1; + else + cmd->child.no_stdin = 1; cmd->child.out = -1; if (start_command(&cmd->child) < 0) { @@ -124,7 +128,10 @@ int odb_helper_init(struct odb_helper *o) return 0; o->initialized = 1; - if (odb_helper_start(o, &cmd, "init") < 0) + if (o->type != ODB_HELPER_SCRIPT_CMD) + return 0; + + if (odb_helper_start(o, &cmd, 0, "init") < 0) return -1; fh = xfdopen(cmd.child.out, "r"); @@ -180,7 +187,7 @@ static void have_object_script(struct odb_helper *o) FILE *fh; struct strbuf line = STRBUF_INIT; - if (odb_helper_start(o, &cmd, "have") < 0) + if (odb_helper_start(o, &cmd, 0, "have") < 0) return; fh = xfdopen(cmd.child.out, "r"); @@ -245,7 +252,7 @@ int odb_helper_get_object(struct odb_helper *o, const unsigned char *sha1, if (!obj) return -1; - if (odb_helper_start(o, &cmd, "get_git_obj %s", sha1_to_hex(sha1)) < 0) + if (odb_helper_start(o, &cmd, 0, "get_git_obj %s", sha1_to_hex(sha1)) < 0) return -1; memset(&stream, 0, sizeof(stream)); @@ -348,7 +355,7 @@ int odb_helper_get_direct(struct odb_helper *o, if (!obj) return -1; - if (odb_helper_start(o, &cmd, "get_direct %s", sha1_to_hex(sha1)) < 0) + if (odb_helper_start(o, &cmd, 0, "get_direct %s", sha1_to_hex(sha1)) < 0) return -1; if (odb_helper_finish(o, &cmd)) @@ -375,3 +382,35 @@ int odb_helper_get_many_direct(struct odb_helper *o, return res; } + +int odb_helper_put_object(struct odb_helper *o, + const void *buf, size_t len, + const char *type, unsigned char *sha1) +{ + struct odb_helper_cmd cmd; + + if (o->type != ODB_HELPER_SCRIPT_CMD) + return 1; + + if (odb_helper_start(o, &cmd, 1, "put_raw_obj %s %"PRIuMAX" %s", + sha1_to_hex(sha1), (uintmax_t)len, type) < 0) + return -1; + + do { + int w = xwrite(cmd.child.in, buf, len); + if (w < 0) { + error("unable to write to odb helper '%s': %s", + o->name, strerror(errno)); + close(cmd.child.in); + close(cmd.child.out); + odb_helper_finish(o, &cmd); + return -1; + } + len -= w; + } while (len > 0); + + close(cmd.child.in); + close(cmd.child.out); + odb_helper_finish(o, &cmd); + return 0; +} diff --git a/odb-helper.h b/odb-helper.h index 3ec2d8448f..b6a1498662 100644 --- a/odb-helper.h +++ b/odb-helper.h @@ -42,5 +42,8 @@ extern int odb_helper_get_direct(struct odb_helper *o, const unsigned char *sha1); extern int odb_helper_get_many_direct(struct odb_helper *o, const struct oid_array *to_get); +extern int odb_helper_put_object(struct odb_helper *o, + const void *buf, size_t len, + const char *type, unsigned char *sha1); #endif /* ODB_HELPER_H */ diff --git a/sha1_file.c b/sha1_file.c index 99adfceede..64679fae36 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1709,6 +1709,8 @@ int write_object_file(const void *buf, unsigned long len, const char *type, * it out into .git/objects/??/?{38} file. */ write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen); + if (!external_odb_put_object(buf, len, type, oid->hash)) + return 0; if (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash)) return 0; return write_loose_object(oid, hdr, hdrlen, buf, len, 0); -- 2.17.0.rc0.37.g8f476fabe9