Merge branch 'dm/http-cleanup'

* dm/http-cleanup:
  t5541-http-push: add test for chunked
  http-push: refactor curl_easy_setup madness
  http-push: use const for strings in signatures
  http: make curl callbacks match contracts from curl header
This commit is contained in:
Junio C Hamano 2011-05-11 11:37:38 -07:00
Родитель ebfd72c856 0cc6330d0c
Коммит 1f0f5b54ba
6 изменённых файлов: 80 добавлений и 114 удалений

Просмотреть файл

@ -169,7 +169,7 @@ enum dav_header_flag {
DAV_HEADER_TIMEOUT = (1u << 2)
};
static char *xml_entities(char *s)
static char *xml_entities(const char *s)
{
struct strbuf buf = STRBUF_INIT;
while (*s) {
@ -197,6 +197,34 @@ static char *xml_entities(char *s)
return strbuf_detach(&buf, NULL);
}
static void curl_setup_http_get(CURL *curl, const char *url,
const char *custom_req)
{
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_null);
}
static void curl_setup_http(CURL *curl, const char *url,
const char *custom_req, struct buffer *buffer,
curl_write_callback write_fn)
{
curl_easy_setopt(curl, CURLOPT_PUT, 1);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &buffer);
#endif
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
}
static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
{
struct strbuf buf = STRBUF_INIT;
@ -272,11 +300,8 @@ static void start_mkcol(struct transfer_request *request)
slot = get_active_slot();
slot->callback_func = process_response;
slot->callback_data = request;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
curl_setup_http_get(slot->curl, request->url, DAV_MKCOL);
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
if (start_active_slot(slot)) {
request->slot = slot;
@ -395,19 +420,8 @@ static void start_put(struct transfer_request *request)
slot = get_active_slot();
slot->callback_func = process_response;
slot->callback_data = request;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &request->buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
curl_setup_http(slot->curl, request->url, DAV_PUT,
&request->buffer, fwrite_null);
if (start_active_slot(slot)) {
request->slot = slot;
@ -427,13 +441,10 @@ static void start_move(struct transfer_request *request)
slot = get_active_slot();
slot->callback_func = process_response;
slot->callback_data = request;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
curl_setup_http_get(slot->curl, request->url, DAV_MOVE);
dav_headers = curl_slist_append(dav_headers, request->dest);
dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
if (start_active_slot(slot)) {
request->slot = slot;
@ -458,10 +469,7 @@ static int refresh_lock(struct remote_lock *lock)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
curl_setup_http_get(slot->curl, lock->url, DAV_LOCK);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
if (start_active_slot(slot)) {
@ -797,7 +805,7 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
}
}
static void one_remote_ref(char *refname);
static void one_remote_ref(const char *refname);
static void
xml_start_tag(void *userData, const char *name, const char **atts)
@ -876,10 +884,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
ep[1] = '\0';
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_setup_http_get(slot->curl, url, DAV_MKCOL);
if (start_active_slot(slot)) {
run_active_slot(slot);
if (results.curl_result != CURLE_OK &&
@ -909,19 +914,9 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
curl_setup_http(slot->curl, url, DAV_LOCK, &out_buffer, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
lock = xcalloc(1, sizeof(*lock));
lock->timeout = -1;
@ -987,9 +982,7 @@ static int unlock_remote(struct remote_lock *lock)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
curl_setup_http_get(slot->curl, lock->url, DAV_UNLOCK);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
if (start_active_slot(slot)) {
@ -1167,19 +1160,10 @@ static void remote_ls(const char *path, int flags,
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
curl_setup_http(slot->curl, url, DAV_PROPFIND,
&out_buffer, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
if (start_active_slot(slot)) {
run_active_slot(slot);
@ -1250,19 +1234,10 @@ static int locking_available(void)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
curl_setup_http(slot->curl, repo->url, DAV_PROPFIND,
&out_buffer, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
if (start_active_slot(slot)) {
run_active_slot(slot);
@ -1436,19 +1411,9 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
curl_setup_http(slot->curl, lock->url, DAV_PUT,
&out_buffer, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
if (start_active_slot(slot)) {
run_active_slot(slot);
@ -1471,7 +1436,7 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
static struct ref *remote_refs;
static void one_remote_ref(char *refname)
static void one_remote_ref(const char *refname)
{
struct ref *ref;
struct object *obj;
@ -1572,19 +1537,9 @@ static void update_remote_info_refs(struct remote_lock *lock)
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.buf.len);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
#ifndef NO_CURL_IOCTL
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &buffer);
#endif
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
curl_setup_http(slot->curl, lock->url, DAV_PUT,
&buffer, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
if (start_active_slot(slot)) {
run_active_slot(slot);
@ -1660,7 +1615,7 @@ static int verify_merge_base(unsigned char *head_sha1, unsigned char *branch_sha
return (merge_bases && !merge_bases->next && merge_bases->item == branch);
}
static int delete_remote_branch(char *pattern, int force)
static int delete_remote_branch(const char *pattern, int force)
{
struct ref *refs = remote_refs;
struct ref *remote_ref = NULL;
@ -1742,10 +1697,7 @@ static int delete_remote_branch(char *pattern, int force)
sprintf(url, "%s%s", repo->url, remote_ref->name);
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_DELETE);
curl_setup_http_get(slot->curl, url, DAV_DELETE);
if (start_active_slot(slot)) {
run_active_slot(slot);
free(url);

Просмотреть файл

@ -185,7 +185,7 @@ static void process_alternates_response(void *callback_data)
struct active_request_slot *slot = alt_req->slot;
struct alt_base *tail = cdata->alt;
const char *base = alt_req->base;
static const char null_byte = '\0';
const char null_byte = '\0';
char *data;
int i = 0;
@ -218,7 +218,7 @@ static void process_alternates_response(void *callback_data)
}
}
fwrite_buffer(&null_byte, 1, 1, alt_req->buffer);
fwrite_buffer((char *)&null_byte, 1, 1, alt_req->buffer);
alt_req->buffer->len--;
data = alt_req->buffer->buf;

12
http.c
Просмотреть файл

@ -60,7 +60,7 @@ static struct curl_slist *no_pragma_header;
static struct active_request_slot *active_queue_head;
size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
struct buffer *buffer = buffer_;
@ -92,7 +92,7 @@ curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
}
#endif
size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
struct strbuf *buffer = buffer_;
@ -102,7 +102,7 @@ size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer
return size;
}
size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf)
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
{
data_received++;
return eltsize * nmemb;
@ -1167,7 +1167,7 @@ abort:
}
/* Helpers for fetching objects (loose) */
static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
void *data)
{
unsigned char expn[4096];
@ -1184,7 +1184,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
} while (posn < size);
freq->stream.avail_in = size;
freq->stream.next_in = ptr;
freq->stream.next_in = (void *)ptr;
do {
freq->stream.next_out = expn;
freq->stream.avail_out = sizeof(expn);
@ -1203,7 +1203,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
char *filename;
char prevfile[PATH_MAX];
int prevlocal;
unsigned char prev_buf[PREV_BUF_SIZE];
char prev_buf[PREV_BUF_SIZE];
ssize_t prev_read = 0;
long prev_posn = 0;
char range[RANGE_HEADER_SIZE];

6
http.h
Просмотреть файл

@ -66,9 +66,9 @@ struct buffer {
};
/* Curl request read/write callbacks */
extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
extern size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
extern size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
extern size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
extern size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
extern size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
#ifndef NO_CURL_IOCTL
extern curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
#endif

Просмотреть файл

@ -347,7 +347,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
}
#endif
static size_t rpc_in(const void *ptr, size_t eltsize,
static size_t rpc_in(char *ptr, size_t eltsize,
size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;

Просмотреть файл

@ -65,14 +65,16 @@ test_expect_success 'clone remote repository' '
git clone $HTTPD_URL/smart/test_repo.git test_repo_clone
'
test_expect_success 'push to remote repository' '
test_expect_success 'push to remote repository (standard)' '
cd "$ROOT_PATH"/test_repo_clone &&
: >path2 &&
git add path2 &&
test_tick &&
git commit -m path2 &&
HEAD=$(git rev-parse --verify HEAD) &&
git push &&
GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
! grep "Expect: 100-continue" err &&
grep "POST git-receive-pack ([0-9]* bytes)" err &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
test $HEAD = $(git rev-parse --verify HEAD))
'
@ -140,5 +142,17 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he
output
'
test_expect_success 'push (chunked)' '
git checkout master &&
test_commit commit path3 &&
HEAD=$(git rev-parse --verify HEAD) &&
git config http.postbuffer 4 &&
test_when_finished "git config --unset http.postbuffer" &&
git push -v -v origin $BRANCH 2>err &&
grep "POST git-receive-pack (chunked)" err &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
test $HEAD = $(git rev-parse --verify HEAD))
'
stop_httpd
test_done