revision --simplify-merges: use decoration instead of commit->util field
[gitweb.git] / connect.c
index 44e423dafd5c5e6566124fd1bb05f3d419b19a40..574f42fa47ffa69328217eb25afee6f85db9595e 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -36,6 +36,11 @@ static int check_ref(const char *name, int len, unsigned int flags)
        return !(flags & ~REF_NORMAL);
 }
 
+int check_ref_type(const struct ref *ref, int flags)
+{
+       return check_ref(ref->name, strlen(ref->name), flags);
+}
+
 /*
  * Read all the refs from the other end
  */
@@ -63,8 +68,7 @@ struct ref **get_remote_heads(int in, struct ref **list,
 
                name_len = strlen(name);
                if (len != name_len + 41) {
-                       if (server_capabilities)
-                               free(server_capabilities);
+                       free(server_capabilities);
                        server_capabilities = xstrdup(name + name_len + 1);
                }
 
@@ -356,7 +360,8 @@ static char *git_proxy_command;
 static const char *rhost_name;
 static int rhost_len;
 
-static int git_proxy_command_options(const char *var, const char *value)
+static int git_proxy_command_options(const char *var, const char *value,
+               void *cb)
 {
        if (!strcmp(var, "core.gitproxy")) {
                const char *for_pos;
@@ -365,6 +370,8 @@ static int git_proxy_command_options(const char *var, const char *value)
 
                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
@@ -398,7 +405,7 @@ static int git_proxy_command_options(const char *var, const char *value)
                return 0;
        }
 
-       return git_default_config(var, value);
+       return git_default_config(var, value, cb);
 }
 
 static int git_use_proxy(const char *host)
@@ -406,7 +413,7 @@ static int git_use_proxy(const char *host)
        rhost_name = host;
        rhost_len = strlen(host);
        git_proxy_command = getenv("GIT_PROXY_COMMAND");
-       git_config(git_proxy_command_options);
+       git_config(git_proxy_command_options, NULL);
        rhost_name = NULL;
        return (git_proxy_command && *git_proxy_command);
 }
@@ -467,18 +474,23 @@ 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], char *url,
+struct child_process *git_connect(int fd[2], const char *url_orig,
                                  const char *prog, int flags)
 {
+       char *url = xstrdup(url_orig);
        char *host, *path = url;
        char *end;
        int c;
@@ -517,7 +529,7 @@ struct child_process *git_connect(int fd[2], char *url,
                end = host;
 
        path = strchr(end, c);
-       if (path) {
+       if (path && !has_dos_drive_prefix(end)) {
                if (c == ':') {
                        protocol = PROTO_SSH;
                        *path++ = '\0';
@@ -568,9 +580,10 @@ struct child_process *git_connect(int fd[2], char *url,
                             prog, path, 0,
                             target_host, 0);
                free(target_host);
+               free(url);
                if (free_path)
                        free(path);
-               return NULL;
+               return &no_fork;
        }
 
        conn = xcalloc(1, sizeof(*conn));
@@ -619,6 +632,7 @@ struct child_process *git_connect(int fd[2], char *url,
        fd[0] = conn->out; /* read from child's stdout */
        fd[1] = conn->in;  /* write to child's stdin */
        strbuf_release(&cmd);
+       free(url);
        if (free_path)
                free(path);
        return conn;
@@ -627,7 +641,7 @@ struct child_process *git_connect(int fd[2], char *url,
 int finish_connect(struct child_process *conn)
 {
        int code;
-       if (!conn)
+       if (!conn || conn == &no_fork)
                return 0;
 
        code = finish_command(conn);