Support remote archive from all smart transports
authorIlari Liusvaara <ilari.liusvaara@elisanet.fi>
Wed, 9 Dec 2009 15:26:33 +0000 (17:26 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Dec 2009 08:24:15 +0000 (00:24 -0800)
Previously, remote archive required internal (non remote-helper)
smart transport. Extend the remote archive to also support smart
transports implemented by remote helpers.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-archive.c
transport-helper.c
transport.c
transport.h

index 12351e9dd5c481fddc8db07c00a211b4620250bd..d34b3fd028262fdd4215380b206abbf58bea07a4 100644 (file)
@@ -5,6 +5,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
+#include "transport.h"
 #include "parse-options.h"
 #include "pkt-line.h"
 #include "sideband.h"
@@ -25,12 +26,16 @@ static void create_output_file(const char *output_file)
 static int run_remote_archiver(int argc, const char **argv,
                               const char *remote, const char *exec)
 {
-       char *url, buf[LARGE_PACKET_MAX];
+       char buf[LARGE_PACKET_MAX];
        int fd[2], i, len, rv;
-       struct child_process *conn;
+       struct transport *transport;
+       struct remote *_remote;
 
-       url = xstrdup(remote);
-       conn = git_connect(fd, url, exec, 0);
+       _remote = remote_get(remote);
+       if (!_remote->url[0])
+               die("git archive: Remote with no URL");
+       transport = transport_get(_remote, _remote->url[0]);
+       transport_connect(transport, "git-upload-archive", exec, fd);
 
        for (i = 1; i < argc; i++)
                packet_write(fd[1], "argument %s\n", argv[i]);
@@ -53,9 +58,7 @@ static int run_remote_archiver(int argc, const char **argv,
 
        /* Now, start reading from fd[0] and spit it out to stdout */
        rv = recv_sideband("archive", fd[0], 1);
-       close(fd[0]);
-       close(fd[1]);
-       rv |= finish_connect(conn);
+       rv |= transport_disconnect(transport);
 
        return !!rv;
 }
index 50b3bac0c45252855505f4ce019a8cec53164fad..6ece0d9875652e5d648be7e18ddf2084c564fc12 100644 (file)
@@ -467,6 +467,24 @@ static int process_connect(struct transport *transport,
        return process_connect_service(transport, name, exec);
 }
 
+static int connect_helper(struct transport *transport, const char *name,
+                  const char *exec, int fd[2])
+{
+       struct helper_data *data = transport->data;
+
+       /* Get_helper so connect is inited. */
+       get_helper(transport);
+       if (!data->connect)
+               die("Operation not supported by protocol.");
+
+       if (!process_connect_service(transport, name, exec))
+               die("Can't connect to subservice %s.", name);
+
+       fd[0] = data->helper->out;
+       fd[1] = data->helper->in;
+       return 0;
+}
+
 static int fetch(struct transport *transport,
                 int nr_heads, struct ref **to_fetch)
 {
@@ -711,6 +729,7 @@ int transport_helper_init(struct transport *transport, const char *name)
        transport->fetch = fetch;
        transport->push_refs = push_refs;
        transport->disconnect = release_helper;
+       transport->connect = connect_helper;
        transport->smart_options = &(data->transport_options);
        return 0;
 }
index ad25b98ae1d094167dfe0c9152b55e953409aa21..a7d67eba83b36fb4f3fec7667c3125fd764ccf74 100644 (file)
@@ -756,6 +756,17 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
        return ret;
 }
 
+static int connect_git(struct transport *transport, const char *name,
+                      const char *executable, int fd[2])
+{
+       struct git_transport_data *data = transport->data;
+       data->conn = git_connect(data->fd, transport->url,
+                                executable, 0);
+       fd[0] = data->fd[0];
+       fd[1] = data->fd[1];
+       return 0;
+}
+
 static int disconnect_git(struct transport *transport)
 {
        struct git_transport_data *data = transport->data;
@@ -901,6 +912,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
                ret->get_refs_list = get_refs_via_connect;
                ret->fetch = fetch_refs_via_pack;
                ret->push_refs = git_transport_push;
+               ret->connect = connect_git;
                ret->disconnect = disconnect_git;
                ret->smart_options = &(data->options);
 
@@ -1061,6 +1073,15 @@ void transport_unlock_pack(struct transport *transport)
        }
 }
 
+int transport_connect(struct transport *transport, const char *name,
+                     const char *exec, int fd[2])
+{
+       if (transport->connect)
+               return transport->connect(transport, name, exec, fd);
+       else
+               die("Operation not supported by protocol");
+}
+
 int transport_disconnect(struct transport *transport)
 {
        int ret = 0;
index 781db2ec82cce20e75a795e1ed3e31a63a6ff58e..97ba2519dd6db2a4341def590e06cbc81b33fed2 100644 (file)
@@ -64,6 +64,8 @@ struct transport {
         **/
        int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
        int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
+       int (*connect)(struct transport *connection, const char *name,
+                      const char *executable, int fd[2]);
 
        /** get_refs_list(), fetch(), and push_refs() can keep
         * resources (such as a connection) reserved for futher
@@ -133,6 +135,9 @@ char *transport_anonymize_url(const char *url);
 void transport_take_over(struct transport *transport,
                         struct child_process *child);
 
+int transport_connect(struct transport *transport, const char *name,
+                     const char *exec, int fd[2]);
+
 /* Transport methods defined outside transport.c */
 int transport_helper_init(struct transport *transport, const char *name);