Use an external program to implement fetching with curl
[gitweb.git] / transport.c
index 17891d5149aab99ce0ec5538a0e11b8e9c2398ec..9935c85cf337ef7e99bee38c8e49684df8dd6b3a 100644 (file)
@@ -1,9 +1,6 @@
 #include "cache.h"
 #include "transport.h"
 #include "run-command.h"
-#ifndef NO_CURL
-#include "http.h"
-#endif
 #include "pkt-line.h"
 #include "fetch-pack.h"
 #include "send-pack.h"
@@ -158,7 +155,7 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
 
        strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
        if (!mkdtemp(temp_dir.buf))
-               die ("Could not make temporary directory");
+               die_errno ("Could not make temporary directory");
        temp_dir_len = temp_dir.len;
 
        strbuf_addstr(&buf, rsync_url(transport->url));
@@ -321,7 +318,7 @@ static int rsync_transport_push(struct transport *transport,
 
        strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
        if (!mkdtemp(temp_dir.buf))
-               die ("Could not make temporary directory");
+               die_errno ("Could not make temporary directory");
        strbuf_addch(&temp_dir, '/');
 
        if (flags & TRANSPORT_PUSH_ALL) {
@@ -352,45 +349,6 @@ static int rsync_transport_push(struct transport *transport,
        return result;
 }
 
-/* Generic functions for using commit walkers */
-
-#ifndef NO_CURL /* http fetch is the only user */
-static int fetch_objs_via_walker(struct transport *transport,
-                                int nr_objs, const struct ref **to_fetch)
-{
-       char *dest = xstrdup(transport->url);
-       struct walker *walker = transport->data;
-       char **objs = xmalloc(nr_objs * sizeof(*objs));
-       int i;
-
-       walker->get_all = 1;
-       walker->get_tree = 1;
-       walker->get_history = 1;
-       walker->get_verbosely = transport->verbose >= 0;
-       walker->get_recover = 0;
-
-       for (i = 0; i < nr_objs; i++)
-               objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
-
-       if (walker_fetch(walker, nr_objs, objs, NULL, NULL))
-               die("Fetch failed.");
-
-       for (i = 0; i < nr_objs; i++)
-               free(objs[i]);
-       free(objs);
-       free(dest);
-       return 0;
-}
-#endif /* NO_CURL */
-
-static int disconnect_walker(struct transport *transport)
-{
-       struct walker *walker = transport->data;
-       if (walker)
-               walker_free(walker);
-       return 0;
-}
-
 #ifndef NO_CURL
 static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
 {
@@ -432,105 +390,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
        return !!err;
 }
 
-static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
-{
-       struct strbuf buffer = STRBUF_INIT;
-       char *data, *start, *mid;
-       char *ref_name;
-       char *refs_url;
-       int i = 0;
-
-       struct active_request_slot *slot;
-       struct slot_results results;
-
-       struct ref *refs = NULL;
-       struct ref *ref = NULL;
-       struct ref *last_ref = NULL;
-
-       struct walker *walker;
-
-       if (for_push)
-               return NULL;
-
-       if (!transport->data)
-               transport->data = get_http_walker(transport->url,
-                                               transport->remote);
-
-       walker = transport->data;
-
-       refs_url = xmalloc(strlen(transport->url) + 11);
-       sprintf(refs_url, "%s/info/refs", transport->url);
-
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, refs_url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       strbuf_release(&buffer);
-                       if (missing_target(&results))
-                               die("%s not found: did you run git update-server-info on the server?", refs_url);
-                       else
-                               die("%s download error - %s", refs_url, curl_errorstr);
-               }
-       } else {
-               strbuf_release(&buffer);
-               die("Unable to start HTTP request");
-       }
-
-       data = buffer.buf;
-       start = NULL;
-       mid = data;
-       while (i < buffer.len) {
-               if (!start)
-                       start = &data[i];
-               if (data[i] == '\t')
-                       mid = &data[i];
-               if (data[i] == '\n') {
-                       data[i] = 0;
-                       ref_name = mid + 1;
-                       ref = xmalloc(sizeof(struct ref) +
-                                     strlen(ref_name) + 1);
-                       memset(ref, 0, sizeof(struct ref));
-                       strcpy(ref->name, ref_name);
-                       get_sha1_hex(start, ref->old_sha1);
-                       if (!refs)
-                               refs = ref;
-                       if (last_ref)
-                               last_ref->next = ref;
-                       last_ref = ref;
-                       start = NULL;
-               }
-               i++;
-       }
-
-       strbuf_release(&buffer);
-
-       ref = alloc_ref("HEAD");
-       if (!walker->fetch_ref(walker, ref) &&
-           !resolve_remote_symref(ref, refs)) {
-               ref->next = refs;
-               refs = ref;
-       } else {
-               free(ref);
-       }
-
-       return refs;
-}
-
-static int fetch_objs_via_curl(struct transport *transport,
-                                int nr_objs, const struct ref **to_fetch)
-{
-       if (!transport->data)
-               transport->data = get_http_walker(transport->url,
-                                               transport->remote);
-       return fetch_objs_via_walker(transport, nr_objs, to_fetch);
-}
-
 #endif
 
 struct bundle_transport_data {
@@ -728,19 +587,30 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb
 
 #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
 
-static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
+static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
 {
-       fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
-       if (from)
-               fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
-       else
-               fputs(prettify_refname(to->name), stderr);
-       if (msg) {
-               fputs(" (", stderr);
-               fputs(msg, stderr);
-               fputc(')', stderr);
+       if (porcelain) {
+               if (from)
+                       fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
+               else
+                       fprintf(stdout, "%c\t:%s\t", flag, to->name);
+               if (msg)
+                       fprintf(stdout, "%s (%s)\n", summary, msg);
+               else
+                       fprintf(stdout, "%s\n", summary);
+       } else {
+               fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
+               if (from)
+                       fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
+               else
+                       fputs(prettify_refname(to->name), stderr);
+               if (msg) {
+                       fputs(" (", stderr);
+                       fputs(msg, stderr);
+                       fputc(')', stderr);
+               }
+               fputc('\n', stderr);
        }
-       fputc('\n', stderr);
 }
 
 static const char *status_abbrev(unsigned char sha1[20])
@@ -748,15 +618,15 @@ static const char *status_abbrev(unsigned char sha1[20])
        return find_unique_abbrev(sha1, DEFAULT_ABBREV);
 }
 
-static void print_ok_ref_status(struct ref *ref)
+static void print_ok_ref_status(struct ref *ref, int porcelain)
 {
        if (ref->deletion)
-               print_ref_status('-', "[deleted]", ref, NULL, NULL);
+               print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
        else if (is_null_sha1(ref->old_sha1))
                print_ref_status('*',
                        (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
-                         "[new branch]"),
-                       ref, ref->peer_ref, NULL);
+                       "[new branch]"),
+                       ref, ref->peer_ref, NULL, porcelain);
        else {
                char quickref[84];
                char type;
@@ -774,50 +644,51 @@ static void print_ok_ref_status(struct ref *ref)
                }
                strcat(quickref, status_abbrev(ref->new_sha1));
 
-               print_ref_status(type, quickref, ref, ref->peer_ref, msg);
+               print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
        }
 }
 
-static int print_one_push_status(struct ref *ref, const char *dest, int count)
+static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
 {
        if (!count)
                fprintf(stderr, "To %s\n", dest);
 
        switch(ref->status) {
        case REF_STATUS_NONE:
-               print_ref_status('X', "[no match]", ref, NULL, NULL);
+               print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
                break;
        case REF_STATUS_REJECT_NODELETE:
                print_ref_status('!', "[rejected]", ref, NULL,
-                               "remote does not support deleting refs");
+                                                "remote does not support deleting refs", porcelain);
                break;
        case REF_STATUS_UPTODATE:
                print_ref_status('=', "[up to date]", ref,
-                               ref->peer_ref, NULL);
+                                                ref->peer_ref, NULL, porcelain);
                break;
        case REF_STATUS_REJECT_NONFASTFORWARD:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
-                               "non-fast forward");
+                                                "non-fast forward", porcelain);
                break;
        case REF_STATUS_REMOTE_REJECT:
                print_ref_status('!', "[remote rejected]", ref,
-                               ref->deletion ? NULL : ref->peer_ref,
-                               ref->remote_status);
+                                                ref->deletion ? NULL : ref->peer_ref,
+                                                ref->remote_status, porcelain);
                break;
        case REF_STATUS_EXPECTING_REPORT:
                print_ref_status('!', "[remote failure]", ref,
-                               ref->deletion ? NULL : ref->peer_ref,
-                               "remote failed to report status");
+                                                ref->deletion ? NULL : ref->peer_ref,
+                                                "remote failed to report status", porcelain);
                break;
        case REF_STATUS_OK:
-               print_ok_ref_status(ref);
+               print_ok_ref_status(ref, porcelain);
                break;
        }
 
        return 1;
 }
 
-static void print_push_status(const char *dest, struct ref *refs, int verbose)
+static void print_push_status(const char *dest, struct ref *refs,
+                                                         int verbose, int porcelain)
 {
        struct ref *ref;
        int n = 0;
@@ -825,18 +696,18 @@ static void print_push_status(const char *dest, struct ref *refs, int verbose)
        if (verbose) {
                for (ref = refs; ref; ref = ref->next)
                        if (ref->status == REF_STATUS_UPTODATE)
-                               n += print_one_push_status(ref, dest, n);
+                               n += print_one_push_status(ref, dest, n, porcelain);
        }
 
        for (ref = refs; ref; ref = ref->next)
                if (ref->status == REF_STATUS_OK)
-                       n += print_one_push_status(ref, dest, n);
+                       n += print_one_push_status(ref, dest, n, porcelain);
 
        for (ref = refs; ref; ref = ref->next) {
                if (ref->status != REF_STATUS_NONE &&
                    ref->status != REF_STATUS_UPTODATE &&
                    ref->status != REF_STATUS_OK)
-                       n += print_one_push_status(ref, dest, n);
+                       n += print_one_push_status(ref, dest, n, porcelain);
        }
 }
 
@@ -947,14 +818,12 @@ struct transport *transport_get(struct remote *remote, const char *url)
        } else if (!prefixcmp(url, "http://")
                || !prefixcmp(url, "https://")
                || !prefixcmp(url, "ftp://")) {
+               transport_helper_init(ret);
 #ifdef NO_CURL
                error("git was compiled without libcurl support.");
 #else
-               ret->get_refs_list = get_refs_via_curl;
-               ret->fetch = fetch_objs_via_curl;
                ret->push = curl_transport_push;
 #endif
-               ret->disconnect = disconnect_walker;
 
        } else if (is_local(url) && is_file(url)) {
                struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
@@ -1003,10 +872,10 @@ int transport_push(struct transport *transport,
        if (transport->push_refs) {
                struct ref *remote_refs =
                        transport->get_refs_list(transport, 1);
-               struct ref **remote_tail;
                struct ref *local_refs = get_local_heads();
                int match_flags = MATCH_REFS_NONE;
                int verbose = flags & TRANSPORT_PUSH_VERBOSE;
+               int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
                int ret;
 
                if (flags & TRANSPORT_PUSH_ALL)
@@ -1014,17 +883,14 @@ int transport_push(struct transport *transport,
                if (flags & TRANSPORT_PUSH_MIRROR)
                        match_flags |= MATCH_REFS_MIRROR;
 
-               remote_tail = &remote_refs;
-               while (*remote_tail)
-                       remote_tail = &((*remote_tail)->next);
-               if (match_refs(local_refs, remote_refs, &remote_tail,
+               if (match_refs(local_refs, &remote_refs,
                               refspec_nr, refspec, match_flags)) {
                        return -1;
                }
 
                ret = transport->push_refs(transport, remote_refs, flags);
 
-               print_push_status(transport->url, remote_refs, verbose);
+               print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
 
                if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
                        struct ref *ref;