Merge branch 'db/no-separate-ls-remote-connection' (early part)
authorJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2008 00:47:07 +0000 (16:47 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2008 00:47:07 +0000 (16:47 -0800)
* 'db/no-separate-ls-remote-connection' (early part):
Fix "git clone" for git:// protocol
Reduce the number of connects when fetching

1  2 
connect.c
transport.c
diff --combined connect.c
index 71597d4920ff11ed474be1a8bd39b4791611e422,700cebad900760223f0d0a7442c16f6a0a6869e0..5ac357278464324d82ac6912c1b7ad84d42d0743
+++ b/connect.c
@@@ -370,8 -370,6 +370,8 @@@ static int git_proxy_command_options(co
  
                if (git_proxy_command)
                        return 0;
 +              if (!value)
 +                      return config_error_nonbool(var);
                /* [core]
                 * ;# matches www.kernel.org as well
                 * gitproxy = netcatter-1 for kernel.org
@@@ -474,14 -472,18 +474,18 @@@ char *get_port(char *host
        return NULL;
  }
  
+ static struct child_process no_fork;
  /*
-  * This returns NULL if the transport protocol does not need fork(2), or a
-  * struct child_process object if it does.  Once done, finish the connection
-  * with finish_connect() with the value returned from this function
-  * (it is safe to call finish_connect() with NULL to support the former
-  * case).
+  * This returns a dummy child_process if the transport protocol does not
+  * need fork(2), or a struct child_process object if it does.  Once done,
+  * finish the connection with finish_connect() with the value returned from
+  * this function (it is safe to call finish_connect() with NULL to support
+  * the former case).
   *
-  * If it returns, the connect is successful; it just dies on errors.
+  * If it returns, the connect is successful; it just dies on errors (this
+  * will hopefully be changed in a libification effort, to return NULL when
+  * the connection failed).
   */
  struct child_process *git_connect(int fd[2], const char *url_orig,
                                  const char *prog, int flags)
                free(url);
                if (free_path)
                        free(path);
-               return NULL;
+               return &no_fork;
        }
  
        conn = xcalloc(1, sizeof(*conn));
  int finish_connect(struct child_process *conn)
  {
        int code;
-       if (!conn)
+       if (!conn || conn == &no_fork)
                return 0;
  
        code = finish_command(conn);
diff --combined transport.c
index 497f85372173f6f270a4c0ee9474f165bb884413,199e9e6a0dbde490b60fd2befd29634905e962dd..397983d1155bed967bd48ad47dbbb81cb2e45168
@@@ -441,12 -441,11 +441,12 @@@ static struct ref *get_refs_via_curl(st
        struct ref *ref = NULL;
        struct ref *last_ref = NULL;
  
 +      if (!transport->data)
 +              transport->data = get_http_walker(transport->url);
 +
        refs_url = xmalloc(strlen(transport->url) + 11);
        sprintf(refs_url, "%s/info/refs", transport->url);
  
 -      http_init();
 -
        slot = get_active_slot();
        slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
                return NULL;
        }
  
 -      http_cleanup();
 -
        data = buffer.buf;
        start = NULL;
        mid = data;
@@@ -562,6 -563,8 +562,8 @@@ struct git_transport_data 
        unsigned thin : 1;
        unsigned keep : 1;
        int depth;
+       struct child_process *conn;
+       int fd[2];
        const char *uploadpack;
        const char *receivepack;
  };
@@@ -592,20 -595,20 +594,20 @@@ static int set_git_option(struct transp
        return 1;
  }
  
+ static int connect_setup(struct transport *transport)
+ {
+       struct git_transport_data *data = transport->data;
+       data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
+       return 0;
+ }
  static struct ref *get_refs_via_connect(struct transport *transport)
  {
        struct git_transport_data *data = transport->data;
        struct ref *refs;
-       int fd[2];
-       char *dest = xstrdup(transport->url);
-       struct child_process *conn = git_connect(fd, dest, data->uploadpack, 0);
  
-       get_remote_heads(fd[0], &refs, 0, NULL, 0);
-       packet_flush(fd[1]);
-       finish_connect(conn);
-       free(dest);
+       connect_setup(transport);
+       get_remote_heads(data->fd[0], &refs, 0, NULL, 0);
  
        return refs;
  }
@@@ -616,7 -619,7 +618,7 @@@ static int fetch_refs_via_pack(struct t
        struct git_transport_data *data = transport->data;
        char **heads = xmalloc(nr_heads * sizeof(*heads));
        char **origh = xmalloc(nr_heads * sizeof(*origh));
-       struct ref *refs;
+       const struct ref *refs;
        char *dest = xstrdup(transport->url);
        struct fetch_pack_args args;
        int i;
  
        for (i = 0; i < nr_heads; i++)
                origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
-       refs = fetch_pack(&args, dest, nr_heads, heads, &transport->pack_lockfile);
+       refs = transport_get_remote_refs(transport);
+       if (!data->conn) {
+               struct ref *refs_tmp;
+               connect_setup(transport);
+               get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
+               free_refs(refs_tmp);
+       }
+       refs = fetch_pack(&args, data->fd, data->conn, transport->remote_refs,
+                         dest, nr_heads, heads, &transport->pack_lockfile);
+       close(data->fd[0]);
+       close(data->fd[1]);
+       if (finish_connect(data->conn))
+               refs = NULL;
+       data->conn = NULL;
  
        for (i = 0; i < nr_heads; i++)
                free(origh[i]);
        free(origh);
        free(heads);
-       free_refs(refs);
        free(dest);
        return (refs ? 0 : -1);
  }
@@@ -660,7 -677,15 +676,15 @@@ static int git_transport_push(struct tr
  
  static int disconnect_git(struct transport *transport)
  {
-       free(transport->data);
+       struct git_transport_data *data = transport->data;
+       if (data->conn) {
+               packet_flush(data->fd[1]);
+               close(data->fd[0]);
+               close(data->fd[1]);
+               finish_connect(data->conn);
+       }
+       free(data);
        return 0;
  }
  
@@@ -720,6 -745,7 +744,7 @@@ struct transport *transport_get(struct 
                ret->disconnect = disconnect_git;
  
                data->thin = 1;
+               data->conn = NULL;
                data->uploadpack = "git-upload-pack";
                if (remote && remote->uploadpack)
                        data->uploadpack = remote->uploadpack;