Re: [RFC/PATCH v4 30/49] odb-helper: add read_object_process()

2017-07-10 Thread Ben Peart



On 6/20/2017 3:55 AM, Christian Couder wrote:

From: Ben Peart 

Signed-off-by: Ben Peart 
Signed-off-by: Christian Couder 
---
  odb-helper.c | 202 ---
  odb-helper.h |   5 ++
  sha1_file.c  |  33 +-
  3 files changed, 227 insertions(+), 13 deletions(-)

diff --git a/odb-helper.c b/odb-helper.c
index 5fb56c6135..20e83cb55a 100644
--- a/odb-helper.c
+++ b/odb-helper.c
@@ -4,6 +4,187 @@
  #include "odb-helper.h"
  #include "run-command.h"
  #include "sha1-lookup.h"
+#include "sub-process.h"
+#include "pkt-line.h"
+#include "sigchain.h"
+
+struct read_object_process {
+   struct subprocess_entry subprocess;
+   unsigned int supported_capabilities;
+};
+
+static int subprocess_map_initialized;
+static struct hashmap subprocess_map;
+
+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(_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")) {
+   *supported_capabilities |= ODB_HELPER_CAP_GET;
+   } else if (!strcmp(cap_name, "put")) {
+   *supported_capabilities |= ODB_HELPER_CAP_PUT;
+   } 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(_list, 0);
+}
+
+static int start_read_object_fn(struct subprocess_entry *subprocess)
+{
+   int err;
+   struct read_object_process *entry = (struct read_object_process 
*)subprocess;
+   struct child_process *process = >process;
+   char *cap_buf;
+
+   sigchain_push(SIGPIPE, SIG_IGN);
+
+   err = packet_writel(process->in, "git-read-object-client", "version=1", 
NULL);
+   if (err)
+   goto done;
+
+   err = strcmp(packet_read_line(process->out, NULL), 
"git-read-object-server");
+   if (err) {
+   error("external process '%s' does not support read-object protocol 
version 1", subprocess->cmd);
+   goto done;
+   }
+   err = strcmp(packet_read_line(process->out, NULL), "version=1");
+   if (err)
+   goto done;
+   err = packet_read_line(process->out, NULL) != NULL;
+   if (err)
+   goto done;
+
+   err = packet_writel(process->in, "capability=get", NULL);
+   if (err)
+   goto done;
+
+   while ((cap_buf = packet_read_line(process->out, NULL)))
+   parse_capabilities(cap_buf, >supported_capabilities, 
subprocess->cmd);
+
+done:
+   sigchain_pop(SIGPIPE);
+
+   return err;
+}
+
+static struct read_object_process *launch_read_object_process(const char *cmd)
+{
+   struct read_object_process *entry;
+
+   if (!subprocess_map_initialized) {
+   subprocess_map_initialized = 1;
+   hashmap_init(_map, (hashmap_cmp_fn) cmd2process_cmp, 
0);
+   entry = NULL;
+   } else {
+   entry = (struct read_object_process 
*)subprocess_find_entry(_map, cmd);
+   }
+
+   fflush(NULL);
+
+   if (!entry) {
+   entry = xmalloc(sizeof(*entry));
+   entry->supported_capabilities = 0;
+
+   if (subprocess_start(_map, >subprocess, cmd, 
start_read_object_fn)) {
+   free(entry);
+   return 0;
+   }
+   }
+
+   return entry;
+}
+
+static int check_object_process_error(int err,
+ const char *status,
+ struct read_object_process *entry,
+ const char *cmd,
+ unsigned int capability)
+{
+   if (!err)
+   return;
+
+   if (!strcmp(status, "error")) {
+   /* The process signaled a problem with the file. */
+   } else if (!strcmp(status, "notfound")) {
+   /* Object was not found */
+   err = -1;
+   } else if (!strcmp(status, "abort")) {
+   /*
+* The process signaled a permanent problem. Don't try to read
+* objects with the same command for the lifetime of the current
+* Git process.
+*/
+   if (capability)
+   entry->supported_capabilities &= ~capability;
+   } else {
+

[RFC/PATCH v4 30/49] odb-helper: add read_object_process()

2017-06-20 Thread Christian Couder
From: Ben Peart 

Signed-off-by: Ben Peart 
Signed-off-by: Christian Couder 
---
 odb-helper.c | 202 ---
 odb-helper.h |   5 ++
 sha1_file.c  |  33 +-
 3 files changed, 227 insertions(+), 13 deletions(-)

diff --git a/odb-helper.c b/odb-helper.c
index 5fb56c6135..20e83cb55a 100644
--- a/odb-helper.c
+++ b/odb-helper.c
@@ -4,6 +4,187 @@
 #include "odb-helper.h"
 #include "run-command.h"
 #include "sha1-lookup.h"
+#include "sub-process.h"
+#include "pkt-line.h"
+#include "sigchain.h"
+
+struct read_object_process {
+   struct subprocess_entry subprocess;
+   unsigned int supported_capabilities;
+};
+
+static int subprocess_map_initialized;
+static struct hashmap subprocess_map;
+
+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(_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")) {
+   *supported_capabilities |= ODB_HELPER_CAP_GET;
+   } else if (!strcmp(cap_name, "put")) {
+   *supported_capabilities |= ODB_HELPER_CAP_PUT;
+   } 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(_list, 0);
+}
+
+static int start_read_object_fn(struct subprocess_entry *subprocess)
+{
+   int err;
+   struct read_object_process *entry = (struct read_object_process 
*)subprocess;
+   struct child_process *process = >process;
+   char *cap_buf;
+
+   sigchain_push(SIGPIPE, SIG_IGN);
+
+   err = packet_writel(process->in, "git-read-object-client", "version=1", 
NULL);
+   if (err)
+   goto done;
+
+   err = strcmp(packet_read_line(process->out, NULL), 
"git-read-object-server");
+   if (err) {
+   error("external process '%s' does not support read-object 
protocol version 1", subprocess->cmd);
+   goto done;
+   }
+   err = strcmp(packet_read_line(process->out, NULL), "version=1");
+   if (err)
+   goto done;
+   err = packet_read_line(process->out, NULL) != NULL;
+   if (err)
+   goto done;
+
+   err = packet_writel(process->in, "capability=get", NULL);
+   if (err)
+   goto done;
+
+   while ((cap_buf = packet_read_line(process->out, NULL)))
+   parse_capabilities(cap_buf, >supported_capabilities, 
subprocess->cmd);
+
+done:
+   sigchain_pop(SIGPIPE);
+
+   return err;
+}
+
+static struct read_object_process *launch_read_object_process(const char *cmd)
+{
+   struct read_object_process *entry;
+
+   if (!subprocess_map_initialized) {
+   subprocess_map_initialized = 1;
+   hashmap_init(_map, (hashmap_cmp_fn) cmd2process_cmp, 
0);
+   entry = NULL;
+   } else {
+   entry = (struct read_object_process 
*)subprocess_find_entry(_map, cmd);
+   }
+
+   fflush(NULL);
+
+   if (!entry) {
+   entry = xmalloc(sizeof(*entry));
+   entry->supported_capabilities = 0;
+
+   if (subprocess_start(_map, >subprocess, cmd, 
start_read_object_fn)) {
+   free(entry);
+   return 0;
+   }
+   }
+
+   return entry;
+}
+
+static int check_object_process_error(int err,
+ const char *status,
+ struct read_object_process *entry,
+ const char *cmd,
+ unsigned int capability)
+{
+   if (!err)
+   return;
+
+   if (!strcmp(status, "error")) {
+   /* The process signaled a problem with the file. */
+   } else if (!strcmp(status, "notfound")) {
+   /* Object was not found */
+   err = -1;
+   } else if (!strcmp(status, "abort")) {
+   /*
+* The process signaled a permanent problem. Don't try to read
+* objects with the same command for the lifetime of the current
+* Git process.
+*/
+   if (capability)
+   entry->supported_capabilities &= ~capability;
+   } else {
+   /*
+* Something went wrong with