ewah: support platforms that require aligned reads
[gitweb.git] / remote-curl.c
index a36c166734f134b702bdcbed76cddbdee9ccb074..b5ebe0180069c1c1f96b769a37c5f3eb9459dfe9 100644 (file)
@@ -6,7 +6,9 @@
 #include "exec_cmd.h"
 #include "run-command.h"
 #include "pkt-line.h"
+#include "string-list.h"
 #include "sideband.h"
+#include "argv-array.h"
 
 static struct remote *remote;
 static const char *url; /* always ends with a trailing slash */
@@ -15,11 +17,13 @@ struct options {
        int verbosity;
        unsigned long depth;
        unsigned progress : 1,
+               check_self_contained_and_connected : 1,
                followtags : 1,
                dry_run : 1,
                thin : 1;
 };
 static struct options options;
+static struct string_list cas_options = STRING_LIST_INIT_DUP;
 
 static int set_option(const char *name, const char *value)
 {
@@ -66,6 +70,22 @@ static int set_option(const char *name, const char *value)
                        return -1;
                return 0;
        }
+       else if (!strcmp(name, "check-connectivity")) {
+               if (!strcmp(value, "true"))
+                       options.check_self_contained_and_connected = 1;
+               else if (!strcmp(value, "false"))
+                       options.check_self_contained_and_connected = 0;
+               else
+                       return -1;
+               return 0;
+       }
+       else if (!strcmp(name, "cas")) {
+               struct strbuf val = STRBUF_INIT;
+               strbuf_addf(&val, "--" CAS_OPT_NAME "=%s", value);
+               string_list_append(&cas_options, val.buf);
+               strbuf_release(&val);
+               return 0;
+       }
        else {
                return 1 /* unsupported */;
        }
@@ -76,6 +96,7 @@ struct discovery {
        char *buf_alloc;
        char *buf;
        size_t len;
+       struct ref *refs;
        unsigned proto_git : 1;
 };
 static struct discovery *last_discovery;
@@ -145,11 +166,39 @@ static void free_discovery(struct discovery *d)
                if (d == last_discovery)
                        last_discovery = NULL;
                free(d->buf_alloc);
+               free_refs(d->refs);
                free(d);
        }
 }
 
-static struct discovery* discover_refs(const char *service)
+static int show_http_message(struct strbuf *type, struct strbuf *msg)
+{
+       const char *p, *eol;
+
+       /*
+        * We only show text/plain parts, as other types are likely
+        * to be ugly to look at on the user's terminal.
+        *
+        * TODO should handle "; charset=XXX", and re-encode into
+        * logoutputencoding
+        */
+       if (strcasecmp(type->buf, "text/plain"))
+               return -1;
+
+       strbuf_trim(msg);
+       if (!msg->len)
+               return -1;
+
+       p = msg->buf;
+       do {
+               eol = strchrnul(p, '\n');
+               fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p);
+               p = eol + 1;
+       } while(*eol);
+       return 0;
+}
+
+static struct discovery* discover_refs(const char *service, int for_push)
 {
        struct strbuf exp = STRBUF_INIT;
        struct strbuf type = STRBUF_INIT;
@@ -174,18 +223,20 @@ static struct discovery* discover_refs(const char *service)
        }
        refs_url = strbuf_detach(&buffer, NULL);
 
-       http_ret = http_get_strbuf(refs_url, &type, &buffer, HTTP_NO_CACHE);
+       http_ret = http_get_strbuf(refs_url, &type, &buffer,
+                                  HTTP_NO_CACHE | HTTP_KEEP_ERROR);
        switch (http_ret) {
        case HTTP_OK:
                break;
        case HTTP_MISSING_TARGET:
-               die("%s not found: did you run git update-server-info on the"
-                   " server?", refs_url);
+               show_http_message(&type, &buffer);
+               die("repository '%s' not found", url);
        case HTTP_NOAUTH:
-               die("Authentication failed");
+               show_http_message(&type, &buffer);
+               die("Authentication failed for '%s'", url);
        default:
-               http_error(refs_url, http_ret);
-               die("HTTP request failed");
+               show_http_message(&type, &buffer);
+               die("unable to access '%s': %s", url, curl_errorstr);
        }
 
        last= xcalloc(1, sizeof(*last_discovery));
@@ -221,6 +272,11 @@ static struct discovery* discover_refs(const char *service)
                last->proto_git = 1;
        }
 
+       if (last->proto_git)
+               last->refs = parse_git_refs(last, for_push);
+       else
+               last->refs = parse_info_refs(last);
+
        free(refs_url);
        strbuf_release(&exp);
        strbuf_release(&type);
@@ -234,13 +290,11 @@ static struct ref *get_refs(int for_push)
        struct discovery *heads;
 
        if (for_push)
-               heads = discover_refs("git-receive-pack");
+               heads = discover_refs("git-receive-pack", for_push);
        else
-               heads = discover_refs("git-upload-pack");
+               heads = discover_refs("git-upload-pack", for_push);
 
-       if (heads->proto_git)
-               return parse_git_refs(heads, for_push);
-       return parse_info_refs(heads);
+       return heads->refs;
 }
 
 static void output_refs(struct ref *refs)
@@ -254,7 +308,6 @@ static void output_refs(struct ref *refs)
        }
        printf("\n");
        fflush(stdout);
-       free_refs(refs);
 }
 
 struct rpc_state {
@@ -620,7 +673,7 @@ static int fetch_git(struct discovery *heads,
        struct strbuf preamble = STRBUF_INIT;
        char *depth_arg = NULL;
        int argc = 0, i, err;
-       const char *argv[15];
+       const char *argv[16];
 
        argv[argc++] = "fetch-pack";
        argv[argc++] = "--stateless-rpc";
@@ -634,6 +687,8 @@ static int fetch_git(struct discovery *heads,
                argv[argc++] = "-v";
                argv[argc++] = "-v";
        }
+       if (options.check_self_contained_and_connected)
+               argv[argc++] = "--check-self-contained-and-connected";
        if (!options.progress)
                argv[argc++] = "--no-progress";
        if (options.depth) {
@@ -670,7 +725,7 @@ static int fetch_git(struct discovery *heads,
 
 static int fetch(int nr_heads, struct ref **to_fetch)
 {
-       struct discovery *d = discover_refs("git-upload-pack");
+       struct discovery *d = discover_refs("git-upload-pack", 0);
        if (d->proto_git)
                return fetch_git(d, nr_heads, to_fetch);
        else
@@ -754,42 +809,44 @@ static int push_dav(int nr_spec, char **specs)
 static int push_git(struct discovery *heads, int nr_spec, char **specs)
 {
        struct rpc_state rpc;
-       const char **argv;
-       int argc = 0, i, err;
+       int i, err;
+       struct argv_array args;
+       struct string_list_item *cas_option;
+
+       argv_array_init(&args);
+       argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
+                        NULL);
 
-       argv = xmalloc((10 + nr_spec) * sizeof(char*));
-       argv[argc++] = "send-pack";
-       argv[argc++] = "--stateless-rpc";
-       argv[argc++] = "--helper-status";
        if (options.thin)
-               argv[argc++] = "--thin";
+               argv_array_push(&args, "--thin");
        if (options.dry_run)
-               argv[argc++] = "--dry-run";
+               argv_array_push(&args, "--dry-run");
        if (options.verbosity == 0)
-               argv[argc++] = "--quiet";
+               argv_array_push(&args, "--quiet");
        else if (options.verbosity > 1)
-               argv[argc++] = "--verbose";
-       argv[argc++] = options.progress ? "--progress" : "--no-progress";
-       argv[argc++] = url;
+               argv_array_push(&args, "--verbose");
+       argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
+       for_each_string_list_item(cas_option, &cas_options)
+               argv_array_push(&args, cas_option->string);
+       argv_array_push(&args, url);
        for (i = 0; i < nr_spec; i++)
-               argv[argc++] = specs[i];
-       argv[argc++] = NULL;
+               argv_array_push(&args, specs[i]);
 
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-receive-pack",
-       rpc.argv = argv;
+       rpc.argv = args.argv;
 
        err = rpc_service(&rpc, heads);
        if (rpc.result.len)
                write_or_die(1, rpc.result.buf, rpc.result.len);
        strbuf_release(&rpc.result);
-       free(argv);
+       argv_array_clear(&args);
        return err;
 }
 
 static int push(int nr_spec, char **specs)
 {
-       struct discovery *heads = discover_refs("git-receive-pack");
+       struct discovery *heads = discover_refs("git-receive-pack", 1);
        int ret;
 
        if (heads->proto_git)
@@ -906,6 +963,7 @@ int main(int argc, const char **argv)
                        printf("fetch\n");
                        printf("option\n");
                        printf("push\n");
+                       printf("check-connectivity\n");
                        printf("\n");
                        fflush(stdout);
                } else {