Skip to content

Commit

Permalink
odb--daemon: implement get-nth-ancestor command
Browse files Browse the repository at this point in the history
Implement a basic version of the get-nth-ancestor command in the ODB
daemon that will simply call the `get_nth_ancestor` function that is
being routed over the IPC channel with the same arguments.

This will get us a simple working proof of concept.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
  • Loading branch information
mjcheetham committed Apr 24, 2024
1 parent b2276a1 commit fb50118
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
56 changes: 56 additions & 0 deletions builtin/odb--daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,50 @@ static int odb_ipc_cb__get_parent(struct my_odb_ipc_state *state,
return 0;
}

static int odb_ipc_cb__get_nth_ancestor(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_nth_ancestor__request *req;
struct odb_over_ipc__get_nth_ancestor__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_nth_ancestor__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-nth-ancestor", 11);

ret = get_nth_ancestor(the_repository, name, name_len, &resp->oid,
req->generation);

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.
Expand Down Expand Up @@ -333,6 +377,18 @@ static int odb_ipc_cb(void *data,
return 0;
}

if (!strcmp(command, "get-nth-ancestor")) {
/*
* A client has requested that we find the nth ancestpr of a
* given object.
*/
trace2_region_enter("odb-daemon", "get-nth-ancestor", NULL);
ret = odb_ipc_cb__get_nth_ancestor(state, command, command_len,
reply_cb, reply_data);
trace2_region_leave("odb-daemon", "get-nth-ancestor", NULL);
return 0;
}

// TODO respond to other requests from client.
//
// TODO decide how to return an error for unknown commands.
Expand Down
3 changes: 3 additions & 0 deletions object-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,9 @@ enum get_oid_result get_nth_ancestor(struct repository *r,
struct commit *commit;
int ret;

if (odb_over_ipc__get_nth_ancestor(r, name, len, generation, result) == 0)
return FOUND;

ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
if (ret)
return ret;
Expand Down
48 changes: 48 additions & 0 deletions odb-over-ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,52 @@ int odb_over_ipc__get_parent(struct repository *r, const char *name, int len,
return ret;
}

int odb_over_ipc__get_nth_ancestor(struct repository *r, const char *name,
int len, int generation,
struct object_id *result)
{
struct odb_over_ipc__get_nth_ancestor__request req;
struct odb_over_ipc__get_nth_ancestor__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-nth-ancestor", 16);
req.generation = generation;
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_nth_ancestor__response *)answer.buf;

oidcpy(result, &resp->oid);

strbuf_release(&answer);
return ret;
}

#endif /* SUPPORTS_SIMPLE_IPC */
17 changes: 17 additions & 0 deletions odb-over-ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ struct odb_over_ipc__get_parent__response
struct object_id oid;
};

struct odb_over_ipc__get_nth_ancestor__request
{
struct odb_over_ipc__key key;
int generation;
int name_len;
};

struct odb_over_ipc__get_nth_ancestor__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
Expand All @@ -116,6 +129,10 @@ int odb_over_ipc__hash_object(struct repository *r, struct object_id *oid,
int odb_over_ipc__get_parent(struct repository *r, const char *name, int len,
int idx, struct object_id *result);

int odb_over_ipc__get_nth_ancestor(struct repository *r, const char *name,
int len, int generation,
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
Expand Down

0 comments on commit fb50118

Please sign in to comment.