diff --git a/builtin/odb--daemon.c b/builtin/odb--daemon.c index e73c5f8ac5794d..3d78326a0ce945 100644 --- a/builtin/odb--daemon.c +++ b/builtin/odb--daemon.c @@ -1,6 +1,7 @@ #include "builtin.h" #include "config.h" #include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "oidmap.h" #include "parse-options.h" @@ -211,6 +212,49 @@ static int odb_ipc_cb__hash_object(struct my_odb_ipc_state *state, return 0; } +static int odb_ipc_cb__get_parent(struct my_odb_ipc_state *state, + const char *command, size_t command_len, + ipc_server_reply_cb *reply_cb, + struct ipc_server_reply_data *reply_data) +{ + struct odb_over_ipc__get_parent__request *req; + struct odb_over_ipc__get_parent__response *resp; + const char *name; + size_t name_len; + int ret; + + if (command_len < sizeof(*req)) + BUG("incorrect size for binary data"); + + req = (struct odb_over_ipc__get_parent__request *)command; + + name = command + sizeof(*req); + name_len = command_len - sizeof(*req); + + if (req->name_len != name_len) + BUG("incorrect data length"); + + resp = xmalloc(sizeof(*resp)); + memcpy(&resp->key.key, "get-parent", 11); + + ret = get_parent(the_repository, name, name_len, &resp->oid, req->idx); + + if (ret != FOUND) + goto fail; + + reply_cb(reply_data, (const char *)resp, sizeof(*resp)); + + return 0; + +fail: + /* + * Send the client an error response to force it to do + * the work itself. + */ + reply_cb(reply_data, "error", 6); + return 0; +} + /* * This callback handles IPC requests from clients. We run on an * arbitrary thread. @@ -277,6 +321,18 @@ static int odb_ipc_cb(void *data, return 0; } + if (!strcmp(command, "get-parent")) { + /* + * A client has requested that we find the parent of a given + * object. + */ + trace2_region_enter("odb-daemon", "get-parent", NULL); + ret = odb_ipc_cb__get_parent(state, command, command_len, + reply_cb, reply_data); + trace2_region_leave("odb-daemon", "get-parent", NULL); + return 0; + } + // TODO respond to other requests from client. // // TODO decide how to return an error for unknown commands. diff --git a/object-name.c b/object-name.c index 55dc8a67d4241c..287faf1e397037 100644 --- a/object-name.c +++ b/object-name.c @@ -24,6 +24,7 @@ #include "commit-reach.h" #include "date.h" #include "object-file-convert.h" +#include "odb-over-ipc.h" static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *); @@ -1086,13 +1087,17 @@ enum get_oid_result get_parent(struct repository *r, struct object_id *result, int idx) { struct object_id oid; - enum get_oid_result ret = get_oid_1(r, name, len, &oid, - GET_OID_COMMITTISH); + enum get_oid_result ret; struct commit *commit; struct commit_list *p; + if (odb_over_ipc__get_parent(r, name, len, idx, result) == 0) + return FOUND; + + ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH); if (ret) return ret; + commit = lookup_commit_reference(r, &oid); if (repo_parse_commit(r, commit)) return MISSING_OBJECT; diff --git a/odb-over-ipc.c b/odb-over-ipc.c index 1d342b71ebbebd..979d56d9e499c5 100644 --- a/odb-over-ipc.c +++ b/odb-over-ipc.c @@ -264,4 +264,51 @@ int odb_over_ipc__hash_object(struct repository *r, struct object_id *oid, return ret; } +int odb_over_ipc__get_parent(struct repository *r, const char *name, int len, + int idx, struct object_id *result) +{ + struct odb_over_ipc__get_parent__request req; + struct odb_over_ipc__get_parent__response *resp; + struct strbuf msg = STRBUF_INIT; + struct strbuf answer = STRBUF_INIT; + int ret; + + if (is_daemon) + return -1; + + if (!core_use_odb_over_ipc) + return -1; + + if (r != the_repository) // TODO not dealing with this + return -1; + + memset(&req, 0, sizeof(req)); + memcpy(req.key.key, "get-parent", 10); + req.idx = idx; + req.name_len = len; + + /* Append the name at the end of the request */ + strbuf_init(&msg, sizeof(req) + len); + strbuf_add(&msg, &req, sizeof(req)); + strbuf_add(&msg, name, len); + + ret = odb_over_ipc__command((const char *)msg.buf, msg.len, &answer); + if (ret) + return ret; + + if (!strncmp(answer.buf, "error", 5)) { + trace2_printf("odb-over-ipc: failed"); + return -1; + } + + if (answer.len != sizeof(*resp)) + BUG("incorrect size for binary data"); + resp = (struct odb_over_ipc__get_parent__response *)answer.buf; + + oidcpy(result, &resp->oid); + + strbuf_release(&answer); + return ret; +} + #endif /* SUPPORTS_SIMPLE_IPC */ diff --git a/odb-over-ipc.h b/odb-over-ipc.h index 8fc1f27200731d..d3a9858cad93dc 100644 --- a/odb-over-ipc.h +++ b/odb-over-ipc.h @@ -82,6 +82,19 @@ struct odb_over_ipc__hash_object__response struct object_id oid; }; +struct odb_over_ipc__get_parent__request +{ + struct odb_over_ipc__key key; + int idx; + int name_len; +}; + +struct odb_over_ipc__get_parent__response +{ + struct odb_over_ipc__key key; + struct object_id oid; +}; + /* * Connect to an existing `git odb--daemon` process and ask it for * an object. This is intended to be inserted into the client @@ -100,6 +113,9 @@ int odb_over_ipc__get_oid(struct repository *r, const struct object_id *oid, int odb_over_ipc__hash_object(struct repository *r, struct object_id *oid, int fd, enum object_type type, unsigned flags); +int odb_over_ipc__get_parent(struct repository *r, const char *name, int len, + int idx, struct object_id *result); + /* * Explicitly shutdown IPC connection to the `git odb--daemon` process. * The connection is implicitly created upon the first request and we