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

[RFC/PATCH v3 15/16] odb-helper: add 'store_plain_objects' to 'struct odb_helper'

From
Christian Couder <christian.couder@gmail.com>
Date
Nov 30, 2016, 21:04 UTC
Message-ID
<20161130210420.15982-16-chriscool@tuxfamily.org>
In-Reply-To
<20161130210420.15982-1-chriscool@tuxfamily.org>

This adds a configuration option odb.<helper>.plainObjects and the corresponding boolean variable called 'store_plain_objects' in 'struct odb_helper' to make it possible for external object databases to store object as plain objects instead of Git objects.

The existing odb_helper_fetch_object() is renamed odb_helper_fetch_git_object() and a new odb_helper_fetch_plain_object() is introduce to deal with external objects that are not in Git format.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 external-odb.c |   2 +
 odb-helper.c   | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 odb-helper.h   |   1 +
 3 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/external-odb.c b/external-odb.c
index a980fbfbf2..af55377281 100644
--- a/external-odb.c
+++ b/external-odb.c
@@ -36,6 +36,8 @@ static int external_odb_config(const char *var, const char *value, void *data)
 
 	if (!strcmp(key, "command"))
 		return git_config_string(&o->cmd, var, value);
+	if (!strcmp(key, "plainobjects"))
+		o->store_plain_objects = git_config_bool(var, value);
 
 	return 0;
 }
diff --git a/odb-helper.c b/odb-helper.c
index 7b7de7380f..6b9fb7927a 100644
--- a/odb-helper.c
+++ b/odb-helper.c
@@ -153,8 +153,107 @@ int odb_helper_has_object(struct odb_helper *o, const unsigned char *sha1)
 	return !!odb_helper_lookup(o, sha1);
 }
 
-int odb_helper_fetch_object(struct odb_helper *o, const unsigned char *sha1,
-			    int fd)
+static int odb_helper_fetch_plain_object(struct odb_helper *o,
+					 const unsigned char *sha1,
+					 int fd)
+{
+	struct odb_helper_object *obj;
+	struct odb_helper_cmd cmd;
+	unsigned long total_got = 0;
+
+	char hdr[32];
+	int hdrlen;
+
+	int ret = Z_STREAM_END;
+	unsigned char compressed[4096];
+	git_zstream stream;
+	git_SHA_CTX hash;
+	unsigned char real_sha1[20];
+
+	obj = odb_helper_lookup(o, sha1);
+	if (!obj)
+		return -1;
+
+	if (odb_helper_start(o, &cmd, 0, "get %s", sha1_to_hex(sha1)) < 0)
+		return -1;
+
+	/* Set it up */
+	git_deflate_init(&stream, zlib_compression_level);
+	stream.next_out = compressed;
+	stream.avail_out = sizeof(compressed);
+	git_SHA1_Init(&hash);
+
+	/* First header.. */
+	hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(obj->type), obj->size) + 1;
+	stream.next_in = (unsigned char *)hdr;
+	stream.avail_in = hdrlen;
+	while (git_deflate(&stream, 0) == Z_OK)
+		; /* nothing */
+	git_SHA1_Update(&hash, hdr, hdrlen);
+
+	for (;;) {
+		unsigned char buf[4096];
+		int r;
+
+		r = xread(cmd.child.out, buf, sizeof(buf));
+		if (r < 0) {
+			error("unable to read from odb helper '%s': %s",
+			      o->name, strerror(errno));
+			close(cmd.child.out);
+			odb_helper_finish(o, &cmd);
+			git_deflate_end(&stream);
+			return -1;
+		}
+		if (r == 0)
+			break;
+
+		total_got += r;
+
+		/* Then the data itself.. */
+		stream.next_in = (void *)buf;
+		stream.avail_in = r;
+		do {
+			unsigned char *in0 = stream.next_in;
+			ret = git_deflate(&stream, Z_FINISH);
+			git_SHA1_Update(&hash, in0, stream.next_in - in0);
+			write_or_die(fd, compressed, stream.next_out - compressed);
+			stream.next_out = compressed;
+			stream.avail_out = sizeof(compressed);
+		} while (ret == Z_OK);
+	}
+
+	close(cmd.child.out);
+	if (ret != Z_STREAM_END) {
+		warning("bad zlib data from odb helper '%s' for %s",
+			o->name, sha1_to_hex(sha1));
+		return -1;
+	}
+	ret = git_deflate_end_gently(&stream);
+	if (ret != Z_OK) {
+		warning("deflateEnd on object %s from odb helper '%s' failed (%d)",
+			sha1_to_hex(sha1), o->name, ret);
+		return -1;
+	}
+	git_SHA1_Final(real_sha1, &hash);
+	if (hashcmp(sha1, real_sha1)) {
+		warning("sha1 mismatch from odb helper '%s' for %s (got %s)",
+			o->name, sha1_to_hex(sha1), sha1_to_hex(real_sha1));
+		return -1;
+	}
+	if (odb_helper_finish(o, &cmd))
+		return -1;
+	if (total_got != obj->size) {
+		warning("size mismatch from odb helper '%s' for %s (%lu != %lu)",
+			o->name, sha1_to_hex(sha1), total_got, obj->size);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int odb_helper_fetch_git_object(struct odb_helper *o,
+				       const unsigned char *sha1,
+				       int fd)
 {
 	struct odb_helper_object *obj;
 	struct odb_helper_cmd cmd;
@@ -242,6 +341,16 @@ int odb_helper_fetch_object(struct odb_helper *o, const unsigned char *sha1,
 	return 0;
 }
 
+int odb_helper_fetch_object(struct odb_helper *o,
+			    const unsigned char *sha1,
+			    int fd)
+{
+	if (o->store_plain_objects)
+		return odb_helper_fetch_plain_object(o, sha1, fd);
+	else
+		return odb_helper_fetch_git_object(o, sha1, fd);
+}
+
 int odb_helper_for_each_object(struct odb_helper *o,
 			       each_external_object_fn fn,
 			       void *data)
diff --git a/odb-helper.h b/odb-helper.h
index af31cc27d5..80d332139d 100644
--- a/odb-helper.h
+++ b/odb-helper.h
@@ -6,6 +6,7 @@
 struct odb_helper {
 	const char *name;
 	const char *cmd;
+	int store_plain_objects;
 
 	struct odb_helper_object {
 		unsigned char sha1[20];
-- 
2.11.0.rc2.37.geb49ca6
Previous: Christian CouderNext: Christian Couder
Message 5 of 30 in “Add initial experimental external ODB support”
  1. 00/16 Add initial experimental external ODB supportChristian Couder, Nov 30, 2016
  2. 05/16 t0400: add test for 'put' commandChristian Couder, Nov 30, 2016
  3. 06/16 external odb: add write supportChristian Couder, Nov 30, 2016
  4. 16/16 t0420: add test with HTTP external odbChristian Couder, Nov 30, 2016
  5. 15/16 odb-helper: add 'store_plain_objects' to 'struct odb_helper'Christian Couder, Nov 30, 2016
  6. 14/16 lib-httpd: add apache-e-odb.confChristian Couder, Nov 30, 2016
  7. 01/16 Add initial external odb supportChristian Couder, Nov 30, 2016
  8. Junio C HamanoNov 30, 2016
  9. Jeff KingNov 30, 2016
  10. Christian CouderAug 3, 2017
  11. Christian CouderAug 3, 2017
  12. Jeff KingAug 3, 2017
  13. 09/16 Add GIT_NO_EXTERNAL_ODB env variableChristian Couder, Nov 30, 2016
  14. 10/16 Add t0410 to test external ODB transferChristian Couder, Nov 30, 2016
  15. 13/16 lib-httpd: add list.shChristian Couder, Nov 30, 2016
  16. 11/16 lib-httpd: pass config file to start_httpd()Christian Couder, Nov 30, 2016
  17. 07/16 external-odb: accept only blobs for nowChristian Couder, Nov 30, 2016
  18. 03/16 t0400: use --batch-all-objects to get all objectsChristian Couder, Nov 30, 2016
  19. 02/16 external odb foreachChristian Couder, Nov 30, 2016
  20. 12/16 lib-httpd: add upload.shChristian Couder, Nov 30, 2016
  21. Junio C HamanoNov 30, 2016
  22. Christian CouderDec 13, 2016
  23. Junio C HamanoDec 13, 2016
  24. Christian CouderDec 15, 2016
  25. 04/16 t0400: add 'put' command to odb-helper scriptChristian Couder, Nov 30, 2016
  26. 08/16 t0400: add test for external odb write supportChristian Couder, Nov 30, 2016
  27. Lars SchneiderDec 3, 2016
  28. Jeff KingDec 5, 2016
  29. Christian CouderDec 13, 2016
  30. Lars SchneiderDec 18, 2016

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.