Re: [WIP 11/15] serve: introduce git-serve

2017-12-08 Thread Brandon Williams
On 12/07, Junio C Hamano wrote:
> Brandon Williams  writes:
> 
> > +static struct protocol_capability *get_capability(const char *key)
> > +{
> > +   int i;
> > +
> > +   if (!key)
> > +   return NULL;
> > +
> > +   for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
> > +   struct protocol_capability *c = [i];
> > +   const char *out;
> > +   if (skip_prefix(key, c->name, ) && (!*out || *out == '='))
> > +   return c;
> 
> Looks familiar and resembles what was recently discussed on list ;-)
> 
> > +int cmd_serve(int argc, const char **argv, const char *prefix)
> > +{
> > +
> > +   struct option options[] = {
> > +   OPT_END()
> > +   };
> > +
> > +   /* ignore all unknown cmdline switches for now */
> > +   argc = parse_options(argc, argv, prefix, options, grep_usage,
> > +PARSE_OPT_KEEP_DASHDASH |
> > +PARSE_OPT_KEEP_UNKNOWN);
> > +   serve();
> > +
> > +   return 0;
> > +}

I assume that at some point we may want to have a new endpoint that just
does v2 without needing the side channel to tell it to do so.  Maybe for
brand new server commands, like a remote grep or a remote object-stat or
something that don't have a v1 equivalent that can be fallen back to.
That's why I included a builtin/serve.c 

> > ...
> > +/* Main serve loop for protocol version 2 */
> > +void serve(void)
> > +{
> > +   /* serve by default supports v2 */
> > +   packet_write_fmt(1, "version 2\n");
> > +
> > +   advertise_capabilities();
> > +
> > +   for (;;)
> > +   if (process_request())
> > +   break;
> > +}
> 
> I am guessing that this would be run just like upload-pack,
> i.e. invoked via ssh or via git-daemon, and that is why it can just
> assume that fd#0/fd#1 are already connected to the other end.  It
> may be helpful to document somewhere how we envision to invoke this
> program.
> 

This function I was planning to just be executed by upload-pack and
receive-pack when a client requests protocol v2.  But yes the idea would
be that fd#0/fd#1 would be already setup like they are for upload-pack
and receive-pack.

-- 
Brandon Williams


Re: [WIP 11/15] serve: introduce git-serve

2017-12-07 Thread Junio C Hamano
Brandon Williams  writes:

> +static struct protocol_capability *get_capability(const char *key)
> +{
> + int i;
> +
> + if (!key)
> + return NULL;
> +
> + for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
> + struct protocol_capability *c = [i];
> + const char *out;
> + if (skip_prefix(key, c->name, ) && (!*out || *out == '='))
> + return c;

Looks familiar and resembles what was recently discussed on list ;-)

> +int cmd_serve(int argc, const char **argv, const char *prefix)
> +{
> +
> + struct option options[] = {
> + OPT_END()
> + };
> +
> + /* ignore all unknown cmdline switches for now */
> + argc = parse_options(argc, argv, prefix, options, grep_usage,
> +  PARSE_OPT_KEEP_DASHDASH |
> +  PARSE_OPT_KEEP_UNKNOWN);
> + serve();
> +
> + return 0;
> +}
> ...
> +/* Main serve loop for protocol version 2 */
> +void serve(void)
> +{
> + /* serve by default supports v2 */
> + packet_write_fmt(1, "version 2\n");
> +
> + advertise_capabilities();
> +
> + for (;;)
> + if (process_request())
> + break;
> +}

I am guessing that this would be run just like upload-pack,
i.e. invoked via ssh or via git-daemon, and that is why it can just
assume that fd#0/fd#1 are already connected to the other end.  It
may be helpful to document somewhere how we envision to invoke this
program.



[WIP 11/15] serve: introduce git-serve

2017-12-04 Thread Brandon Williams
Introduce git-serve, the base server for protocol version 2.

When connecting to a server supporting protocol version 2, the server
will send a list all of its capabilities and then wait for the client to
send a command request.  Some capabilities advertised are 'commands'
which the client can request (push and fetch are examples of such
commands).  A command request is comprised of a list of capabilities,
including a command request "command=", a delimiter packet,
followed by a list of parameters for the requested command.

At the end of each command a client can request that another command be
executed or can terminate the connection by sending a flush packet.

Signed-off-by: Brandon Williams 
---
 .gitignore  |   1 +
 Makefile|   2 +
 builtin.h   |   1 +
 builtin/serve.c |  25 
 git.c   |   1 +
 serve.c | 185 
 serve.h |   6 ++
 7 files changed, 221 insertions(+)
 create mode 100644 builtin/serve.c
 create mode 100644 serve.c
 create mode 100644 serve.h

diff --git a/.gitignore b/.gitignore
index 833ef3b0b..2d0450c26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,6 +140,7 @@
 /git-rm
 /git-send-email
 /git-send-pack
+/git-serve
 /git-sh-i18n
 /git-sh-i18n--envsubst
 /git-sh-setup
diff --git a/Makefile b/Makefile
index 86394b69d..710672cf4 100644
--- a/Makefile
+++ b/Makefile
@@ -862,6 +862,7 @@ LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
 LIB_OBJS += send-pack.o
 LIB_OBJS += sequencer.o
+LIB_OBJS += serve.o
 LIB_OBJS += server-info.o
 LIB_OBJS += setup.o
 LIB_OBJS += sha1-array.o
@@ -995,6 +996,7 @@ BUILTIN_OBJS += builtin/rev-parse.o
 BUILTIN_OBJS += builtin/revert.o
 BUILTIN_OBJS += builtin/rm.o
 BUILTIN_OBJS += builtin/send-pack.o
+BUILTIN_OBJS += builtin/serve.o
 BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
diff --git a/builtin.h b/builtin.h
index f332a1257..3f3fdfc28 100644
--- a/builtin.h
+++ b/builtin.h
@@ -215,6 +215,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const 
char *prefix);
 extern int cmd_revert(int argc, const char **argv, const char *prefix);
 extern int cmd_rm(int argc, const char **argv, const char *prefix);
 extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
+extern int cmd_serve(int argc, const char **argv, const char *prefix);
 extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
 extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
diff --git a/builtin/serve.c b/builtin/serve.c
new file mode 100644
index 0..2ecaad3b6
--- /dev/null
+++ b/builtin/serve.c
@@ -0,0 +1,25 @@
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "serve.h"
+
+static char const * const grep_usage[] = {
+   N_("git serve []"),
+   NULL
+};
+
+int cmd_serve(int argc, const char **argv, const char *prefix)
+{
+
+   struct option options[] = {
+   OPT_END()
+   };
+
+   /* ignore all unknown cmdline switches for now */
+   argc = parse_options(argc, argv, prefix, options, grep_usage,
+PARSE_OPT_KEEP_DASHDASH |
+PARSE_OPT_KEEP_UNKNOWN);
+   serve();
+
+   return 0;
+}
diff --git a/git.c b/git.c
index e32e16f2d..527086eaf 100644
--- a/git.c
+++ b/git.c
@@ -457,6 +457,7 @@ static struct cmd_struct commands[] = {
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
{ "rm", cmd_rm, RUN_SETUP },
{ "send-pack", cmd_send_pack, RUN_SETUP },
+   { "serve", cmd_serve, RUN_SETUP },
{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
{ "show", cmd_show, RUN_SETUP },
{ "show-branch", cmd_show_branch, RUN_SETUP },
diff --git a/serve.c b/serve.c
new file mode 100644
index 0..476e73b54
--- /dev/null
+++ b/serve.c
@@ -0,0 +1,185 @@
+#include "cache.h"
+#include "repository.h"
+#include "config.h"
+#include "pkt-line.h"
+#include "version.h"
+#include "argv-array.h"
+#include "serve.h"
+
+static int agent_advertise(struct repository *r,
+  struct strbuf *value)
+{
+   strbuf_addstr(value, git_user_agent_sanitized());
+   return 1;
+}
+
+struct protocol_capability {
+   const char *name;
+   int advertised; /* capability was advertised */
+   /* int advertise(struct strbuf *value, struct repository *r) */
+   int (*advertise)(struct repository *r, struct strbuf *value);
+   /* int command(struct repository *r, struct argv_array *keys, struct 
argv_array *args)*/
+   int (*command)(struct repository *r,
+  struct argv_array *keys,
+  struct argv_array *args);
+};
+
+static struct protocol_capability capabilities[] = {
+   { "agent", 0, agent_advertise, NULL },
+};
+
+static void