return 0;
}
-static inline int needs_quote(int ch)
-{
- if (((ch >= 'A') && (ch <= 'Z'))
- || ((ch >= 'a') && (ch <= 'z'))
- || ((ch >= '0') && (ch <= '9'))
- || (ch == '/')
- || (ch == '-')
- || (ch == '.'))
- return 0;
- return 1;
-}
-
-static inline int hex(int v)
-{
- if (v < 10) return '0' + v;
- else return 'A' + v - 10;
-}
-
-static char *quote_ref_url(const char *base, const char *ref)
-{
- const char *cp;
- char *dp, *qref;
- int len, baselen, ch;
-
- baselen = strlen(base);
- len = baselen + 1;
- for (cp = ref; (ch = *cp) != 0; cp++, len++)
- if (needs_quote(ch))
- len += 2; /* extra two hex plus replacement % */
- qref = xmalloc(len);
- memcpy(qref, base, baselen);
- for (cp = ref, dp = qref + baselen; (ch = *cp) != 0; cp++) {
- if (needs_quote(ch)) {
- *dp++ = '%';
- *dp++ = hex((ch >> 4) & 0xF);
- *dp++ = hex(ch & 0xF);
- }
- else
- *dp++ = ch;
- }
- *dp = 0;
-
- return qref;
-}
-
-int fetch_ref(char *ref, unsigned char *sha1)
-{
- char *url;
- struct strbuf buffer = STRBUF_INIT;
- char *base = remote->url;
- struct active_request_slot *slot;
- struct slot_results results;
-
- url = quote_ref_url(base, ref);
- 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_HTTPHEADER, NULL);
- curl_easy_setopt(slot->curl, CURLOPT_URL, url);
- if (start_active_slot(slot)) {
- run_active_slot(slot);
- free(url);
- if (results.curl_result != CURLE_OK)
- return error("Couldn't get %s for %s\n%s",
- url, ref, curl_errorstr);
- } else {
- free(url);
- return error("Unable to start request");
- }
-
- strbuf_rtrim(&buffer);
- if (buffer.len != 40)
- return 1;
- return get_sha1_hex(buffer.buf, sha1);
-}
-
static void one_remote_object(const char *hex)
{
unsigned char sha1[20];
lock_flags = 0;
}
XML_ParserFree(parser);
+ if (!lock_flags)
+ error("Error: no DAV locking support on %s",
+ remote->url);
+
+ } else {
+ error("Cannot access URL %s, return code %d",
+ remote->url, results.curl_result);
+ lock_flags = 0;
}
} else {
- fprintf(stderr, "Unable to start PROPFIND request\n");
+ error("Unable to start PROPFIND request on %s", remote->url);
}
strbuf_release(&out_buffer.buf);
struct object *obj;
int len = strlen(refname) + 1;
- if (fetch_ref(refname, remote_sha1) != 0) {
+ if (http_fetch_ref(remote->url, refname + 5 /* "refs/" */,
+ remote_sha1) != 0) {
fprintf(stderr,
"Unable to fetch ref %s from %s\n",
refname, remote->url);
int len;
char *ref_info;
- if (fetch_ref(ls->dentry_name, remote_sha1) != 0) {
+ if (http_fetch_ref(remote->url, ls->dentry_name + 5 /* "refs/" */,
+ remote_sha1) != 0) {
fprintf(stderr,
"Unable to fetch ref %s from %s\n",
ls->dentry_name, remote->url);
char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
struct active_request_slot *slot;
struct slot_results results;
+ int ret = -1;
sprintf(url, "%s%s", remote->url, path);
if (start_active_slot(slot)) {
run_active_slot(slot);
- free(url);
if (results.http_code == 404)
- return 0;
+ ret = 0;
else if (results.curl_result == CURLE_OK)
- return 1;
+ ret = 1;
else
fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code);
} else {
- free(url);
fprintf(stderr, "Unable to start HEAD request\n");
}
- return -1;
+ free(url);
+ return ret;
}
static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
int i;
int new_refs;
struct ref *ref;
+ char *rewritten_url = NULL;
setup_git_directory();
break;
}
+#ifndef USE_CURL_MULTI
+ die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
+#endif
+
if (!remote->url)
usage(http_push_usage);
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
+ if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
+ rewritten_url = malloc(strlen(remote->url)+2);
+ strcpy(rewritten_url, remote->url);
+ strcat(rewritten_url, "/");
+ remote->url = rewritten_url;
+ ++remote->path_len;
+ }
+
/* Verify DAV compliance/lock support */
if (!locking_available()) {
- fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
rc = 1;
goto cleanup;
}
info_ref_lock = lock_remote("info/refs", LOCK_TIME);
if (info_ref_lock)
remote->can_update_info_refs = 1;
+ else {
+ fprintf(stderr, "Error: cannot lock existing info/refs\n");
+ rc = 1;
+ goto cleanup;
+ }
}
if (remote->has_info_packs)
fetch_indices();
if (!remote_tail)
remote_tail = &remote_refs;
if (match_refs(local_refs, remote_refs, &remote_tail,
- nr_refspec, (const char **) refspec, push_all))
- return -1;
+ nr_refspec, (const char **) refspec, push_all)) {
+ rc = -1;
+ goto cleanup;
+ }
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
- return 0;
+ rc = 0;
+ goto cleanup;
}
new_refs = 0;
/* Generate a list of objects that need to be pushed */
pushing = 0;
- prepare_revision_walk(&revs);
+ if (prepare_revision_walk(&revs))
+ die("revision walk setup failed");
mark_edges_uninteresting(revs.commits);
objects_to_send = get_delta(&revs, ref_lock);
finish_all_active_slots();
fprintf(stderr, "Unable to update server info\n");
}
}
- if (info_ref_lock)
- unlock_remote(info_ref_lock);
cleanup:
+ if (rewritten_url)
+ free(rewritten_url);
+ if (info_ref_lock)
+ unlock_remote(info_ref_lock);
free(remote);
curl_slist_free_all(no_pragma_header);