Skip to content

Commit

Permalink
Merge branch 'rc/http-push'
Browse files Browse the repository at this point in the history
* rc/http-push: (22 commits)
  http*: add helper methods for fetching objects (loose)
  http*: add helper methods for fetching packs
  http: use new http API in fetch_index()
  http*: add http_get_info_packs
  http-push.c::fetch_symref(): use the new http API
  http-push.c::remote_exists(): use the new http API
  http.c::http_fetch_ref(): use the new http API
  transport.c::get_refs_via_curl(): use the new http API
  http.c: new functions for the http API
  http: create function end_url_with_slash
  http*: move common variables and macros to http.[ch]
  transport.c::get_refs_via_curl(): do not leak refs_url
  Don't expect verify_pack() callers to set pack_size
  http-push: do not SEGV after fetching a bad pack idx file
  http*: copy string returned by sha1_to_hex
  http-walker: verify remote packs
  http-push, http-walker: style fixes
  t5550-http-fetch: test fetching of packed objects
  http-push: fix missing "#ifdef USE_CURL_MULTI" around "is_running_queue"
  http-push: send out fetch requests on queue
  ...
  • Loading branch information
Junio C Hamano committed Jun 13, 2009
2 parents cec3f98 + 5424bc5 commit e248619
Show file tree
Hide file tree
Showing 8 changed files with 904 additions and 993 deletions.
585 changes: 93 additions & 492 deletions http-push.c

Large diffs are not rendered by default.

539 changes: 87 additions & 452 deletions http-walker.c

Large diffs are not rendered by default.

601 changes: 577 additions & 24 deletions http.c

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions http.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ extern void http_cleanup(void);

extern int data_received;
extern int active_requests;
extern int http_is_verbose;

extern char curl_errorstr[CURL_ERROR_SIZE];

Expand All @@ -109,6 +110,90 @@ static inline int missing__target(int code, int result)

#define missing_target(a) missing__target((a)->http_code, (a)->curl_result)

/* Helpers for modifying and creating URLs */
extern void append_remote_object_url(struct strbuf *buf, const char *url,
const char *hex,
int only_two_digit_prefix);
extern char *get_remote_object_url(const char *url, const char *hex,
int only_two_digit_prefix);

/* Options for http_request_*() */
#define HTTP_NO_CACHE 1

/* Return values for http_request_*() */
#define HTTP_OK 0
#define HTTP_MISSING_TARGET 1
#define HTTP_ERROR 2
#define HTTP_START_FAILED 3

/*
* Requests an url and stores the result in a strbuf.
*
* If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
*/
int http_get_strbuf(const char *url, struct strbuf *result, int options);

/*
* Downloads an url and stores the result in the given file.
*
* If a previous interrupted download is detected (i.e. a previous temporary
* file is still around) the download is resumed.
*/
int http_get_file(const char *url, const char *filename, int options);

/*
* Prints an error message using error() containing url and curl_errorstr,
* and returns ret.
*/
int http_error(const char *url, int ret);

extern int http_fetch_ref(const char *base, struct ref *ref);

/* Helpers for fetching packs */
extern int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);

struct http_pack_request
{
char *url;
struct packed_git *target;
struct packed_git **lst;
FILE *packfile;
char filename[PATH_MAX];
char tmpfile[PATH_MAX];
struct curl_slist *range_header;
struct active_request_slot *slot;
};

extern struct http_pack_request *new_http_pack_request(
struct packed_git *target, const char *base_url);
extern int finish_http_pack_request(struct http_pack_request *preq);
extern void release_http_pack_request(struct http_pack_request *preq);

/* Helpers for fetching object */
struct http_object_request
{
char *url;
char filename[PATH_MAX];
char tmpfile[PATH_MAX];
int localfile;
CURLcode curl_result;
char errorstr[CURL_ERROR_SIZE];
long http_code;
unsigned char sha1[20];
unsigned char real_sha1[20];
git_SHA_CTX c;
z_stream stream;
int zret;
int rename;
struct active_request_slot *slot;
};

extern struct http_object_request *new_http_object_request(
const char *base_url, unsigned char *sha1);
extern void process_http_object_request(struct http_object_request *freq);
extern int finish_http_object_request(struct http_object_request *freq);
extern void abort_http_object_request(struct http_object_request *freq);
extern void release_http_object_request(struct http_object_request *freq);

#endif /* HTTP_H */
8 changes: 5 additions & 3 deletions pack-check.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static int verify_packfile(struct packed_git *p,
const unsigned char *index_base = p->index_data;
git_SHA_CTX ctx;
unsigned char sha1[20], *pack_sig;
off_t offset = 0, pack_sig_ofs = p->pack_size - 20;
off_t offset = 0, pack_sig_ofs = 0;
uint32_t nr_objects, i;
int err = 0;
struct idx_entry *entries;
Expand All @@ -61,14 +61,16 @@ static int verify_packfile(struct packed_git *p,
*/

git_SHA1_Init(&ctx);
while (offset < pack_sig_ofs) {
do {
unsigned int remaining;
unsigned char *in = use_pack(p, w_curs, offset, &remaining);
offset += remaining;
if (!pack_sig_ofs)
pack_sig_ofs = p->pack_size - 20;
if (offset > pack_sig_ofs)
remaining -= (unsigned int)(offset - pack_sig_ofs);
git_SHA1_Update(&ctx, in, remaining);
}
} while (offset < pack_sig_ofs);
git_SHA1_Final(sha1, &ctx);
pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);
if (hashcmp(sha1, pack_sig))
Expand Down
36 changes: 36 additions & 0 deletions t/t5540-http-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,42 @@ test_expect_success ' push to remote repository with unpacked refs' '
test $HEAD = $(git rev-parse --verify HEAD))
'

test_expect_success 'http-push fetches unpacked objects' '
cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
"$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_unpacked.git &&
git clone $HTTPD_URL/test_repo_unpacked.git \
"$ROOT_PATH"/fetch_unpacked &&
# By reset, we force git to retrieve the object
(cd "$ROOT_PATH"/fetch_unpacked &&
git reset --hard HEAD^ &&
git remote rm origin &&
git reflog expire --expire=0 --all &&
git prune &&
git push -f -v $HTTPD_URL/test_repo_unpacked.git master)
'

test_expect_success 'http-push fetches packed objects' '
cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
"$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
git clone $HTTPD_URL/test_repo_packed.git \
"$ROOT_PATH"/test_repo_clone_packed &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
git --bare repack &&
git --bare prune-packed) &&
# By reset, we force git to retrieve the packed object
(cd "$ROOT_PATH"/test_repo_clone_packed &&
git reset --hard HEAD^ &&
git remote rm origin &&
git reflog expire --expire=0 --all &&
git prune &&
git push -f -v $HTTPD_URL/test_repo_packed.git master)
'

test_expect_success 'create and delete remote branch' '
cd "$ROOT_PATH"/test_repo_clone &&
git checkout -b dev &&
Expand Down
8 changes: 8 additions & 0 deletions t/t5550-http-fetch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,13 @@ test_expect_success 'http remote detects correct HEAD' '
)
'

test_expect_success 'fetch packed objects' '
cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
git --bare repack &&
git --bare prune-packed &&
git clone $HTTPD_URL/repo_pack.git
'

stop_httpd
test_done
35 changes: 13 additions & 22 deletions transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,7 @@ static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
char *ref_name;
char *refs_url;
int i = 0;

struct active_request_slot *slot;
struct slot_results results;
int http_ret;

struct ref *refs = NULL;
struct ref *ref = NULL;
Expand All @@ -461,25 +459,16 @@ static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
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");
http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
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);
default:
http_error(refs_url, http_ret);
die("HTTP request failed");
}

data = buffer.buf;
Expand Down Expand Up @@ -519,6 +508,8 @@ static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
free(ref);
}

strbuf_release(&buffer);
free(refs_url);
return refs;
}

Expand Down

0 comments on commit e248619

Please sign in to comment.