git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 11/36] odb-helper: add odb_helper_init() to send 'init' instruction

From
Christian Couder <christian.couder@gmail.com>
Date
Mar 19, 2018, 13:31 UTC
Message-ID
<20180319133147.15413-12-chriscool@tuxfamily.org>
In-Reply-To
<20180319133147.15413-1-chriscool@tuxfamily.org>

Let's add an odb_helper_init() function to send an 'init' instruction to the helpers. This 'init' instruction is especially useful to get the capabilities that are supported by the helpers.

So while at it, let's also add a parse_capabilities() function to parse them and a supported_capabilities variable in struct odb_helper to store them.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 external-odb.c          | 13 ++++++++-
 odb-helper.c            | 58 +++++++++++++++++++++++++++++++++++++++++
 odb-helper.h            | 11 ++++++++
 t/t0500-external-odb.sh |  4 +++
 4 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/external-odb.c b/external-odb.c
index 9f797d66f4..ae6bc017fe 100644
--- a/external-odb.c
+++ b/external-odb.c
@@ -35,6 +35,8 @@ static int external_odb_config(const char *var, const char *value, void *data)
 
 	if (!strcmp(subkey, "promisorremote")) {
 		o->type = ODB_HELPER_GIT_REMOTE;
+		o->supported_capabilities |= ODB_HELPER_CAP_HAVE;
+		o->supported_capabilities |= ODB_HELPER_CAP_GET_DIRECT;
 		return git_config_string(&o->dealer, var, value);
 	}
 	if (!strcmp(subkey, "scriptcommand")) {
@@ -52,12 +54,16 @@ static int external_odb_config(const char *var, const char *value, void *data)
 static void external_odb_do_init(int force)
 {
 	static int initialized;
+	struct odb_helper *o;
 
 	if ((!force && initialized) || !use_external_odb)
 		return;
 	initialized = 1;
 
 	git_config(external_odb_config, NULL);
+
+	for (o = helpers; o; o = o->next)
+		odb_helper_init(o);
 }
 
 static inline void external_odb_init(void)
@@ -104,9 +110,12 @@ int external_odb_has_object(const unsigned char *sha1)
 
 	external_odb_init();
 
-	for (o = helpers; o; o = o->next)
+	for (o = helpers; o; o = o->next) {
+		if (!(o->supported_capabilities & ODB_HELPER_CAP_HAVE))
+			return 1;
 		if (odb_helper_has_object(o, sha1))
 			return 1;
+	}
 	return 0;
 }
 
@@ -164,6 +173,8 @@ int external_odb_get_direct(const unsigned char *sha1)
 	external_odb_init();
 
 	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;
diff --git a/odb-helper.c b/odb-helper.c
index bf3c1ad8ac..a99f4a1299 100644
--- a/odb-helper.c
+++ b/odb-helper.c
@@ -6,6 +6,40 @@
 #include "sha1-lookup.h"
 #include "fetch-object.h"
 
+static void parse_capabilities(char *cap_buf,
+			       unsigned int *supported_capabilities,
+			       const char *process_name)
+{
+	struct string_list cap_list = STRING_LIST_INIT_NODUP;
+
+	string_list_split_in_place(&cap_list, cap_buf, '=', 1);
+
+	if (cap_list.nr == 2 && !strcmp(cap_list.items[0].string, "capability")) {
+		const char *cap_name = cap_list.items[1].string;
+
+		if (!strcmp(cap_name, "get_git_obj")) {
+			*supported_capabilities |= ODB_HELPER_CAP_GET_GIT_OBJ;
+		} else if (!strcmp(cap_name, "get_raw_obj")) {
+			*supported_capabilities |= ODB_HELPER_CAP_GET_RAW_OBJ;
+		} else if (!strcmp(cap_name, "get_direct")) {
+			*supported_capabilities |= ODB_HELPER_CAP_GET_DIRECT;
+		} else if (!strcmp(cap_name, "put_git_obj")) {
+			*supported_capabilities |= ODB_HELPER_CAP_PUT_GIT_OBJ;
+		} else if (!strcmp(cap_name, "put_raw_obj")) {
+			*supported_capabilities |= ODB_HELPER_CAP_PUT_RAW_OBJ;
+		} else if (!strcmp(cap_name, "put_direct")) {
+			*supported_capabilities |= ODB_HELPER_CAP_PUT_DIRECT;
+		} else if (!strcmp(cap_name, "have")) {
+			*supported_capabilities |= ODB_HELPER_CAP_HAVE;
+		} else {
+			warning("external process '%s' requested unsupported read-object capability '%s'",
+				process_name, cap_name);
+		}
+	}
+
+	string_list_clear(&cap_list, 0);
+}
+
 struct odb_helper *odb_helper_new(const char *name, int namelen)
 {
 	struct odb_helper *o;
@@ -80,6 +114,30 @@ static int odb_helper_finish(struct odb_helper *o,
 	return 0;
 }
 
+int odb_helper_init(struct odb_helper *o)
+{
+	struct odb_helper_cmd cmd;
+	FILE *fh;
+	struct strbuf line = STRBUF_INIT;
+
+	if (o->initialized)
+		return 0;
+	o->initialized = 1;
+
+	if (odb_helper_start(o, &cmd, "init") < 0)
+		return -1;
+
+	fh = xfdopen(cmd.child.out, "r");
+	while (strbuf_getline(&line, fh) != EOF)
+		parse_capabilities(line.buf, &o->supported_capabilities, o->name);
+
+	strbuf_release(&line);
+	fclose(fh);
+	odb_helper_finish(o, &cmd);
+
+	return 0;
+}
+
 static int parse_object_line(struct odb_helper_object *o, const char *line)
 {
 	char *end;
diff --git a/odb-helper.h b/odb-helper.h
index 819182f76a..7720684744 100644
--- a/odb-helper.h
+++ b/odb-helper.h
@@ -3,10 +3,20 @@
 
 #include "external-odb.h"
 
+#define ODB_HELPER_CAP_GET_GIT_OBJ    (1u<<0)
+#define ODB_HELPER_CAP_GET_RAW_OBJ    (1u<<1)
+#define ODB_HELPER_CAP_GET_DIRECT     (1u<<2)
+#define ODB_HELPER_CAP_PUT_GIT_OBJ    (1u<<3)
+#define ODB_HELPER_CAP_PUT_RAW_OBJ    (1u<<4)
+#define ODB_HELPER_CAP_PUT_DIRECT     (1u<<5)
+#define ODB_HELPER_CAP_HAVE           (1u<<6)
+
 struct odb_helper {
 	const char *name;
 	const char *dealer;
 	enum odb_helper_type type;
+	unsigned int supported_capabilities;
+	int initialized;
 
 	struct odb_helper_object {
 		struct object_id oid;
@@ -21,6 +31,7 @@ struct odb_helper {
 };
 
 extern struct odb_helper *odb_helper_new(const char *name, int namelen);
+extern int odb_helper_init(struct odb_helper *o);
 extern int odb_helper_has_object(struct odb_helper *o,
 				 const unsigned char *sha1);
 extern int odb_helper_get_object(struct odb_helper *o,
diff --git a/t/t0500-external-odb.sh b/t/t0500-external-odb.sh
index eaa3688a31..977fea852d 100755
--- a/t/t0500-external-odb.sh
+++ b/t/t0500-external-odb.sh
@@ -9,6 +9,10 @@ export ALT_SOURCE
 write_script odb-helper <<\EOF
 GIT_DIR=$ALT_SOURCE; export GIT_DIR
 case "$1" in
+init)
+	echo "capability=get_git_obj"
+	echo "capability=have"
+	;;
 have)
 	git cat-file --batch-check --batch-all-objects |
 	awk '{print $1 " " $3 " " $2}'
-- 
2.17.0.rc0.37.g8f476fabe9
Previous: Christian CouderNext: Christian Couder
Message 21 of 38 in “Promisor remotes and external ODB support”
  1. 00/36 Promisor remotes and external ODB supportChristian Couder, Mar 19, 2018
  2. 01/36 Add initial external odb supportChristian Couder, Mar 19, 2018
  3. 02/36 sha1_file: add prepare_external_alt_odb()Christian Couder, Mar 19, 2018
  4. 06/36 sha1_file: prepare for external odbsChristian Couder, Mar 19, 2018
  5. 05/36 external-odb: implement external_odb_get_directChristian Couder, Mar 19, 2018
  6. 07/36 odb-helper: add 'enum odb_helper_type'Christian Couder, Mar 19, 2018
  7. 04/36 external-odb: add has_external_odb()Christian Couder, Mar 19, 2018
  8. 03/36 Add GIT_NO_EXTERNAL_ODB env variableChristian Couder, Mar 19, 2018
  9. 12/36 external-odb: add external_odb_get_many_direct()Christian Couder, Mar 19, 2018
  10. 16/36 t0500: add 'put_raw_obj' instruction to odb-helper scriptChristian Couder, Mar 19, 2018
  11. 18/36 external-odb: accept only blobs for nowChristian Couder, Mar 19, 2018
  12. 17/36 external odb: add 'put_raw_obj' supportChristian Couder, Mar 19, 2018
  13. 14/36 Use odb.origin.partialclonefilter instead of core.partialclonefilterChristian Couder, Mar 19, 2018
  14. 13/36 Use external_odb_get_direct() and has_external_odb()Christian Couder, Mar 19, 2018
  15. 22/36 lib-httpd: add upload.shChristian Couder, Mar 19, 2018
  16. 21/36 lib-httpd: pass config file to start_httpd()Christian Couder, Mar 19, 2018
  17. 26/36 pack-objects: don't pack objects in external odbsChristian Couder, Mar 19, 2018
  18. 27/36 Add t0520 to test transfer to HTTP external odbChristian Couder, Mar 19, 2018
  19. 30/36 Add t0560 to test passing git objectsChristian Couder, Mar 19, 2018
  20. 36/36 Add Documentation/technical/external-odb.txtChristian Couder, Mar 19, 2018
  21. 11/36 odb-helper: add odb_helper_init() to send 'init' instructionChristian Couder, Mar 19, 2018
  22. 34/36 Add t0580 to test "have" capability and raw objectsChristian Couder, Mar 19, 2018
  23. 33/36 odb-helper: add have_object_process()Christian Couder, Mar 19, 2018
  24. 35/36 external-odb: use 'odb=magic' attribute to mark odb blobsChristian Couder, Mar 19, 2018
  25. 15/36 external-odb: add 'get_direct' supportChristian Couder, Mar 19, 2018
  26. 32/36 Add t0570 to test passing raw objectsChristian Couder, Mar 19, 2018
  27. 31/36 odb-helper: add put_object_process()Christian Couder, Mar 19, 2018
  28. 29/36 Add t0550 to test 'get_direct' mechanismChristian Couder, Mar 19, 2018
  29. 28/36 odb-helper: add init_object_process()Christian Couder, Mar 19, 2018
  30. 25/36 odb-helper: add odb_helper_get_raw_object()Christian Couder, Mar 19, 2018
  31. 20/36 Add t0510 to test external ODB transferChristian Couder, Mar 19, 2018
  32. 19/36 t0500: add test for external odb write supportChristian Couder, Mar 19, 2018
  33. 24/36 lib-httpd: add apache-e-odb.confChristian Couder, Mar 19, 2018
  34. 23/36 lib-httpd: add list.shChristian Couder, Mar 19, 2018
  35. 10/36 odb-helper: add 'script_mode' to 'struct odb_helper'Christian Couder, Mar 19, 2018
  36. 09/36 external-odb: add script mode supportChristian Couder, Mar 19, 2018
  37. 08/36 external-odb: add external_odb_reinit()Christian Couder, Mar 19, 2018
  38. Junio C HamanoMar 19, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.