* Re: Teach "approxidate" about weekday syntax
From: Linus Torvalds @ 2005-11-18 17:33 UTC (permalink / raw)
To: Andreas Ericsson; +Cc: David Roundy, git
In-Reply-To: <437E0ECC.8000503@op5.se>
On Fri, 18 Nov 2005, Andreas Ericsson wrote:
>
> 5 months with 73 days each; Chaos, Discord, Confusion, Bureaucracy, The
> Aftermath
> 5 days: Sweetmorn, Boomtime, Pungenday, Prickle-Prickle, Setting Orange
>
> February 29 is "St. Tibs day".
I'm sorry, but having "git log --since=confusion" would just be
irresponsible.
Linus
^ permalink raw reply
* Re: "make test" fails with current HEAD
From: Junio C Hamano @ 2005-11-18 17:16 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Matthias Urlichs, git
In-Reply-To: <Pine.LNX.4.64.0511180812200.13959@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> Umm.. Why not just say "if the line after the 'diff' line doesn't start
> with '@@ ', then it's a binary diff"?
Thanks, that makes sense.
^ permalink raw reply
* Re: Teach "approxidate" about weekday syntax
From: Andreas Ericsson @ 2005-11-18 17:26 UTC (permalink / raw)
To: Linus Torvalds; +Cc: David Roundy, git
In-Reply-To: <Pine.LNX.4.64.0511180842480.13959@g5.osdl.org>
Linus Torvalds wrote:
>
> On Fri, 18 Nov 2005, David Roundy wrote:
>
>>Don't forget "high noon"! (and perhaps "tea time"?) :)
>
>
> Done.
>
What about Discordian dates? You seem to be having so much fun and I'd
hate to spoil it for you. :)
It should be easier than Gregorian ones too.
5 months with 73 days each; Chaos, Discord, Confusion, Bureaucracy, The
Aftermath
5 days: Sweetmorn, Boomtime, Pungenday, Prickle-Prickle, Setting Orange
February 29 is "St. Tibs day".
For years, just tack on 1166 and you're good to go.
It'd be just lovely to be able to say
git whatchanged --since=chaos
Incidentally, git was first released in "Discord" which seems somehow
appropriate. :)
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: Ismail Donmez @ 2005-11-18 17:26 UTC (permalink / raw)
To: git
In-Reply-To: <200511181833.40048.ismail@uludag.org.tr>
On Friday 18 November 2005 18:33, you wrote:
> Hi all,
>
> I am trying to parse git's rss feed and now xml parsers seems to choke on
> it because of an error in the produced feed. Looking at
> http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=rss
>
> line 781 says :
>
> On Thu, 17 Nov 2005, David G\363mez wrote:<br/>
>
> which is part of the commit :
> http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=comm
>it;h=05b8b0fafd4cac75d205ecd5ad40992e2cc5934d
Ok looks like this text is latin-1 encoded although xml is served as utf-8.
/ismail
^ permalink raw reply
* Re: [RFC] Applying a graft to a tree and "rippling" the changes through
From: Linus Torvalds @ 2005-11-18 17:25 UTC (permalink / raw)
To: sf; +Cc: git
In-Reply-To: <437DDDB1.60103@b-i-t.de>
On Fri, 18 Nov 2005, sf wrote:
>
> I would go even further: The resulting tree does not depend on anything. A
> tree is a tree is a tree.
Agreed.
> A commit is really just the statement: "I changed the tree from state A to
> state B". After all, the commit message does not describe the new state
> (neither the old state) but does describe the changes.
No.
A commit is _not_ just the statement of change between two trees.
It's a statement of _history_ of the resulting tree. This is important.
It's why a commit does not just point to the previous tree, but to the
previous commit(s).
And that's really important. If you don't have a history of what has
happened, then all the trees are just random collections of files. They're
not a project any more.
So a commit doesn't just say "tree A changed into tree B". It very much
says something much much stronger, which includes how you got to A in the
first place.
The history is also what allow a commit to be meaningful. Without that
history, you could never say "I fixed the bug that was introduced by xyz",
which is often a very integral part of _why_ the change happened.
There are lots of changelog entries that don't necessarily make sense
without knowing what went before them, so history is actually important
even in a local sense - it's often what allows the explanation to make
sense.
Linus
^ permalink raw reply
* Re: Teach "approxidate" about weekday syntax
From: Linus Torvalds @ 2005-11-18 17:00 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: Johannes Schindelin, David Roundy, git
In-Reply-To: <Pine.LNX.4.58.0511180806550.25159@shark.he.net>
On Fri, 18 Nov 2005, Randy.Dunlap wrote:
>
> ~Randy [who would just use ISO standard date format]
That actually _does_ work, and has done so since the beginning:
[torvalds@g5 git]$ ./test-date "2005-11-02 14:45:00"
2005-11-02 14:45:00 -> 1130971500 -0800 -> Wed Nov 2 14:45:00 2005
2005-11-02 14:45:00 -> Wed Nov 2 14:45:00 2005
ie both the exact and the fuzzy date parsing will happily accept ISO
standard date format and exact times.
But when you want to know what happened since high tea yesterday, the
fuzzy format is unbeatable.
Linus
^ permalink raw reply
* Re: Teach "approxidate" about weekday syntax
From: H. Peter Anvin @ 2005-11-18 18:08 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: David Roundy, git
In-Reply-To: <Pine.LNX.4.63.0511181419340.28109@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin wrote:
> Hi,
>
> On Fri, 18 Nov 2005, David Roundy wrote:
>
>
>>Don't forget "high noon"! (and perhaps "tea time"?) :)
>
>
> How about "dooms day"? I would like to do this:
>
> git-whatchanged -p --until="dooms day"
>
Domesday was some time in August 1086, right?
-hpa
^ permalink raw reply
* [PATCH 0/5] HTTP refactoring/cleanup
From: Nick Hengeveld @ 2005-11-18 19:02 UTC (permalink / raw)
To: git
The following set of patches cleans up http-fetch and http-push.
- Common HTTP code has been moved to http.c/http.h. While
curl-specific code still exists in both http-fetch and http-push,
it is a step in the direction of allowing use of a different HTTP
request library if someone is so inclined.
- Object request functions and data have been renamed to keep clear
what types of requests are being processed, which will make it
easier to process additional types of requests in parallel (eg.
starting pack downloads immediately when an object 404s)
- The reliability and performance of http-fetch has been improved when
built in an environment without curl multi support.
- XML parsing in http-push has been improved, which will make it
easier to add functionality to update remote server info.
--
For a successful technology, reality must take precedence over public
relations, for nature cannot be fooled.
^ permalink raw reply
* [PATCH 2/5] Make http-fetch request types more clear
From: Nick Hengeveld @ 2005-11-18 19:03 UTC (permalink / raw)
To: git
Rename object request functions and data to make it more clear which type
of request is being processed - this is a response to the introduction of
slot callbacks and the definition of different types of requests such as
alternates_request.
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
http-fetch.c | 275 +++++++++++++++++++++++++++++-----------------------------
1 files changed, 139 insertions(+), 136 deletions(-)
applies-to: ca1aeba57d4c1ac8d7e6550dba68ead4539696e5
d3d94b6074099a6aa68280430d38678028268678
diff --git a/http-fetch.c b/http-fetch.c
index 6a9eaf3..53a7dbf 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -21,14 +21,14 @@ struct alt_base
static struct alt_base *alt = NULL;
-enum transfer_state {
+enum object_request_state {
WAITING,
ABORTED,
ACTIVE,
COMPLETE,
};
-struct transfer_request
+struct object_request
{
unsigned char sha1[20];
struct alt_base *repo;
@@ -36,7 +36,7 @@ struct transfer_request
char filename[PATH_MAX];
char tmpfile[PATH_MAX];
int local;
- enum transfer_state state;
+ enum object_request_state state;
CURLcode curl_result;
char errorstr[CURL_ERROR_SIZE];
long http_code;
@@ -46,10 +46,10 @@ struct transfer_request
int zret;
int rename;
struct active_request_slot *slot;
- struct transfer_request *next;
+ struct object_request *next;
};
-struct alt_request {
+struct alternates_request {
char *base;
char *url;
struct buffer *buffer;
@@ -57,7 +57,7 @@ struct alt_request {
int http_specific;
};
-static struct transfer_request *request_queue_head = NULL;
+static struct object_request *object_queue_head = NULL;
static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
void *data)
@@ -65,24 +65,24 @@ static size_t fwrite_sha1_file(void *ptr
unsigned char expn[4096];
size_t size = eltsize * nmemb;
int posn = 0;
- struct transfer_request *request = (struct transfer_request *)data;
+ struct object_request *obj_req = (struct object_request *)data;
do {
- ssize_t retval = write(request->local,
+ ssize_t retval = write(obj_req->local,
ptr + posn, size - posn);
if (retval < 0)
return posn;
posn += retval;
} while (posn < size);
- request->stream.avail_in = size;
- request->stream.next_in = ptr;
+ obj_req->stream.avail_in = size;
+ obj_req->stream.next_in = ptr;
do {
- request->stream.next_out = expn;
- request->stream.avail_out = sizeof(expn);
- request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
- SHA1_Update(&request->c, expn,
- sizeof(expn) - request->stream.avail_out);
- } while (request->stream.avail_in && request->zret == Z_OK);
+ obj_req->stream.next_out = expn;
+ obj_req->stream.avail_out = sizeof(expn);
+ obj_req->zret = inflate(&obj_req->stream, Z_SYNC_FLUSH);
+ SHA1_Update(&obj_req->c, expn,
+ sizeof(expn) - obj_req->stream.avail_out);
+ } while (obj_req->stream.avail_in && obj_req->zret == Z_OK);
data_received++;
return size;
}
@@ -91,9 +91,9 @@ static void fetch_alternates(char *base)
static void process_object_response(void *callback_data);
-static void start_request(struct transfer_request *request)
+static void start_object_request(struct object_request *obj_req)
{
- char *hex = sha1_to_hex(request->sha1);
+ char *hex = sha1_to_hex(obj_req->sha1);
char prevfile[PATH_MAX];
char *url;
char *posn;
@@ -105,53 +105,53 @@ static void start_request(struct transfe
struct curl_slist *range_header = NULL;
struct active_request_slot *slot;
- snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
+ snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename);
unlink(prevfile);
- rename(request->tmpfile, prevfile);
- unlink(request->tmpfile);
+ rename(obj_req->tmpfile, prevfile);
+ unlink(obj_req->tmpfile);
- if (request->local != -1)
- error("fd leakage in start: %d", request->local);
- request->local = open(request->tmpfile,
+ if (obj_req->local != -1)
+ error("fd leakage in start: %d", obj_req->local);
+ obj_req->local = open(obj_req->tmpfile,
O_WRONLY | O_CREAT | O_EXCL, 0666);
/* This could have failed due to the "lazy directory creation";
* try to mkdir the last path component.
*/
- if (request->local < 0 && errno == ENOENT) {
- char *dir = strrchr(request->tmpfile, '/');
+ if (obj_req->local < 0 && errno == ENOENT) {
+ char *dir = strrchr(obj_req->tmpfile, '/');
if (dir) {
*dir = 0;
- mkdir(request->tmpfile, 0777);
+ mkdir(obj_req->tmpfile, 0777);
*dir = '/';
}
- request->local = open(request->tmpfile,
+ obj_req->local = open(obj_req->tmpfile,
O_WRONLY | O_CREAT | O_EXCL, 0666);
}
- if (request->local < 0) {
- request->state = ABORTED;
+ if (obj_req->local < 0) {
+ obj_req->state = ABORTED;
error("Couldn't create temporary file %s for %s: %s\n",
- request->tmpfile, request->filename, strerror(errno));
+ obj_req->tmpfile, obj_req->filename, strerror(errno));
return;
}
- memset(&request->stream, 0, sizeof(request->stream));
+ memset(&obj_req->stream, 0, sizeof(obj_req->stream));
- inflateInit(&request->stream);
+ inflateInit(&obj_req->stream);
- SHA1_Init(&request->c);
+ SHA1_Init(&obj_req->c);
- url = xmalloc(strlen(request->repo->base) + 50);
- request->url = xmalloc(strlen(request->repo->base) + 50);
- strcpy(url, request->repo->base);
- posn = url + strlen(request->repo->base);
+ url = xmalloc(strlen(obj_req->repo->base) + 50);
+ obj_req->url = xmalloc(strlen(obj_req->repo->base) + 50);
+ strcpy(url, obj_req->repo->base);
+ posn = url + strlen(obj_req->repo->base);
strcpy(posn, "objects/");
posn += 8;
memcpy(posn, hex, 2);
posn += 2;
*(posn++) = '/';
strcpy(posn, hex + 2);
- strcpy(request->url, url);
+ strcpy(obj_req->url, url);
/* If a previous temp file is present, process what was already
fetched. */
@@ -163,7 +163,7 @@ static void start_request(struct transfe
if (fwrite_sha1_file(prev_buf,
1,
prev_read,
- request) == prev_read) {
+ obj_req) == prev_read) {
prev_posn += prev_read;
} else {
prev_read = -1;
@@ -177,24 +177,24 @@ static void start_request(struct transfe
/* Reset inflate/SHA1 if there was an error reading the previous temp
file; also rewind to the beginning of the local file. */
if (prev_read == -1) {
- memset(&request->stream, 0, sizeof(request->stream));
- inflateInit(&request->stream);
- SHA1_Init(&request->c);
+ memset(&obj_req->stream, 0, sizeof(obj_req->stream));
+ inflateInit(&obj_req->stream);
+ SHA1_Init(&obj_req->c);
if (prev_posn>0) {
prev_posn = 0;
- lseek(request->local, SEEK_SET, 0);
- ftruncate(request->local, 0);
+ lseek(obj_req->local, SEEK_SET, 0);
+ ftruncate(obj_req->local, 0);
}
}
slot = get_active_slot();
slot->callback_func = process_object_response;
- slot->callback_data = request;
- request->slot = slot;
+ slot->callback_data = obj_req;
+ obj_req->slot = slot;
- curl_easy_setopt(slot->curl, CURLOPT_FILE, request);
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, obj_req);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
- curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, obj_req->errorstr);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
@@ -212,109 +212,111 @@ static void start_request(struct transfe
}
/* Try to get the request started, abort the request on error */
- request->state = ACTIVE;
+ obj_req->state = ACTIVE;
if (!start_active_slot(slot)) {
- request->state = ABORTED;
- request->slot = NULL;
- close(request->local); request->local = -1;
- free(request->url);
+ obj_req->state = ABORTED;
+ obj_req->slot = NULL;
+ close(obj_req->local); obj_req->local = -1;
+ free(obj_req->url);
+ return;
}
+
}
-static void finish_request(struct transfer_request *request)
+static void finish_object_request(struct object_request *obj_req)
{
struct stat st;
- fchmod(request->local, 0444);
- close(request->local); request->local = -1;
+ fchmod(obj_req->local, 0444);
+ close(obj_req->local); obj_req->local = -1;
- if (request->http_code == 416) {
+ if (obj_req->http_code == 416) {
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
- } else if (request->curl_result != CURLE_OK) {
- if (stat(request->tmpfile, &st) == 0)
+ } else if (obj_req->curl_result != CURLE_OK) {
+ if (stat(obj_req->tmpfile, &st) == 0)
if (st.st_size == 0)
- unlink(request->tmpfile);
+ unlink(obj_req->tmpfile);
return;
}
- inflateEnd(&request->stream);
- SHA1_Final(request->real_sha1, &request->c);
- if (request->zret != Z_STREAM_END) {
- unlink(request->tmpfile);
+ inflateEnd(&obj_req->stream);
+ SHA1_Final(obj_req->real_sha1, &obj_req->c);
+ if (obj_req->zret != Z_STREAM_END) {
+ unlink(obj_req->tmpfile);
return;
}
- if (memcmp(request->sha1, request->real_sha1, 20)) {
- unlink(request->tmpfile);
+ if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
+ unlink(obj_req->tmpfile);
return;
}
- request->rename =
- move_temp_to_file(request->tmpfile, request->filename);
+ obj_req->rename =
+ move_temp_to_file(obj_req->tmpfile, obj_req->filename);
- if (request->rename == 0)
- pull_say("got %s\n", sha1_to_hex(request->sha1));
+ if (obj_req->rename == 0)
+ pull_say("got %s\n", sha1_to_hex(obj_req->sha1));
}
static void process_object_response(void *callback_data)
{
- struct transfer_request *request =
- (struct transfer_request *)callback_data;
+ struct object_request *obj_req =
+ (struct object_request *)callback_data;
- request->curl_result = request->slot->curl_result;
- request->http_code = request->slot->http_code;
- request->slot = NULL;
- request->state = COMPLETE;
+ obj_req->curl_result = obj_req->slot->curl_result;
+ obj_req->http_code = obj_req->slot->http_code;
+ obj_req->slot = NULL;
+ obj_req->state = COMPLETE;
/* Use alternates if necessary */
- if (request->http_code == 404) {
+ if (obj_req->http_code == 404) {
fetch_alternates(alt->base);
- if (request->repo->next != NULL) {
- request->repo =
- request->repo->next;
- close(request->local);
- request->local = -1;
- start_request(request);
+ if (obj_req->repo->next != NULL) {
+ obj_req->repo =
+ obj_req->repo->next;
+ close(obj_req->local);
+ obj_req->local = -1;
+ start_object_request(obj_req);
return;
}
}
- finish_request(request);
+ finish_object_request(obj_req);
}
-static void release_request(struct transfer_request *request)
+static void release_object_request(struct object_request *obj_req)
{
- struct transfer_request *entry = request_queue_head;
+ struct object_request *entry = object_queue_head;
- if (request->local != -1)
- error("fd leakage in release: %d", request->local);
- if (request == request_queue_head) {
- request_queue_head = request->next;
+ if (obj_req->local != -1)
+ error("fd leakage in release: %d", obj_req->local);
+ if (obj_req == object_queue_head) {
+ object_queue_head = obj_req->next;
} else {
- while (entry->next != NULL && entry->next != request)
+ while (entry->next != NULL && entry->next != obj_req)
entry = entry->next;
- if (entry->next == request)
+ if (entry->next == obj_req)
entry->next = entry->next->next;
}
- free(request->url);
- free(request);
+ free(obj_req->url);
+ free(obj_req);
}
#ifdef USE_CURL_MULTI
void fill_active_slots(void)
{
- struct transfer_request *request = request_queue_head;
+ struct object_request *obj_req = object_queue_head;
struct active_request_slot *slot = active_queue_head;
int num_transfers;
- while (active_requests < max_requests && request != NULL) {
- if (request->state == WAITING) {
- if (has_sha1_file(request->sha1))
- release_request(request);
+ while (active_requests < max_requests && obj_req != NULL) {
+ if (obj_req->state == WAITING) {
+ if (has_sha1_file(obj_req->sha1))
+ release_object_request(obj_req);
else
- start_request(request);
+ start_object_request(obj_req);
curl_multi_perform(curlm, &num_transfers);
}
- request = request->next;
+ obj_req = obj_req->next;
}
while (slot != NULL) {
@@ -329,8 +331,8 @@ void fill_active_slots(void)
void prefetch(unsigned char *sha1)
{
- struct transfer_request *newreq;
- struct transfer_request *tail;
+ struct object_request *newreq;
+ struct object_request *tail;
char *filename = sha1_file_name(sha1);
newreq = xmalloc(sizeof(*newreq));
@@ -344,10 +346,10 @@ void prefetch(unsigned char *sha1)
"%s.temp", filename);
newreq->next = NULL;
- if (request_queue_head == NULL) {
- request_queue_head = newreq;
+ if (object_queue_head == NULL) {
+ object_queue_head = newreq;
} else {
- tail = request_queue_head;
+ tail = object_queue_head;
while (tail->next != NULL) {
tail = tail->next;
}
@@ -441,9 +443,10 @@ static int setup_index(struct alt_base *
return 0;
}
-static void process_alternates(void *callback_data)
+static void process_alternates_response(void *callback_data)
{
- struct alt_request *alt_req = (struct alt_request *)callback_data;
+ struct alternates_request *alt_req =
+ (struct alternates_request *)callback_data;
struct active_request_slot *slot = alt_req->slot;
struct alt_base *tail = alt;
char *base = alt_req->base;
@@ -548,7 +551,7 @@ static void fetch_alternates(char *base)
char *url;
char *data;
struct active_request_slot *slot;
- static struct alt_request alt_req;
+ static struct alternates_request alt_req;
/* If another request has already started fetching alternates,
wait for them to arrive and return to processing this request's
@@ -580,7 +583,7 @@ static void fetch_alternates(char *base)
/* Use a callback to process the result, since another request
may fail and need to have alternates loaded before continuing */
slot = get_active_slot();
- slot->callback_func = process_alternates;
+ slot->callback_func = process_alternates_response;
slot->callback_data = &alt_req;
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
@@ -760,54 +763,54 @@ static int fetch_object(struct alt_base
{
char *hex = sha1_to_hex(sha1);
int ret = 0;
- struct transfer_request *request = request_queue_head;
+ struct object_request *obj_req = object_queue_head;
- while (request != NULL && memcmp(request->sha1, sha1, 20))
- request = request->next;
- if (request == NULL)
+ while (obj_req != NULL && memcmp(obj_req->sha1, sha1, 20))
+ obj_req = obj_req->next;
+ if (obj_req == NULL)
return error("Couldn't find request for %s in the queue", hex);
- if (has_sha1_file(request->sha1)) {
- release_request(request);
+ if (has_sha1_file(obj_req->sha1)) {
+ release_object_request(obj_req);
return 0;
}
#ifdef USE_CURL_MULTI
- while (request->state == WAITING) {
+ while (obj_req->state == WAITING) {
step_active_slots();
}
#else
- start_request(request);
+ start_object_request(obj_req);
#endif
- while (request->state == ACTIVE) {
- run_active_slot(request->slot);
+ while (obj_req->state == ACTIVE) {
+ run_active_slot(obj_req->slot);
}
- if (request->local != -1) {
- close(request->local); request->local = -1;
+ if (obj_req->local != -1) {
+ close(obj_req->local); obj_req->local = -1;
}
- if (request->state == ABORTED) {
+ if (obj_req->state == ABORTED) {
ret = error("Request for %s aborted", hex);
- } else if (request->curl_result != CURLE_OK &&
- request->http_code != 416) {
- if (request->http_code == 404)
+ } else if (obj_req->curl_result != CURLE_OK &&
+ obj_req->http_code != 416) {
+ if (obj_req->http_code == 404)
ret = -1; /* Be silent, it is probably in a pack. */
else
ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)",
- request->errorstr, request->curl_result,
- request->http_code, hex);
- } else if (request->zret != Z_STREAM_END) {
- ret = error("File %s (%s) corrupt\n", hex, request->url);
- } else if (memcmp(request->sha1, request->real_sha1, 20)) {
+ obj_req->errorstr, obj_req->curl_result,
+ obj_req->http_code, hex);
+ } else if (obj_req->zret != Z_STREAM_END) {
+ ret = error("File %s (%s) corrupt\n", hex, obj_req->url);
+ } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
ret = error("File %s has bad hash\n", hex);
- } else if (request->rename < 0) {
+ } else if (obj_req->rename < 0) {
ret = error("unable to write sha1 filename %s: %s",
- request->filename,
- strerror(request->rename));
+ obj_req->filename,
+ strerror(obj_req->rename));
}
- release_request(request);
+ release_object_request(obj_req);
return ret;
}
---
0.99.9.GIT
^ permalink raw reply related
* [PATCH 1/5] Isolate shared HTTP request functionality
From: Nick Hengeveld @ 2005-11-18 19:02 UTC (permalink / raw)
To: git
Move shared HTTP request functionality out of http-fetch and http-push,
and replace the two fwrite_buffer/fwrite_buffer_dynamic functions with
one fwrite_buffer function that does dynamic buffering. Use slot
callbacks to process responses to fetch object transfer requests and
push transfer requests, and put all of http-push into an #ifdef check
for curl multi support.
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
Makefile | 3
http-fetch.c | 586 ++++++----------------------------------------------------
http-push.c | 484 ++++--------------------------------------------
http.c | 443 ++++++++++++++++++++++++++++++++++++++++++++
http.h | 95 +++++++++
5 files changed, 635 insertions(+), 976 deletions(-)
create mode 100644 http.c
create mode 100644 http.h
applies-to: ae209db4abcd6d0c83ac92c23bb9b16ffd5bcf7e
4e68fe30c4999c9b1ad40ab562df61d9c267b8a2
diff --git a/Makefile b/Makefile
index 3bdd059..59c9a44 100644
--- a/Makefile
+++ b/Makefile
@@ -383,7 +383,8 @@ $(SIMPLE_PROGRAMS) : git-%$X : %.o
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIB_FILE) $(SIMPLE_LIB)
-git-http-fetch$X: fetch.o
+git-http-fetch$X: fetch.o http.o
+git-http-push$X: http.o
git-local-fetch$X: fetch.o
git-ssh-fetch$X: rsh.o fetch.o
git-ssh-upload$X: rsh.o
diff --git a/http-fetch.c b/http-fetch.c
index 21cc1b9..6a9eaf3 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -2,44 +2,14 @@
#include "commit.h"
#include "pack.h"
#include "fetch.h"
-
-#include <curl/curl.h>
-#include <curl/easy.h>
-
-#if LIBCURL_VERSION_NUM >= 0x070908
-#define USE_CURL_MULTI
-#define DEFAULT_MAX_REQUESTS 5
-#endif
-
-#if LIBCURL_VERSION_NUM < 0x070704
-#define curl_global_cleanup() do { /* nothing */ } while(0)
-#endif
-#if LIBCURL_VERSION_NUM < 0x070800
-#define curl_global_init(a) do { /* nothing */ } while(0)
-#endif
-
-#if LIBCURL_VERSION_NUM < 0x070c04
-#define NO_CURL_EASY_DUPHANDLE
-#endif
+#include "http.h"
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
static int got_alternates = -1;
-static int active_requests = 0;
-static int data_received;
-#ifdef USE_CURL_MULTI
-static int max_requests = -1;
-static CURLM *curlm;
-#endif
-#ifndef NO_CURL_EASY_DUPHANDLE
-static CURL *curl_default;
-#endif
-static struct curl_slist *pragma_header;
static struct curl_slist *no_pragma_header;
-static struct curl_slist *no_range_header;
-static char curl_errorstr[CURL_ERROR_SIZE];
struct alt_base
{
@@ -79,19 +49,6 @@ struct transfer_request
struct transfer_request *next;
};
-struct active_request_slot
-{
- CURL *curl;
- FILE *local;
- int in_use;
- int done;
- CURLcode curl_result;
- long http_code;
- void *callback_data;
- void (*callback_func)(void *data);
- struct active_request_slot *next;
-};
-
struct alt_request {
char *base;
char *url;
@@ -101,119 +58,6 @@ struct alt_request {
};
static struct transfer_request *request_queue_head = NULL;
-static struct active_request_slot *active_queue_head = NULL;
-
-static int curl_ssl_verify = -1;
-static char *ssl_cert = NULL;
-#if LIBCURL_VERSION_NUM >= 0x070902
-static char *ssl_key = NULL;
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
-static char *ssl_capath = NULL;
-#endif
-static char *ssl_cainfo = NULL;
-static long curl_low_speed_limit = -1;
-static long curl_low_speed_time = -1;
-
-struct buffer
-{
- size_t posn;
- size_t size;
- void *buffer;
-};
-
-static int http_options(const char *var, const char *value)
-{
- if (!strcmp("http.sslverify", var)) {
- if (curl_ssl_verify == -1) {
- curl_ssl_verify = git_config_bool(var, value);
- }
- return 0;
- }
-
- if (!strcmp("http.sslcert", var)) {
- if (ssl_cert == NULL) {
- ssl_cert = xmalloc(strlen(value)+1);
- strcpy(ssl_cert, value);
- }
- return 0;
- }
-#if LIBCURL_VERSION_NUM >= 0x070902
- if (!strcmp("http.sslkey", var)) {
- if (ssl_key == NULL) {
- ssl_key = xmalloc(strlen(value)+1);
- strcpy(ssl_key, value);
- }
- return 0;
- }
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- if (!strcmp("http.sslcapath", var)) {
- if (ssl_capath == NULL) {
- ssl_capath = xmalloc(strlen(value)+1);
- strcpy(ssl_capath, value);
- }
- return 0;
- }
-#endif
- if (!strcmp("http.sslcainfo", var)) {
- if (ssl_cainfo == NULL) {
- ssl_cainfo = xmalloc(strlen(value)+1);
- strcpy(ssl_cainfo, value);
- }
- return 0;
- }
-
-#ifdef USE_CURL_MULTI
- if (!strcmp("http.maxrequests", var)) {
- if (max_requests == -1)
- max_requests = git_config_int(var, value);
- return 0;
- }
-#endif
-
- if (!strcmp("http.lowspeedlimit", var)) {
- if (curl_low_speed_limit == -1)
- curl_low_speed_limit = (long)git_config_int(var, value);
- return 0;
- }
- if (!strcmp("http.lowspeedtime", var)) {
- if (curl_low_speed_time == -1)
- curl_low_speed_time = (long)git_config_int(var, value);
- return 0;
- }
-
- /* Fall back on the default ones */
- return git_default_config(var, value);
-}
-
-static size_t fwrite_buffer(void *ptr, size_t eltsize, size_t nmemb,
- struct buffer *buffer)
-{
- size_t size = eltsize * nmemb;
- if (size > buffer->size - buffer->posn)
- size = buffer->size - buffer->posn;
- memcpy(buffer->buffer + buffer->posn, ptr, size);
- buffer->posn += size;
- data_received++;
- return size;
-}
-
-static size_t fwrite_buffer_dynamic(const void *ptr, size_t eltsize,
- size_t nmemb, struct buffer *buffer)
-{
- size_t size = eltsize * nmemb;
- if (size > buffer->size - buffer->posn) {
- buffer->size = buffer->size * 3 / 2;
- if (buffer->size < buffer->posn + size)
- buffer->size = buffer->posn + size;
- buffer->buffer = xrealloc(buffer->buffer, buffer->size);
- }
- memcpy(buffer->buffer + buffer->posn, ptr, size);
- buffer->posn += size;
- data_received++;
- return size;
-}
static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
void *data)
@@ -243,168 +87,9 @@ static size_t fwrite_sha1_file(void *ptr
return size;
}
-#ifdef USE_CURL_MULTI
-static void process_curl_messages(void);
-static void process_request_queue(void);
-#endif
static void fetch_alternates(char *base);
-static CURL* get_curl_handle(void)
-{
- CURL* result = curl_easy_init();
-
- curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
-#if LIBCURL_VERSION_NUM >= 0x070907
- curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
-#endif
-
- if (ssl_cert != NULL)
- curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
-#if LIBCURL_VERSION_NUM >= 0x070902
- if (ssl_key != NULL)
- curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- if (ssl_capath != NULL)
- curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
-#endif
- if (ssl_cainfo != NULL)
- curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
- curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
-
- if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
- curl_low_speed_limit);
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
- curl_low_speed_time);
- }
-
- curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
-
- return result;
-}
-
-static struct active_request_slot *get_active_slot(void)
-{
- struct active_request_slot *slot = active_queue_head;
- struct active_request_slot *newslot;
-
-#ifdef USE_CURL_MULTI
- int num_transfers;
-
- /* Wait for a slot to open up if the queue is full */
- while (active_requests >= max_requests) {
- curl_multi_perform(curlm, &num_transfers);
- if (num_transfers < active_requests) {
- process_curl_messages();
- }
- }
-#endif
-
- while (slot != NULL && slot->in_use) {
- slot = slot->next;
- }
- if (slot == NULL) {
- newslot = xmalloc(sizeof(*newslot));
- newslot->curl = NULL;
- newslot->in_use = 0;
- newslot->next = NULL;
-
- slot = active_queue_head;
- if (slot == NULL) {
- active_queue_head = newslot;
- } else {
- while (slot->next != NULL) {
- slot = slot->next;
- }
- slot->next = newslot;
- }
- slot = newslot;
- }
-
- if (slot->curl == NULL) {
-#ifdef NO_CURL_EASY_DUPHANDLE
- slot->curl = get_curl_handle();
-#else
- slot->curl = curl_easy_duphandle(curl_default);
-#endif
- }
-
- active_requests++;
- slot->in_use = 1;
- slot->done = 0;
- slot->local = NULL;
- slot->callback_data = NULL;
- slot->callback_func = NULL;
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
- curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
-
- return slot;
-}
-
-static int start_active_slot(struct active_request_slot *slot)
-{
-#ifdef USE_CURL_MULTI
- CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
-
- if (curlm_result != CURLM_OK &&
- curlm_result != CURLM_CALL_MULTI_PERFORM) {
- active_requests--;
- slot->in_use = 0;
- return 0;
- }
-#endif
- return 1;
-}
-
-static void run_active_slot(struct active_request_slot *slot)
-{
-#ifdef USE_CURL_MULTI
- int num_transfers;
- long last_pos = 0;
- long current_pos;
- fd_set readfds;
- fd_set writefds;
- fd_set excfds;
- int max_fd;
- struct timeval select_timeout;
- CURLMcode curlm_result;
-
- while (!slot->done) {
- data_received = 0;
- do {
- curlm_result = curl_multi_perform(curlm,
- &num_transfers);
- } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
- if (num_transfers < active_requests) {
- process_curl_messages();
- process_request_queue();
- }
-
- if (!data_received && slot->local != NULL) {
- current_pos = ftell(slot->local);
- if (current_pos > last_pos)
- data_received++;
- last_pos = current_pos;
- }
-
- if (!slot->done && !data_received) {
- max_fd = 0;
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&excfds);
- select_timeout.tv_sec = 0;
- select_timeout.tv_usec = 50000;
- select(max_fd, &readfds, &writefds,
- &excfds, &select_timeout);
- }
- }
-#else
- slot->curl_result = curl_easy_perform(slot->curl);
- active_requests--;
-#endif
-}
+static void process_object_response(void *callback_data);
static void start_request(struct transfer_request *request)
{
@@ -503,6 +188,10 @@ static void start_request(struct transfe
}
slot = get_active_slot();
+ slot->callback_func = process_object_response;
+ slot->callback_data = request;
+ request->slot = slot;
+
curl_easy_setopt(slot->curl, CURLOPT_FILE, request);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
@@ -523,15 +212,13 @@ static void start_request(struct transfe
}
/* Try to get the request started, abort the request on error */
+ request->state = ACTIVE;
if (!start_active_slot(slot)) {
request->state = ABORTED;
+ request->slot = NULL;
close(request->local); request->local = -1;
free(request->url);
- return;
}
-
- request->slot = slot;
- request->state = ACTIVE;
}
static void finish_request(struct transfer_request *request)
@@ -567,6 +254,32 @@ static void finish_request(struct transf
pull_say("got %s\n", sha1_to_hex(request->sha1));
}
+static void process_object_response(void *callback_data)
+{
+ struct transfer_request *request =
+ (struct transfer_request *)callback_data;
+
+ request->curl_result = request->slot->curl_result;
+ request->http_code = request->slot->http_code;
+ request->slot = NULL;
+ request->state = COMPLETE;
+
+ /* Use alternates if necessary */
+ if (request->http_code == 404) {
+ fetch_alternates(alt->base);
+ if (request->repo->next != NULL) {
+ request->repo =
+ request->repo->next;
+ close(request->local);
+ request->local = -1;
+ start_request(request);
+ return;
+ }
+ }
+
+ finish_request(request);
+}
+
static void release_request(struct transfer_request *request)
{
struct transfer_request *entry = request_queue_head;
@@ -587,73 +300,7 @@ static void release_request(struct trans
}
#ifdef USE_CURL_MULTI
-static void process_curl_messages(void)
-{
- int num_messages;
- struct active_request_slot *slot;
- struct transfer_request *request = NULL;
- CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
-
- while (curl_message != NULL) {
- if (curl_message->msg == CURLMSG_DONE) {
- int curl_result = curl_message->data.result;
- slot = active_queue_head;
- while (slot != NULL &&
- slot->curl != curl_message->easy_handle)
- slot = slot->next;
- if (slot != NULL) {
- curl_multi_remove_handle(curlm, slot->curl);
- active_requests--;
- slot->done = 1;
- slot->in_use = 0;
- slot->curl_result = curl_result;
- curl_easy_getinfo(slot->curl,
- CURLINFO_HTTP_CODE,
- &slot->http_code);
- request = request_queue_head;
- while (request != NULL &&
- request->slot != slot)
- request = request->next;
- } else {
- fprintf(stderr, "Received DONE message for unknown request!\n");
- }
-
- /* Process slot callback if appropriate */
- if (slot->callback_func != NULL) {
- slot->callback_func(slot->callback_data);
- }
-
- if (request != NULL) {
- request->curl_result = curl_result;
- request->http_code = slot->http_code;
- request->slot = NULL;
- request->state = COMPLETE;
-
- /* Use alternates if necessary */
- if (request->http_code == 404) {
- fetch_alternates(alt->base);
- if (request->repo->next != NULL) {
- request->repo =
- request->repo->next;
- close(request->local);
- request->local = -1;
- start_request(request);
- } else {
- finish_request(request);
- }
- } else {
- finish_request(request);
- }
- }
- } else {
- fprintf(stderr, "Unknown CURL message received: %d\n",
- (int)curl_message->msg);
- }
- curl_message = curl_multi_info_read(curlm, &num_messages);
- }
-}
-
-static void process_request_queue(void)
+void fill_active_slots(void)
{
struct transfer_request *request = request_queue_head;
struct active_request_slot *slot = active_queue_head;
@@ -706,9 +353,10 @@ void prefetch(unsigned char *sha1)
}
tail->next = newreq;
}
+
#ifdef USE_CURL_MULTI
- process_request_queue();
- process_curl_messages();
+ fill_active_slots();
+ step_active_slots();
#endif
}
@@ -815,12 +463,11 @@ static void process_alternates(void *cal
alt_req->url);
active_requests++;
slot->in_use = 1;
- slot->done = 0;
if (start_active_slot(slot)) {
return;
} else {
got_alternates = -1;
- slot->done = 1;
+ slot->in_use = 0;
return;
}
}
@@ -831,7 +478,7 @@ static void process_alternates(void *cal
}
}
- fwrite_buffer_dynamic(&null_byte, 1, 1, alt_req->buffer);
+ fwrite_buffer(&null_byte, 1, 1, alt_req->buffer);
alt_req->buffer->posn--;
data = alt_req->buffer->buffer;
@@ -902,16 +549,15 @@ static void fetch_alternates(char *base)
char *data;
struct active_request_slot *slot;
static struct alt_request alt_req;
- int num_transfers;
/* If another request has already started fetching alternates,
wait for them to arrive and return to processing this request's
curl message */
+#ifdef USE_CURL_MULTI
while (got_alternates == 0) {
- curl_multi_perform(curlm, &num_transfers);
- process_curl_messages();
- process_request_queue();
+ step_active_slots();
}
+#endif
/* Nothing to do if they've already been fetched */
if (got_alternates == 1)
@@ -938,8 +584,7 @@ static void fetch_alternates(char *base)
slot->callback_data = &alt_req;
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
alt_req.base = base;
@@ -983,8 +628,7 @@ static int fetch_indices(struct alt_base
slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
if (start_active_slot(slot)) {
@@ -1115,7 +759,7 @@ static int fetch_pack(struct alt_base *r
static int fetch_object(struct alt_base *repo, unsigned char *sha1)
{
char *hex = sha1_to_hex(sha1);
- int ret;
+ int ret = 0;
struct transfer_request *request = request_queue_head;
while (request != NULL && memcmp(request->sha1, sha1, 20))
@@ -1130,12 +774,7 @@ static int fetch_object(struct alt_base
#ifdef USE_CURL_MULTI
while (request->state == WAITING) {
- int num_transfers;
- curl_multi_perform(curlm, &num_transfers);
- if (num_transfers < active_requests) {
- process_curl_messages();
- process_request_queue();
- }
+ step_active_slots();
}
#else
start_request(request);
@@ -1143,66 +782,33 @@ static int fetch_object(struct alt_base
while (request->state == ACTIVE) {
run_active_slot(request->slot);
-#ifndef USE_CURL_MULTI
- request->curl_result = request->slot->curl_result;
- request->http_code = request->slot->http_code;
- request->slot = NULL;
-
- /* Use alternates if necessary */
- if (request->http_code == 404) {
- fetch_alternates(alt->base);
- if (request->repo->next != NULL) {
- request->repo = request->repo->next;
- close(request->local); request->local = -1;
- start_request(request);
- }
- } else {
- finish_request(request);
- request->state = COMPLETE;
- }
-#endif
}
if (request->local != -1) {
close(request->local); request->local = -1;
}
if (request->state == ABORTED) {
- release_request(request);
- return error("Request for %s aborted", hex);
- }
-
- if (request->curl_result != CURLE_OK && request->http_code != 416) {
+ ret = error("Request for %s aborted", hex);
+ } else if (request->curl_result != CURLE_OK &&
+ request->http_code != 416) {
if (request->http_code == 404)
ret = -1; /* Be silent, it is probably in a pack. */
else
ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)",
request->errorstr, request->curl_result,
request->http_code, hex);
- release_request(request);
- return ret;
- }
-
- if (request->zret != Z_STREAM_END) {
+ } else if (request->zret != Z_STREAM_END) {
ret = error("File %s (%s) corrupt\n", hex, request->url);
- release_request(request);
- return ret;
- }
-
- if (memcmp(request->sha1, request->real_sha1, 20)) {
- release_request(request);
- return error("File %s has bad hash\n", hex);
- }
-
- if (request->rename < 0) {
+ } else if (memcmp(request->sha1, request->real_sha1, 20)) {
+ ret = error("File %s has bad hash\n", hex);
+ } else if (request->rename < 0) {
ret = error("unable to write sha1 filename %s: %s",
request->filename,
strerror(request->rename));
- release_request(request);
- return ret;
}
release_request(request);
- return 0;
+ return ret;
}
int fetch(unsigned char *sha1)
@@ -1303,10 +909,6 @@ int main(int argc, char **argv)
char *commit_id;
char *url;
int arg = 1;
- struct active_request_slot *slot;
- char *low_speed_limit;
- char *low_speed_time;
- char *wait_url;
int rc = 0;
while (arg < argc && argv[arg][0] == '-') {
@@ -1335,58 +937,9 @@ int main(int argc, char **argv)
commit_id = argv[arg];
url = argv[arg + 1];
- curl_global_init(CURL_GLOBAL_ALL);
-
-#ifdef USE_CURL_MULTI
- {
- char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
- if (http_max_requests != NULL)
- max_requests = atoi(http_max_requests);
- }
+ http_init();
- curlm = curl_multi_init();
- if (curlm == NULL) {
- fprintf(stderr, "Error creating curl multi handle.\n");
- return 1;
- }
-#endif
-
- if (getenv("GIT_SSL_NO_VERIFY"))
- curl_ssl_verify = 0;
-
- ssl_cert = getenv("GIT_SSL_CERT");
-#if LIBCURL_VERSION_NUM >= 0x070902
- ssl_key = getenv("GIT_SSL_KEY");
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- ssl_capath = getenv("GIT_SSL_CAPATH");
-#endif
- ssl_cainfo = getenv("GIT_SSL_CAINFO");
-
- low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
- if (low_speed_limit != NULL)
- curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
- low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
- if (low_speed_time != NULL)
- curl_low_speed_time = strtol(low_speed_time, NULL, 10);
-
- git_config(http_options);
-
- if (curl_ssl_verify == -1)
- curl_ssl_verify = 1;
-
-#ifdef USE_CURL_MULTI
- if (max_requests < 1)
- max_requests = DEFAULT_MAX_REQUESTS;
-#endif
-
- pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
- no_range_header = curl_slist_append(no_range_header, "Range:");
-
-#ifndef NO_CURL_EASY_DUPHANDLE
- curl_default = get_curl_handle();
-#endif
alt = xmalloc(sizeof(*alt));
alt->base = url;
@@ -1397,30 +950,9 @@ int main(int argc, char **argv)
if (pull(commit_id))
rc = 1;
- curl_slist_free_all(pragma_header);
curl_slist_free_all(no_pragma_header);
- curl_slist_free_all(no_range_header);
-#ifndef NO_CURL_EASY_DUPHANDLE
- curl_easy_cleanup(curl_default);
-#endif
- slot = active_queue_head;
- while (slot != NULL) {
- if (slot->in_use) {
- if (get_verbosely) {
- curl_easy_getinfo(slot->curl,
- CURLINFO_EFFECTIVE_URL,
- &wait_url);
- fprintf(stderr, "Waiting for %s\n", wait_url);
- }
- run_active_slot(slot);
- }
- if (slot->curl != NULL)
- curl_easy_cleanup(slot->curl);
- slot = slot->next;
- }
-#ifdef USE_CURL_MULTI
- curl_multi_cleanup(curlm);
-#endif
- curl_global_cleanup();
+
+ http_cleanup();
+
return rc;
}
diff --git a/http-push.c b/http-push.c
index 8866189..afdcd8b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -4,30 +4,15 @@
#include "fetch.h"
#include "tag.h"
#include "blob.h"
+#include "http.h"
+
+#ifdef USE_CURL_MULTI
-#include <curl/curl.h>
-#include <curl/easy.h>
#include <expat.h>
static const char http_push_usage[] =
"git-http-push [--complete] [--force] [--verbose] <url> <ref> [<ref>...]\n";
-#if LIBCURL_VERSION_NUM >= 0x070908
-#define USE_CURL_MULTI
-#define DEFAULT_MAX_REQUESTS 5
-#endif
-
-#if LIBCURL_VERSION_NUM < 0x070704
-#define curl_global_cleanup() do { /* nothing */ } while(0)
-#endif
-#if LIBCURL_VERSION_NUM < 0x070800
-#define curl_global_init(a) do { /* nothing */ } while(0)
-#endif
-
-#if LIBCURL_VERSION_NUM < 0x070c04
-#define NO_CURL_EASY_DUPHANDLE
-#endif
-
#ifndef XML_STATUS_OK
enum XML_Status {
XML_STATUS_OK = 1,
@@ -52,34 +37,17 @@ enum XML_Status {
#define LOCK_TIME 600
#define LOCK_REFRESH 30
-static int active_requests = 0;
-static int data_received;
static int pushing = 0;
static int aborted = 0;
static char remote_dir_exists[256];
-#ifdef USE_CURL_MULTI
-static int max_requests = -1;
-static CURLM *curlm;
-#endif
-#ifndef NO_CURL_EASY_DUPHANDLE
-static CURL *curl_default;
-#endif
static struct curl_slist *no_pragma_header;
static struct curl_slist *default_headers;
-static char curl_errorstr[CURL_ERROR_SIZE];
static int push_verbosely = 0;
static int push_all = 0;
static int force_all = 0;
-struct buffer
-{
- size_t posn;
- size_t size;
- void *buffer;
-};
-
struct repo
{
char *url;
@@ -122,31 +90,7 @@ struct transfer_request
struct transfer_request *next;
};
-struct active_request_slot
-{
- CURL *curl;
- FILE *local;
- int in_use;
- int done;
- CURLcode curl_result;
- long http_code;
- struct active_request_slot *next;
-};
-
static struct transfer_request *request_queue_head = NULL;
-static struct active_request_slot *active_queue_head = NULL;
-
-static int curl_ssl_verify = -1;
-static char *ssl_cert = NULL;
-#if LIBCURL_VERSION_NUM >= 0x070902
-static char *ssl_key = NULL;
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
-static char *ssl_capath = NULL;
-#endif
-static char *ssl_cainfo = NULL;
-static long curl_low_speed_limit = -1;
-static long curl_low_speed_time = -1;
struct active_lock
{
@@ -174,260 +118,14 @@ struct lockprop
int lock_exclusive_write;
};
-static int http_options(const char *var, const char *value)
-{
- if (!strcmp("http.sslverify", var)) {
- if (curl_ssl_verify == -1) {
- curl_ssl_verify = git_config_bool(var, value);
- }
- return 0;
- }
-
- if (!strcmp("http.sslcert", var)) {
- if (ssl_cert == NULL) {
- ssl_cert = xmalloc(strlen(value)+1);
- strcpy(ssl_cert, value);
- }
- return 0;
- }
-#if LIBCURL_VERSION_NUM >= 0x070902
- if (!strcmp("http.sslkey", var)) {
- if (ssl_key == NULL) {
- ssl_key = xmalloc(strlen(value)+1);
- strcpy(ssl_key, value);
- }
- return 0;
- }
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- if (!strcmp("http.sslcapath", var)) {
- if (ssl_capath == NULL) {
- ssl_capath = xmalloc(strlen(value)+1);
- strcpy(ssl_capath, value);
- }
- return 0;
- }
-#endif
- if (!strcmp("http.sslcainfo", var)) {
- if (ssl_cainfo == NULL) {
- ssl_cainfo = xmalloc(strlen(value)+1);
- strcpy(ssl_cainfo, value);
- }
- return 0;
- }
+static void finish_request(struct transfer_request *request);
-#ifdef USE_CURL_MULTI
- if (!strcmp("http.maxrequests", var)) {
- if (max_requests == -1)
- max_requests = git_config_int(var, value);
- return 0;
- }
-#endif
-
- if (!strcmp("http.lowspeedlimit", var)) {
- if (curl_low_speed_limit == -1)
- curl_low_speed_limit = (long)git_config_int(var, value);
- return 0;
- }
- if (!strcmp("http.lowspeedtime", var)) {
- if (curl_low_speed_time == -1)
- curl_low_speed_time = (long)git_config_int(var, value);
- return 0;
- }
-
- /* Fall back on the default ones */
- return git_default_config(var, value);
-}
-
-static size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb,
- struct buffer *buffer)
+static void process_response(void *callback_data)
{
- size_t size = eltsize * nmemb;
- if (size > buffer->size - buffer->posn)
- size = buffer->size - buffer->posn;
- memcpy(ptr, buffer->buffer + buffer->posn, size);
- buffer->posn += size;
- return size;
-}
-
-static size_t fwrite_buffer_dynamic(const void *ptr, size_t eltsize,
- size_t nmemb, struct buffer *buffer)
-{
- size_t size = eltsize * nmemb;
- if (size > buffer->size - buffer->posn) {
- buffer->size = buffer->size * 3 / 2;
- if (buffer->size < buffer->posn + size)
- buffer->size = buffer->posn + size;
- buffer->buffer = xrealloc(buffer->buffer, buffer->size);
- }
- memcpy(buffer->buffer + buffer->posn, ptr, size);
- buffer->posn += size;
- data_received++;
- return size;
-}
+ struct transfer_request *request =
+ (struct transfer_request *)callback_data;
-static size_t fwrite_null(const void *ptr, size_t eltsize,
- size_t nmemb, struct buffer *buffer)
-{
- data_received++;
- return eltsize * nmemb;
-}
-
-#ifdef USE_CURL_MULTI
-static void process_curl_messages(void);
-static void process_request_queue(void);
-#endif
-
-static CURL* get_curl_handle(void)
-{
- CURL* result = curl_easy_init();
-
- curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
-#if LIBCURL_VERSION_NUM >= 0x070907
- curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
-#endif
-
- if (ssl_cert != NULL)
- curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
-#if LIBCURL_VERSION_NUM >= 0x070902
- if (ssl_key != NULL)
- curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- if (ssl_capath != NULL)
- curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
-#endif
- if (ssl_cainfo != NULL)
- curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
- curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
-
- if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
- curl_low_speed_limit);
- curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
- curl_low_speed_time);
- }
-
- return result;
-}
-
-static struct active_request_slot *get_active_slot(void)
-{
- struct active_request_slot *slot = active_queue_head;
- struct active_request_slot *newslot;
-
-#ifdef USE_CURL_MULTI
- int num_transfers;
-
- /* Wait for a slot to open up if the queue is full */
- while (active_requests >= max_requests) {
- curl_multi_perform(curlm, &num_transfers);
- if (num_transfers < active_requests) {
- process_curl_messages();
- }
- }
-#endif
-
- while (slot != NULL && slot->in_use) {
- slot = slot->next;
- }
- if (slot == NULL) {
- newslot = xmalloc(sizeof(*newslot));
- newslot->curl = NULL;
- newslot->in_use = 0;
- newslot->next = NULL;
-
- slot = active_queue_head;
- if (slot == NULL) {
- active_queue_head = newslot;
- } else {
- while (slot->next != NULL) {
- slot = slot->next;
- }
- slot->next = newslot;
- }
- slot = newslot;
- }
-
- if (slot->curl == NULL) {
-#ifdef NO_CURL_EASY_DUPHANDLE
- slot->curl = get_curl_handle();
-#else
- slot->curl = curl_easy_duphandle(curl_default);
-#endif
- }
-
- active_requests++;
- slot->in_use = 1;
- slot->done = 0;
- slot->local = NULL;
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, default_headers);
- curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
-
- return slot;
-}
-
-static int start_active_slot(struct active_request_slot *slot)
-{
-#ifdef USE_CURL_MULTI
- CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
-
- if (curlm_result != CURLM_OK &&
- curlm_result != CURLM_CALL_MULTI_PERFORM) {
- active_requests--;
- slot->in_use = 0;
- return 0;
- }
-#endif
- return 1;
-}
-
-static void run_active_slot(struct active_request_slot *slot)
-{
-#ifdef USE_CURL_MULTI
- int num_transfers;
- long last_pos = 0;
- long current_pos;
- fd_set readfds;
- fd_set writefds;
- fd_set excfds;
- int max_fd;
- struct timeval select_timeout;
- CURLMcode curlm_result;
-
- while (!slot->done) {
- data_received = 0;
- do {
- curlm_result = curl_multi_perform(curlm,
- &num_transfers);
- } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
- if (num_transfers < active_requests) {
- process_curl_messages();
- process_request_queue();
- }
-
- if (!data_received && slot->local != NULL) {
- current_pos = ftell(slot->local);
- if (current_pos > last_pos)
- data_received++;
- last_pos = current_pos;
- }
-
- if (!slot->done && !data_received) {
- max_fd = 0;
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&excfds);
- select_timeout.tv_sec = 0;
- select_timeout.tv_usec = 50000;
- select(max_fd, &readfds, &writefds,
- &excfds, &select_timeout);
- }
- }
-#else
- slot->curl_result = curl_easy_perform(slot->curl);
- active_requests--;
-#endif
+ finish_request(request);
}
static void start_check(struct transfer_request *request)
@@ -447,6 +145,8 @@ static void start_check(struct transfer_
strcpy(posn, hex + 2);
slot = get_active_slot();
+ slot->callback_func = process_response;
+ slot->callback_data = request;
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
@@ -476,6 +176,8 @@ static void start_mkcol(struct transfer_
strcpy(posn, "/");
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_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
@@ -553,6 +255,8 @@ static void start_put(struct transfer_re
strcpy(posn, request->lock->token);
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.size);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
@@ -578,6 +282,8 @@ static void start_move(struct transfer_r
struct curl_slist *dav_headers = NULL;
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);
dav_headers = curl_slist_append(dav_headers, request->dest);
@@ -725,48 +431,7 @@ static void release_request(struct trans
free(request);
}
-#ifdef USE_CURL_MULTI
-static void process_curl_messages(void)
-{
- int num_messages;
- struct active_request_slot *slot;
- struct transfer_request *request = NULL;
- CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
-
- while (curl_message != NULL) {
- if (curl_message->msg == CURLMSG_DONE) {
- slot = active_queue_head;
- while (slot != NULL &&
- slot->curl != curl_message->easy_handle)
- slot = slot->next;
- if (slot != NULL) {
- int curl_result = curl_message->data.result;
- curl_multi_remove_handle(curlm, slot->curl);
- active_requests--;
- slot->done = 1;
- slot->in_use = 0;
- slot->curl_result = curl_result;
- curl_easy_getinfo(slot->curl,
- CURLINFO_HTTP_CODE,
- &slot->http_code);
- request = request_queue_head;
- while (request != NULL &&
- request->slot != slot)
- request = request->next;
- if (request != NULL)
- finish_request(request);
- } else {
- fprintf(stderr, "Received DONE message for unknown request!\n");
- }
- } else {
- fprintf(stderr, "Unknown CURL message received: %d\n",
- (int)curl_message->msg);
- }
- curl_message = curl_multi_info_read(curlm, &num_messages);
- }
-}
-
-static void process_request_queue(void)
+void fill_active_slots(void)
{
struct transfer_request *request = request_queue_head;
struct active_request_slot *slot = active_queue_head;
@@ -797,20 +462,6 @@ static void process_request_queue(void)
slot = slot->next;
}
}
-#endif
-
-static void process_waiting_requests(void)
-{
- struct active_request_slot *slot = active_queue_head;
-
- while (slot != NULL)
- if (slot->in_use) {
- run_active_slot(slot);
- slot = active_queue_head;
- } else {
- slot = slot->next;
- }
-}
static void add_request(unsigned char *sha1, struct active_lock *lock)
{
@@ -834,10 +485,9 @@ static void add_request(unsigned char *s
request->state = NEED_CHECK;
request->next = request_queue_head;
request_queue_head = request;
-#ifdef USE_CURL_MULTI
- process_request_queue();
- process_curl_messages();
-#endif
+
+ fill_active_slots();
+ step_active_slots();
}
static int fetch_index(unsigned char *sha1)
@@ -963,8 +613,7 @@ static int fetch_indices(void)
slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
if (start_active_slot(slot)) {
@@ -1068,8 +717,7 @@ int fetch_ref(char *ref, unsigned char *
url = quote_ref_url(base, ref);
slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ 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)) {
@@ -1261,8 +909,7 @@ static struct active_lock *lock_remote(c
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ 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);
@@ -1390,8 +1037,7 @@ static int check_locking(void)
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
- fwrite_buffer_dynamic);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
@@ -1560,8 +1206,6 @@ static int update_remote(unsigned char *
int main(int argc, char **argv)
{
- struct active_request_slot *slot;
- struct active_request_slot *next_slot;
struct transfer_request *request;
struct transfer_request *next_request;
int nr_refspec = 0;
@@ -1576,8 +1220,6 @@ int main(int argc, char **argv)
unsigned char remote_sha1[20];
struct active_lock *remote_lock;
char *remote_path = NULL;
- char *low_speed_limit;
- char *low_speed_time;
int rc = 0;
int i;
@@ -1617,50 +1259,7 @@ int main(int argc, char **argv)
memset(remote_dir_exists, 0, 256);
- curl_global_init(CURL_GLOBAL_ALL);
-
-#ifdef USE_CURL_MULTI
- {
- char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
- if (http_max_requests != NULL)
- max_requests = atoi(http_max_requests);
- }
-
- curlm = curl_multi_init();
- if (curlm == NULL) {
- fprintf(stderr, "Error creating curl multi handle.\n");
- return 1;
- }
-#endif
-
- if (getenv("GIT_SSL_NO_VERIFY"))
- curl_ssl_verify = 0;
-
- ssl_cert = getenv("GIT_SSL_CERT");
-#if LIBCURL_VERSION_NUM >= 0x070902
- ssl_key = getenv("GIT_SSL_KEY");
-#endif
-#if LIBCURL_VERSION_NUM >= 0x070908
- ssl_capath = getenv("GIT_SSL_CAPATH");
-#endif
- ssl_cainfo = getenv("GIT_SSL_CAINFO");
-
- low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
- if (low_speed_limit != NULL)
- curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
- low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
- if (low_speed_time != NULL)
- curl_low_speed_time = strtol(low_speed_time, NULL, 10);
-
- git_config(http_options);
-
- if (curl_ssl_verify == -1)
- curl_ssl_verify = 1;
-
-#ifdef USE_CURL_MULTI
- if (max_requests < 1)
- max_requests = DEFAULT_MAX_REQUESTS;
-#endif
+ http_init();
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
default_headers = curl_slist_append(default_headers, "Range:");
@@ -1669,10 +1268,6 @@ int main(int argc, char **argv)
default_headers = curl_slist_append(default_headers,
"Pragma: no-cache");
-#ifndef NO_CURL_EASY_DUPHANDLE
- curl_default = get_curl_handle();
-#endif
-
/* Verify DAV compliance/lock support */
if (check_locking() != 0) {
fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
@@ -1766,13 +1361,13 @@ int main(int argc, char **argv)
fetch_indices();
get_delta(push_all ? NULL : remote_sha1,
local_object, remote_lock);
- process_waiting_requests();
+ finish_all_active_slots();
/* Push missing objects to remote, this would be a
convenient time to pack them first if appropriate. */
pushing = 1;
- process_request_queue();
- process_waiting_requests();
+ fill_active_slots();
+ finish_all_active_slots();
/* Update the remote branch if all went well */
if (do_remote_update) {
@@ -1802,14 +1397,7 @@ int main(int argc, char **argv)
curl_slist_free_all(no_pragma_header);
curl_slist_free_all(default_headers);
- slot = active_queue_head;
- while (slot != NULL) {
- next_slot = slot->next;
- if (slot->curl != NULL)
- curl_easy_cleanup(slot->curl);
- free(slot);
- slot = next_slot;
- }
+ http_cleanup();
request = request_queue_head;
while (request != NULL) {
@@ -1818,12 +1406,12 @@ int main(int argc, char **argv)
request = next_request;
}
-#ifndef NO_CURL_EASY_DUPHANDLE
- curl_easy_cleanup(curl_default);
-#endif
-#ifdef USE_CURL_MULTI
- curl_multi_cleanup(curlm);
-#endif
- curl_global_cleanup();
return rc;
}
+#else /* ifdef USE_CURL_MULTI */
+int main(int argc, char **argv)
+{
+ fprintf(stderr, "http-push requires curl 7.9.8 or higher.\n");
+ return 1;
+}
+#endif
diff --git a/http.c b/http.c
new file mode 100644
index 0000000..470b56e
--- /dev/null
+++ b/http.c
@@ -0,0 +1,443 @@
+#include "http.h"
+
+int data_received;
+int active_requests = 0;
+
+#ifdef USE_CURL_MULTI
+int max_requests = -1;
+CURLM *curlm;
+#endif
+#ifndef NO_CURL_EASY_DUPHANDLE
+CURL *curl_default;
+#endif
+char curl_errorstr[CURL_ERROR_SIZE];
+
+int curl_ssl_verify = -1;
+char *ssl_cert = NULL;
+#if LIBCURL_VERSION_NUM >= 0x070902
+char *ssl_key = NULL;
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+char *ssl_capath = NULL;
+#endif
+char *ssl_cainfo = NULL;
+long curl_low_speed_limit = -1;
+long curl_low_speed_time = -1;
+
+struct curl_slist *pragma_header;
+struct curl_slist *no_range_header;
+
+struct active_request_slot *active_queue_head = NULL;
+
+size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb,
+ struct buffer *buffer)
+{
+ size_t size = eltsize * nmemb;
+ if (size > buffer->size - buffer->posn)
+ size = buffer->size - buffer->posn;
+ memcpy(ptr, buffer->buffer + buffer->posn, size);
+ buffer->posn += size;
+ return size;
+}
+
+size_t fwrite_buffer(const void *ptr, size_t eltsize,
+ size_t nmemb, struct buffer *buffer)
+{
+ size_t size = eltsize * nmemb;
+ if (size > buffer->size - buffer->posn) {
+ buffer->size = buffer->size * 3 / 2;
+ if (buffer->size < buffer->posn + size)
+ buffer->size = buffer->posn + size;
+ buffer->buffer = xrealloc(buffer->buffer, buffer->size);
+ }
+ memcpy(buffer->buffer + buffer->posn, ptr, size);
+ buffer->posn += size;
+ data_received++;
+ return size;
+}
+
+size_t fwrite_null(const void *ptr, size_t eltsize,
+ size_t nmemb, struct buffer *buffer)
+{
+ data_received++;
+ return eltsize * nmemb;
+}
+
+static void finish_active_slot(struct active_request_slot *slot);
+
+#ifdef USE_CURL_MULTI
+static void process_curl_messages(void)
+{
+ int num_messages;
+ struct active_request_slot *slot;
+ CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
+
+ while (curl_message != NULL) {
+ if (curl_message->msg == CURLMSG_DONE) {
+ int curl_result = curl_message->data.result;
+ slot = active_queue_head;
+ while (slot != NULL &&
+ slot->curl != curl_message->easy_handle)
+ slot = slot->next;
+ if (slot != NULL) {
+ curl_multi_remove_handle(curlm, slot->curl);
+ slot->curl_result = curl_result;
+ finish_active_slot(slot);
+ } else {
+ fprintf(stderr, "Received DONE message for unknown request!\n");
+ }
+ } else {
+ fprintf(stderr, "Unknown CURL message received: %d\n",
+ (int)curl_message->msg);
+ }
+ curl_message = curl_multi_info_read(curlm, &num_messages);
+ }
+}
+#endif
+
+static int http_options(const char *var, const char *value)
+{
+ if (!strcmp("http.sslverify", var)) {
+ if (curl_ssl_verify == -1) {
+ curl_ssl_verify = git_config_bool(var, value);
+ }
+ return 0;
+ }
+
+ if (!strcmp("http.sslcert", var)) {
+ if (ssl_cert == NULL) {
+ ssl_cert = xmalloc(strlen(value)+1);
+ strcpy(ssl_cert, value);
+ }
+ return 0;
+ }
+#if LIBCURL_VERSION_NUM >= 0x070902
+ if (!strcmp("http.sslkey", var)) {
+ if (ssl_key == NULL) {
+ ssl_key = xmalloc(strlen(value)+1);
+ strcpy(ssl_key, value);
+ }
+ return 0;
+ }
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+ if (!strcmp("http.sslcapath", var)) {
+ if (ssl_capath == NULL) {
+ ssl_capath = xmalloc(strlen(value)+1);
+ strcpy(ssl_capath, value);
+ }
+ return 0;
+ }
+#endif
+ if (!strcmp("http.sslcainfo", var)) {
+ if (ssl_cainfo == NULL) {
+ ssl_cainfo = xmalloc(strlen(value)+1);
+ strcpy(ssl_cainfo, value);
+ }
+ return 0;
+ }
+
+#ifdef USE_CURL_MULTI
+ if (!strcmp("http.maxrequests", var)) {
+ if (max_requests == -1)
+ max_requests = git_config_int(var, value);
+ return 0;
+ }
+#endif
+
+ if (!strcmp("http.lowspeedlimit", var)) {
+ if (curl_low_speed_limit == -1)
+ curl_low_speed_limit = (long)git_config_int(var, value);
+ return 0;
+ }
+ if (!strcmp("http.lowspeedtime", var)) {
+ if (curl_low_speed_time == -1)
+ curl_low_speed_time = (long)git_config_int(var, value);
+ return 0;
+ }
+
+ /* Fall back on the default ones */
+ return git_default_config(var, value);
+}
+
+void http_init(void)
+{
+ char *low_speed_limit;
+ char *low_speed_time;
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
+ no_range_header = curl_slist_append(no_range_header, "Range:");
+
+#ifdef USE_CURL_MULTI
+ {
+ char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
+ if (http_max_requests != NULL)
+ max_requests = atoi(http_max_requests);
+ }
+
+ curlm = curl_multi_init();
+ if (curlm == NULL) {
+ fprintf(stderr, "Error creating curl multi handle.\n");
+ exit(1);
+ }
+#endif
+
+ if (getenv("GIT_SSL_NO_VERIFY"))
+ curl_ssl_verify = 0;
+
+ ssl_cert = getenv("GIT_SSL_CERT");
+#if LIBCURL_VERSION_NUM >= 0x070902
+ ssl_key = getenv("GIT_SSL_KEY");
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+ ssl_capath = getenv("GIT_SSL_CAPATH");
+#endif
+ ssl_cainfo = getenv("GIT_SSL_CAINFO");
+
+ low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
+ if (low_speed_limit != NULL)
+ curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
+ low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
+ if (low_speed_time != NULL)
+ curl_low_speed_time = strtol(low_speed_time, NULL, 10);
+
+ git_config(http_options);
+
+ if (curl_ssl_verify == -1)
+ curl_ssl_verify = 1;
+
+#ifdef USE_CURL_MULTI
+ if (max_requests < 1)
+ max_requests = DEFAULT_MAX_REQUESTS;
+#endif
+
+#ifndef NO_CURL_EASY_DUPHANDLE
+ curl_default = get_curl_handle();
+#endif
+}
+
+void http_cleanup(void)
+{
+ struct active_request_slot *slot = active_queue_head;
+#ifdef USE_CURL_MULTI
+ char *wait_url;
+ CURLMcode curlm_result;
+#endif
+
+ while (slot != NULL) {
+#ifdef USE_CURL_MULTI
+ if (slot->in_use) {
+ curl_easy_getinfo(slot->curl,
+ CURLINFO_EFFECTIVE_URL,
+ &wait_url);
+ fprintf(stderr, "Waiting for %s\n", wait_url);
+ run_active_slot(slot);
+ }
+#endif
+ if (slot->curl != NULL)
+ curl_easy_cleanup(slot->curl);
+ slot = slot->next;
+ }
+
+#ifndef NO_CURL_EASY_DUPHANDLE
+ curl_easy_cleanup(curl_default);
+#endif
+
+#ifdef USE_CURL_MULTI
+ curl_multi_cleanup(curlm);
+#endif
+ curl_global_cleanup();
+
+}
+
+static CURL* get_curl_handle(void)
+{
+ CURL* result = curl_easy_init();
+
+ curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
+#if LIBCURL_VERSION_NUM >= 0x070907
+ curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+#endif
+
+ if (ssl_cert != NULL)
+ curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
+#if LIBCURL_VERSION_NUM >= 0x070902
+ if (ssl_key != NULL)
+ curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+ if (ssl_capath != NULL)
+ curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
+#endif
+ if (ssl_cainfo != NULL)
+ curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
+ curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
+
+ if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
+ curl_low_speed_limit);
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
+ curl_low_speed_time);
+ }
+
+ curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
+
+ return result;
+}
+
+struct active_request_slot *get_active_slot(void)
+{
+ struct active_request_slot *slot = active_queue_head;
+ struct active_request_slot *newslot;
+
+#ifdef USE_CURL_MULTI
+ int num_transfers;
+
+ /* Wait for a slot to open up if the queue is full */
+ while (active_requests >= max_requests) {
+ curl_multi_perform(curlm, &num_transfers);
+ if (num_transfers < active_requests) {
+ process_curl_messages();
+ }
+ }
+#endif
+
+ while (slot != NULL && slot->in_use) {
+ slot = slot->next;
+ }
+ if (slot == NULL) {
+ newslot = xmalloc(sizeof(*newslot));
+ newslot->curl = NULL;
+ newslot->in_use = 0;
+ newslot->next = NULL;
+
+ slot = active_queue_head;
+ if (slot == NULL) {
+ active_queue_head = newslot;
+ } else {
+ while (slot->next != NULL) {
+ slot = slot->next;
+ }
+ slot->next = newslot;
+ }
+ slot = newslot;
+ }
+
+ if (slot->curl == NULL) {
+#ifdef NO_CURL_EASY_DUPHANDLE
+ slot->curl = get_curl_handle();
+#else
+ slot->curl = curl_easy_duphandle(curl_default);
+#endif
+ }
+
+ active_requests++;
+ slot->in_use = 1;
+ slot->local = NULL;
+ slot->callback_data = NULL;
+ slot->callback_func = NULL;
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
+ curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+
+ return slot;
+}
+
+int start_active_slot(struct active_request_slot *slot)
+{
+#ifdef USE_CURL_MULTI
+ CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
+
+ if (curlm_result != CURLM_OK &&
+ curlm_result != CURLM_CALL_MULTI_PERFORM) {
+ active_requests--;
+ slot->in_use = 0;
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+#ifdef USE_CURL_MULTI
+void step_active_slots(void)
+{
+ int num_transfers;
+ CURLMcode curlm_result;
+
+ do {
+ curlm_result = curl_multi_perform(curlm, &num_transfers);
+ } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
+ if (num_transfers < active_requests) {
+ process_curl_messages();
+ fill_active_slots();
+ }
+}
+#endif
+
+void run_active_slot(struct active_request_slot *slot)
+{
+#ifdef USE_CURL_MULTI
+ long last_pos = 0;
+ long current_pos;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set excfds;
+ int max_fd;
+ struct timeval select_timeout;
+
+ while (slot->in_use) {
+ data_received = 0;
+ step_active_slots();
+
+ if (!data_received && slot->local != NULL) {
+ current_pos = ftell(slot->local);
+ if (current_pos > last_pos)
+ data_received++;
+ last_pos = current_pos;
+ }
+
+ if (slot->in_use && !data_received) {
+ max_fd = 0;
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&excfds);
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = 50000;
+ select(max_fd, &readfds, &writefds,
+ &excfds, &select_timeout);
+ }
+ }
+#else
+ while (slot->in_use) {
+ slot->curl_result = curl_easy_perform(slot->curl);
+ finish_active_slot(slot);
+ }
+#endif
+}
+
+static void finish_active_slot(struct active_request_slot *slot)
+{
+ active_requests--;
+ slot->in_use = 0;
+ curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
+
+ /* Run callback if appropriate */
+ if (slot->callback_func != NULL) {
+ slot->callback_func(slot->callback_data);
+ }
+}
+
+void finish_all_active_slots(void)
+{
+ struct active_request_slot *slot = active_queue_head;
+
+ while (slot != NULL)
+ if (slot->in_use) {
+ run_active_slot(slot);
+ slot = active_queue_head;
+ } else {
+ slot = slot->next;
+ }
+}
diff --git a/http.h b/http.h
new file mode 100644
index 0000000..ed4ea33
--- /dev/null
+++ b/http.h
@@ -0,0 +1,95 @@
+#ifndef HTTP_H
+#define HTTP_H
+
+#include "cache.h"
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#if LIBCURL_VERSION_NUM >= 0x070908
+#define USE_CURL_MULTI
+#define DEFAULT_MAX_REQUESTS 5
+#endif
+
+#if LIBCURL_VERSION_NUM < 0x070704
+#define curl_global_cleanup() do { /* nothing */ } while(0)
+#endif
+#if LIBCURL_VERSION_NUM < 0x070800
+#define curl_global_init(a) do { /* nothing */ } while(0)
+#endif
+
+#if LIBCURL_VERSION_NUM < 0x070c04
+#define NO_CURL_EASY_DUPHANDLE
+#endif
+
+struct active_request_slot
+{
+ CURL *curl;
+ FILE *local;
+ int in_use;
+ CURLcode curl_result;
+ long http_code;
+ void *callback_data;
+ void (*callback_func)(void *data);
+ struct active_request_slot *next;
+};
+
+struct buffer
+{
+ size_t posn;
+ size_t size;
+ void *buffer;
+};
+
+/* Curl request read/write callbacks */
+extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb,
+ struct buffer *buffer);
+extern size_t fwrite_buffer(const void *ptr, size_t eltsize,
+ size_t nmemb, struct buffer *buffer);
+extern size_t fwrite_null(const void *ptr, size_t eltsize,
+ size_t nmemb, struct buffer *buffer);
+
+/* Slot lifecycle functions */
+extern struct active_request_slot *get_active_slot(void);
+extern int start_active_slot(struct active_request_slot *slot);
+extern void run_active_slot(struct active_request_slot *slot);
+extern void finish_all_active_slots(void);
+
+#ifdef USE_CURL_MULTI
+extern void fill_active_slots(void);
+extern void step_active_slots(void);
+#endif
+
+extern void http_init(void);
+extern void http_cleanup(void);
+
+extern int data_received;
+extern int active_requests;
+
+#ifdef USE_CURL_MULTI
+extern int max_requests;
+extern CURLM *curlm;
+#endif
+#ifndef NO_CURL_EASY_DUPHANDLE
+extern CURL *curl_default;
+#endif
+extern char curl_errorstr[CURL_ERROR_SIZE];
+
+extern int curl_ssl_verify;
+extern char *ssl_cert;
+#if LIBCURL_VERSION_NUM >= 0x070902
+extern char *ssl_key;
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+extern char *ssl_capath;
+#endif
+extern char *ssl_cainfo;
+extern long curl_low_speed_limit;
+extern long curl_low_speed_time;
+
+extern struct curl_slist *pragma_header;
+extern struct curl_slist *no_range_header;
+
+extern struct active_request_slot *active_queue_head;
+
+#endif /* HTTP_H */
---
0.99.9.GIT
^ permalink raw reply related
* [PATCH 3/5] Improve pack list response handling
From: Nick Hengeveld @ 2005-11-18 19:03 UTC (permalink / raw)
To: git
Better response handling for pack list requests - a 404 means we do have
the list but it happens to be empty.
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
http-fetch.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
applies-to: 8e27b8361908dda4ea5955f5ffe332b8cf09c0ec
20223d677b9d7291080acae9f9943aee90ee12ca
diff --git a/http-fetch.c b/http-fetch.c
index 53a7dbf..4353173 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -637,10 +637,18 @@ static int fetch_indices(struct alt_base
if (start_active_slot(slot)) {
run_active_slot(slot);
if (slot->curl_result != CURLE_OK) {
- free(buffer.buffer);
- return error("%s", curl_errorstr);
+ if (slot->http_code == 404) {
+ repo->got_indices = 1;
+ free(buffer.buffer);
+ return 0;
+ } else {
+ repo->got_indices = 0;
+ free(buffer.buffer);
+ return error("%s", curl_errorstr);
+ }
}
} else {
+ repo->got_indices = 0;
free(buffer.buffer);
return error("Unable to start request");
}
---
0.99.9.GIT
^ permalink raw reply related
* [PATCH 4/5] Improve XML parsing in http-push
From: Nick Hengeveld @ 2005-11-18 19:03 UTC (permalink / raw)
To: git
Improved XML parsing - replace specialized doc parser callbacks with generic
functions that track the parser context and use document-specific callbacks
to process that data.
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
http-push.c | 319 ++++++++++++++++++++++++++++++-----------------------------
1 files changed, 163 insertions(+), 156 deletions(-)
applies-to: 819a270f2d0479478cd34d90e5d764ffad88b9d5
61e23ac52c5276cdddc9dd4d0de444dfe1dde39d
diff --git a/http-push.c b/http-push.c
index afdcd8b..2932693 100644
--- a/http-push.c
+++ b/http-push.c
@@ -24,13 +24,28 @@ enum XML_Status {
#define RANGE_HEADER_SIZE 30
-/* DAV method names and request body templates */
+/* DAV methods */
#define DAV_LOCK "LOCK"
#define DAV_MKCOL "MKCOL"
#define DAV_MOVE "MOVE"
#define DAV_PROPFIND "PROPFIND"
#define DAV_PUT "PUT"
#define DAV_UNLOCK "UNLOCK"
+
+/* DAV lock flags */
+#define DAV_PROP_LOCKWR (1u << 0)
+#define DAV_PROP_LOCKEX (1u << 1)
+#define DAV_LOCK_OK (1u << 2)
+
+/* DAV XML properties */
+#define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry"
+#define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write"
+#define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive"
+#define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href"
+#define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout"
+#define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href"
+
+/* DAV request body templates */
#define PROPFIND_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>"
#define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n<D:owner>\n<D:href>mailto:%s</D:href>\n</D:owner>\n</D:lockinfo>"
@@ -92,14 +107,17 @@ struct transfer_request
static struct transfer_request *request_queue_head = NULL;
+struct xml_ctx
+{
+ char *name;
+ int len;
+ char *cdata;
+ void (*userFunc)(struct xml_ctx *ctx, int tag_closed);
+ void *userData;
+};
+
struct active_lock
{
- int ctx_activelock;
- int ctx_owner;
- int ctx_owner_href;
- int ctx_timeout;
- int ctx_locktoken;
- int ctx_locktoken_href;
char *url;
char *owner;
char *token;
@@ -108,16 +126,6 @@ struct active_lock
int refreshing;
};
-struct lockprop
-{
- int supported_lock;
- int lock_entry;
- int lock_scope;
- int lock_type;
- int lock_exclusive;
- int lock_exclusive_write;
-};
-
static void finish_request(struct transfer_request *request);
static void process_response(void *callback_data)
@@ -734,107 +742,101 @@ int fetch_ref(char *ref, unsigned char *
return 0;
}
-static void
-start_activelock_element(void *userData, const char *name, const char **atts)
+static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
{
- struct active_lock *lock = (struct active_lock *)userData;
+ int *lock_flags = (int *)ctx->userData;
- if (lock->ctx_activelock && !strcmp(name, "D:timeout"))
- lock->ctx_timeout = 1;
- else if (lock->ctx_owner && strstr(name, "href"))
- lock->ctx_owner_href = 1;
- else if (lock->ctx_activelock && strstr(name, "owner"))
- lock->ctx_owner = 1;
- else if (lock->ctx_locktoken && !strcmp(name, "D:href"))
- lock->ctx_locktoken_href = 1;
- else if (lock->ctx_activelock && !strcmp(name, "D:locktoken"))
- lock->ctx_locktoken = 1;
- else if (!strcmp(name, "D:activelock"))
- lock->ctx_activelock = 1;
+ if (tag_closed) {
+ if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) {
+ if ((*lock_flags & DAV_PROP_LOCKEX) &&
+ (*lock_flags & DAV_PROP_LOCKWR)) {
+ *lock_flags |= DAV_LOCK_OK;
+ }
+ *lock_flags &= DAV_LOCK_OK;
+ } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) {
+ *lock_flags |= DAV_PROP_LOCKWR;
+ } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) {
+ *lock_flags |= DAV_PROP_LOCKEX;
+ }
+ }
}
-static void
-end_activelock_element(void *userData, const char *name)
-{
- struct active_lock *lock = (struct active_lock *)userData;
-
- if (lock->ctx_timeout && !strcmp(name, "D:timeout")) {
- lock->ctx_timeout = 0;
- } else if (lock->ctx_owner_href && strstr(name, "href")) {
- lock->ctx_owner_href = 0;
- } else if (lock->ctx_owner && strstr(name, "owner")) {
- lock->ctx_owner = 0;
- } else if (lock->ctx_locktoken_href && !strcmp(name, "D:href")) {
- lock->ctx_locktoken_href = 0;
- } else if (lock->ctx_locktoken && !strcmp(name, "D:locktoken")) {
- lock->ctx_locktoken = 0;
- } else if (lock->ctx_activelock && !strcmp(name, "D:activelock")) {
- lock->ctx_activelock = 0;
+static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
+{
+ struct active_lock *lock = (struct active_lock *)ctx->userData;
+
+ if (tag_closed && ctx->cdata) {
+ if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
+ lock->owner = xmalloc(strlen(ctx->cdata) + 1);
+ strcpy(lock->owner, ctx->cdata);
+ } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
+ if (!strncmp(ctx->cdata, "Second-", 7))
+ lock->timeout =
+ strtol(ctx->cdata + 7, NULL, 10);
+ } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
+ if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
+ lock->token = xmalloc(strlen(ctx->cdata - 15));
+ strcpy(lock->token, ctx->cdata + 16);
+ }
+ }
}
}
static void
-activelock_cdata(void *userData, const XML_Char *s, int len)
+xml_start_tag(void *userData, const char *name, const char **atts)
{
- struct active_lock *lock = (struct active_lock *)userData;
- char *this = malloc(len+1);
- strncpy(this, s, len);
-
- if (lock->ctx_owner_href) {
- lock->owner = malloc(len+1);
- strcpy(lock->owner, this);
- } else if (lock->ctx_locktoken_href) {
- if (!strncmp(this, "opaquelocktoken:", 16)) {
- lock->token = malloc(len-15);
- strcpy(lock->token, this+16);
- }
- } else if (lock->ctx_timeout) {
- if (!strncmp(this, "Second-", 7))
- lock->timeout = strtol(this+7, NULL, 10);
+ struct xml_ctx *ctx = (struct xml_ctx *)userData;
+ const char *c = index(name, ':');
+ int new_len;
+
+ if (c == NULL)
+ c = name;
+ else
+ c++;
+
+ new_len = strlen(ctx->name) + strlen(c) + 2;
+
+ if (new_len > ctx->len) {
+ ctx->name = xrealloc(ctx->name, new_len);
+ ctx->len = new_len;
+ }
+ strcat(ctx->name, ".");
+ strcat(ctx->name, c);
+
+ if (ctx->cdata) {
+ free(ctx->cdata);
+ ctx->cdata = NULL;
}
- free(this);
+ ctx->userFunc(ctx, 0);
}
static void
-start_lockprop_element(void *userData, const char *name, const char **atts)
+xml_end_tag(void *userData, const char *name)
{
- struct lockprop *prop = (struct lockprop *)userData;
+ struct xml_ctx *ctx = (struct xml_ctx *)userData;
+ const char *c = index(name, ':');
+ char *ep;
- if (prop->lock_type && !strcmp(name, "D:write")) {
- if (prop->lock_exclusive) {
- prop->lock_exclusive_write = 1;
- }
- } else if (prop->lock_scope && !strcmp(name, "D:exclusive")) {
- prop->lock_exclusive = 1;
- } else if (prop->lock_entry) {
- if (!strcmp(name, "D:lockscope")) {
- prop->lock_scope = 1;
- } else if (!strcmp(name, "D:locktype")) {
- prop->lock_type = 1;
- }
- } else if (prop->supported_lock) {
- if (!strcmp(name, "D:lockentry")) {
- prop->lock_entry = 1;
- }
- } else if (!strcmp(name, "D:supportedlock")) {
- prop->supported_lock = 1;
- }
+ ctx->userFunc(ctx, 1);
+
+ if (c == NULL)
+ c = name;
+ else
+ c++;
+
+ ep = ctx->name + strlen(ctx->name) - strlen(c) - 1;
+ *ep = 0;
}
static void
-end_lockprop_element(void *userData, const char *name)
+xml_cdata(void *userData, const XML_Char *s, int len)
{
- struct lockprop *prop = (struct lockprop *)userData;
-
- if (!strcmp(name, "D:lockentry")) {
- prop->lock_entry = 0;
- prop->lock_scope = 0;
- prop->lock_type = 0;
- prop->lock_exclusive = 0;
- } else if (!strcmp(name, "D:supportedlock")) {
- prop->supported_lock = 0;
- }
+ struct xml_ctx *ctx = (struct xml_ctx *)userData;
+ if (ctx->cdata)
+ free(ctx->cdata);
+ ctx->cdata = xcalloc(len+1, 1);
+ strncpy(ctx->cdata, s, len);
}
static struct active_lock *lock_remote(char *file, long timeout)
@@ -847,10 +849,11 @@ static struct active_lock *lock_remote(c
char *url;
char *ep;
char timeout_header[25];
- struct active_lock *new_lock;
+ struct active_lock *new_lock = NULL;
XML_Parser parser = XML_ParserCreate(NULL);
enum XML_Status result;
struct curl_slist *dav_headers = NULL;
+ struct xml_ctx ctx;
url = xmalloc(strlen(remote->url) + strlen(file) + 1);
sprintf(url, "%s%s", remote->url, file);
@@ -894,12 +897,6 @@ static struct active_lock *lock_remote(c
in_buffer.posn = 0;
in_buffer.buffer = in_data;
- new_lock = xcalloc(1, sizeof(*new_lock));
- new_lock->owner = NULL;
- new_lock->token = NULL;
- new_lock->timeout = -1;
- new_lock->refreshing = 0;
-
sprintf(timeout_header, "Timeout: Second-%ld", timeout);
dav_headers = curl_slist_append(dav_headers, timeout_header);
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
@@ -915,40 +912,41 @@ static struct active_lock *lock_remote(c
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
+ new_lock = xcalloc(1, sizeof(*new_lock));
+ new_lock->owner = NULL;
+ new_lock->token = NULL;
+ new_lock->timeout = -1;
+ new_lock->refreshing = 0;
+
if (start_active_slot(slot)) {
run_active_slot(slot);
- if (slot->curl_result != CURLE_OK) {
- fprintf(stderr, "Got HTTP error %ld\n", slot->http_code);
- free(new_lock);
- free(url);
- free(out_data);
- free(in_data);
- return NULL;
+ if (slot->curl_result == CURLE_OK) {
+ ctx.name = xcalloc(10, 1);
+ ctx.len = 0;
+ ctx.cdata = NULL;
+ ctx.userFunc = handle_new_lock_ctx;
+ ctx.userData = new_lock;
+ XML_SetUserData(parser, &ctx);
+ XML_SetElementHandler(parser, xml_start_tag,
+ xml_end_tag);
+ XML_SetCharacterDataHandler(parser, xml_cdata);
+ result = XML_Parse(parser, in_buffer.buffer,
+ in_buffer.posn, 1);
+ free(ctx.name);
+ if (result != XML_STATUS_OK) {
+ fprintf(stderr, "XML error: %s\n",
+ XML_ErrorString(
+ XML_GetErrorCode(parser)));
+ new_lock->timeout = -1;
+ }
}
} else {
- free(new_lock);
- free(url);
- free(out_data);
- free(in_data);
fprintf(stderr, "Unable to start request\n");
- return NULL;
}
+ curl_slist_free_all(dav_headers);
free(out_data);
-
- XML_SetUserData(parser, new_lock);
- XML_SetElementHandler(parser, start_activelock_element,
- end_activelock_element);
- XML_SetCharacterDataHandler(parser, activelock_cdata);
- result = XML_Parse(parser, in_buffer.buffer, in_buffer.posn, 1);
free(in_data);
- if (result != XML_STATUS_OK) {
- fprintf(stderr, "%s", XML_ErrorString(
- XML_GetErrorCode(parser)));
- free(url);
- free(new_lock);
- return NULL;
- }
if (new_lock->token == NULL || new_lock->timeout <= 0) {
if (new_lock->token != NULL)
@@ -957,11 +955,12 @@ static struct active_lock *lock_remote(c
free(new_lock->owner);
free(url);
free(new_lock);
- return NULL;
+ new_lock = NULL;
+ } else {
+ new_lock->url = url;
+ new_lock->start_time = time(NULL);
}
- new_lock->url = url;
- new_lock->start_time = time(NULL);
return new_lock;
}
@@ -1000,13 +999,15 @@ static int unlock_remote(struct active_l
if (lock->owner != NULL)
free(lock->owner);
free(lock->url);
+/* Freeing the token causes a segfault...
free(lock->token);
+*/
free(lock);
return rc;
}
-static int check_locking(void)
+static int locking_available(void)
{
struct active_request_slot *slot;
struct buffer in_buffer;
@@ -1015,8 +1016,9 @@ static int check_locking(void)
char *out_data;
XML_Parser parser = XML_ParserCreate(NULL);
enum XML_Status result;
- struct lockprop supported_lock;
struct curl_slist *dav_headers = NULL;
+ struct xml_ctx ctx;
+ int lock_flags = 0;
out_buffer.size = strlen(PROPFIND_REQUEST) + strlen(remote->url) - 2;
out_data = xmalloc(out_buffer.size + 1);
@@ -1045,30 +1047,35 @@ static int check_locking(void)
if (start_active_slot(slot)) {
run_active_slot(slot);
- free(out_data);
- if (slot->curl_result != CURLE_OK) {
- free(in_buffer.buffer);
- return -1;
+ if (slot->curl_result == CURLE_OK) {
+ ctx.name = xcalloc(10, 1);
+ ctx.len = 0;
+ ctx.cdata = NULL;
+ ctx.userFunc = handle_lockprop_ctx;
+ ctx.userData = &lock_flags;
+ XML_SetUserData(parser, &ctx);
+ XML_SetElementHandler(parser, xml_start_tag,
+ xml_end_tag);
+ result = XML_Parse(parser, in_buffer.buffer,
+ in_buffer.posn, 1);
+ free(ctx.name);
+
+ if (result != XML_STATUS_OK) {
+ fprintf(stderr, "XML error: %s\n",
+ XML_ErrorString(
+ XML_GetErrorCode(parser)));
+ lock_flags = 0;
+ }
}
-
- XML_SetUserData(parser, &supported_lock);
- XML_SetElementHandler(parser, start_lockprop_element,
- end_lockprop_element);
- result = XML_Parse(parser, in_buffer.buffer, in_buffer.posn, 1);
- free(in_buffer.buffer);
- if (result != XML_STATUS_OK)
- return error("%s", XML_ErrorString(
- XML_GetErrorCode(parser)));
} else {
- free(out_data);
- free(in_buffer.buffer);
- return error("Unable to start request");
+ fprintf(stderr, "Unable to start request\n");
}
- if (supported_lock.lock_exclusive_write)
- return 0;
- else
- return 1;
+ free(out_data);
+ free(in_buffer.buffer);
+ curl_slist_free_all(dav_headers);
+
+ return lock_flags;
}
static int is_ancestor(unsigned char *sha1, struct commit *commit)
@@ -1269,7 +1276,7 @@ int main(int argc, char **argv)
"Pragma: no-cache");
/* Verify DAV compliance/lock support */
- if (check_locking() != 0) {
+ if (!locking_available()) {
fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
rc = 1;
goto cleanup;
---
0.99.9.GIT
^ permalink raw reply related
* [PATCH 5/5] http-push memory/fd cleanup
From: Nick Hengeveld @ 2005-11-18 19:03 UTC (permalink / raw)
To: git
Clean up memory and file descriptor usage
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
http-push.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
applies-to: 697c3fa609568c3befb803dd8a131814ca1fad6a
898a8d2e69916757f423a8bd487d97f19c06c1e0
diff --git a/http-push.c b/http-push.c
index 2932693..f3c92c9 100644
--- a/http-push.c
+++ b/http-push.c
@@ -165,6 +165,7 @@ static void start_check(struct transfer_
} else {
request->state = ABORTED;
free(request->url);
+ request->url = NULL;
}
}
@@ -198,6 +199,7 @@ static void start_mkcol(struct transfer_
} else {
request->state = ABORTED;
free(request->url);
+ request->url = NULL;
}
}
@@ -244,8 +246,6 @@ static void start_put(struct transfer_re
request->buffer.size = stream.total_out;
request->buffer.posn = 0;
- if (request->url != NULL)
- free(request->url);
request->url = xmalloc(strlen(remote->url) +
strlen(request->lock->token) + 51);
strcpy(request->url, remote->url);
@@ -281,6 +281,7 @@ static void start_put(struct transfer_re
} else {
request->state = ABORTED;
free(request->url);
+ request->url = NULL;
}
}
@@ -306,6 +307,7 @@ static void start_move(struct transfer_r
} else {
request->state = ABORTED;
free(request->url);
+ request->url = NULL;
}
}
@@ -370,6 +372,13 @@ static void finish_request(struct transf
if (request->headers != NULL)
curl_slist_free_all(request->headers);
+
+ /* URL is reused for MOVE after PUT */
+ if (request->state != RUN_PUT) {
+ free(request->url);
+ request->url = NULL;
+ }
+
if (request->state == RUN_HEAD) {
if (request->http_code == 404) {
request->state = NEED_PUSH;
@@ -435,7 +444,8 @@ static void release_request(struct trans
entry->next = entry->next->next;
}
- free(request->url);
+ if (request->url != NULL)
+ free(request->url);
free(request);
}
@@ -575,6 +585,7 @@ static int fetch_index(unsigned char *sh
}
} else {
free(url);
+ fclose(indexfile);
return error("Unable to start request");
}
---
0.99.9.GIT
^ permalink raw reply related
* Re: "make test" fails with current HEAD
From: Junio C Hamano @ 2005-11-18 19:13 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <7vwtj5lvvc.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Linus Torvalds <torvalds@osdl.org> writes:
>
>> Umm.. Why not just say "if the line after the 'diff' line doesn't start
>> with '@@ ', then it's a binary diff"?
>
> Thanks, that makes sense.
Maybe not; parse_single_patch would have eaten '@@ -' lines so
in practice that amounts to not checking anything at all.
Which is not a bad idea, though... That means we would treat
all empty patches as binary diffs, which is certainly simple,
but is it safe enough?
^ permalink raw reply
* git fetch --tags doesn't quite do what I expect
From: Tony Luck @ 2005-11-18 19:14 UTC (permalink / raw)
To: git
I've been doing some updating on my git scripts to make use of the features
that you have been working hard to put in (thank you). My script to update
my local "linus" branch from Linus' master branch at kernel.org had a simple
"git fetch linus" (with the appropriate[1] URL and Pull lines in
.git/refs/remotes/linus)
followed by an unholy piece of script that parsed the output from
"git-ls-remote --tags linus" to see if I had all the latest tags, and
get them if
I didn't.
Looking at the manual, I thought that I could just change the "git
fetch linus" to
be "git fetch --tags linus" and drop the script. But it appears that
with the "--tags"
argument the "fetch" will not fetch anything beyond the tagged commits (i.e.
at the moment v2.6.15-rc1) ... so I need both:
git fetch --tags linus
and
git fetch linus
one to get any new tags, and the other to fetch all the way up to "master".
Is this intended behaivour? If so, the "--tags" entry on the git-fetch(1) man
page needs a little extra text to say that --tags limits the fetch to only
commits reachable from the tags.
-Tony
[1] Contents:
URL: master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Pull: master:linus
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: Ismail Donmez @ 2005-11-18 19:27 UTC (permalink / raw)
To: git
In-Reply-To: <200511181926.10357.ismail@uludag.org.tr>
On Friday 18 November 2005 19:26, you wrote:
> On Friday 18 November 2005 18:33, you wrote:
> > Hi all,
> >
> > I am trying to parse git's rss feed and now xml parsers seems to choke on
> > it because of an error in the produced feed. Looking at
> > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=rs
> >s
> >
> > line 781 says :
> >
> > On Thu, 17 Nov 2005, David G\363mez wrote:<br/>
> >
> > which is part of the commit :
> > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=co
> >mm it;h=05b8b0fafd4cac75d205ecd5ad40992e2cc5934d
>
> Ok looks like this text is latin-1 encoded although xml is served as utf-8.
Any comments on this?
Regards,
ismail
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: Kay Sievers @ 2005-11-18 20:02 UTC (permalink / raw)
To: Ismail Donmez; +Cc: git
In-Reply-To: <200511182127.06958.ismail@uludag.org.tr>
On Fri, Nov 18, 2005 at 09:27:06PM +0200, Ismail Donmez wrote:
> On Friday 18 November 2005 19:26, you wrote:
> > On Friday 18 November 2005 18:33, you wrote:
> > > Hi all,
> > >
> > > I am trying to parse git's rss feed and now xml parsers seems to choke on
> > > it because of an error in the produced feed. Looking at
> > > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=rs
> > >s
> > >
> > > line 781 says :
> > >
> > > On Thu, 17 Nov 2005, David G\363mez wrote:<br/>
> > >
> > > which is part of the commit :
> > > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=co
> > >mm it;h=05b8b0fafd4cac75d205ecd5ad40992e2cc5934d
> >
> > Ok looks like this text is latin-1 encoded although xml is served as utf-8.
>
> Any comments on this?
Yes, convince the git maintainers, that it's incredibly stupid not to
enforce utf8 in commit messages. It makes absolutely zero sense in a
SCM, which merges forth and back between people around the world to
allow random encodings from the last century.
I still can't believe that this is a subject for discussion, in a
software developed in the year 2005.
With the next round of gitweb, I will substitute these caracters with
valid utf8, which will show up as invalid chars.
And git guys, please start to think again about your insane options,
that cause more harm than anything good.
Thanks,
Kay
^ permalink raw reply
* Re: git fetch --tags doesn't quite do what I expect
From: Junio C Hamano @ 2005-11-18 20:06 UTC (permalink / raw)
To: Tony Luck; +Cc: git
In-Reply-To: <12c511ca0511181114jf4ca3c0p195a128fa541b8f2@mail.gmail.com>
Tony Luck <tony.luck@gmail.com> writes:
> Is this intended behaivour? If so, the "--tags" entry on the
> git-fetch(1) man page needs a little extra text to say that
> --tags limits the fetch to only commits reachable from the
> tags.
I think both Linus (who did the initial implementation of "git
fetch --tags") and I are in "tags do not matter until you care"
camp, and the expected usage pattern is that you frequently do
"git fetch" or "git pull", but "git fetch --tags" is done only
every once in a while, just to give you known anchors to compare
against or specify a known bottom for log, whatchanged and
friends. The branch heads are necessary for your day to day
work, the tags are less essential. That is what I mean by "tags
do not matter until you care".
A tag usually points at somewhere in the commit chain leading to
branch heads [*1*], and if your branch heads are up to date,
"git fetch --tags" does not download anything other than the
tags themselves, finds the commits they point at are already
available and complete, and stops there.
Now it happens that "git fetch --tags" slurps commits you do not
yet have _if_ your branch heads are behind, because git barebone
Porcelain is designed to keep your object database complete
(i.e. it does not just fetch and store tags under refs/tags/
without making sure you have everything they connect to). What
you saw that is a side effect of the above design assumption.
I am not good at documenting things, so I'd appreciate if
somebody paraphrased the above and send it back to me in a patch
form to update the document ;-).
[Footnote]
*1* This is not necessarily true; tags can point at anything,
and indeed v1.0rc3 tag point at another tag and junio-gpg-tag
points at a freestanding blob. Even a tag pointing at a commit,
as Daniel suggested in
<Pine.LNX.4.64.0511041745480.25300@iabervon.org>
I could do the "pu" branch as a tag without exposing the actual
branch. Then that tag would point at a chain of commits not
connected to any branch head.
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: Ismail Donmez @ 2005-11-18 20:08 UTC (permalink / raw)
To: git
In-Reply-To: <20051118200217.GA2831@vrfy.org>
On Friday 18 November 2005 22:02, you wrote:
> On Fri, Nov 18, 2005 at 09:27:06PM +0200, Ismail Donmez wrote:
> > On Friday 18 November 2005 19:26, you wrote:
> > > On Friday 18 November 2005 18:33, you wrote:
> > > > Hi all,
> > > >
> > > > I am trying to parse git's rss feed and now xml parsers seems to
> > > > choke on it because of an error in the produced feed. Looking at
> > > > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;
> > > >a=rs s
> > > >
> > > > line 781 says :
> > > >
> > > > On Thu, 17 Nov 2005, David G\363mez wrote:<br/>
> > > >
> > > > which is part of the commit :
> > > > http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;
> > > >a=co mm it;h=05b8b0fafd4cac75d205ecd5ad40992e2cc5934d
> > >
> > > Ok looks like this text is latin-1 encoded although xml is served as
> > > utf-8.
> >
> > Any comments on this?
>
> Yes, convince the git maintainers, that it's incredibly stupid not to
> enforce utf8 in commit messages. It makes absolutely zero sense in a
> SCM, which merges forth and back between people around the world to
> allow random encodings from the last century.
>
I totally agree, utf8 should be default else the produced XML is wrong. Its
advertised as utf-8 but the content is latin1.
> With the next round of gitweb, I will substitute these caracters with
> valid utf8, which will show up as invalid chars.
When should we expect this? Currently I can't parse commit feed without
encoding to utf8 first.
> And git guys, please start to think again about your insane options,
> that cause more harm than anything good.
Can git maintainer(s) comment on this please?
Regards,
ismail
^ permalink raw reply
* Re: master has some toys
From: Junio C Hamano @ 2005-11-18 20:09 UTC (permalink / raw)
To: git
In-Reply-To: <7vveyrt6ms.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
I just had a small excitement finding out I did something right
and felt an urge to brag ;-).
> I am not so sure about forcing people upgrade, but we may end up
> deciding it is better not to have NO_MMAP as the default. If
> that turns out to be the case, I'd prefer to have something like
> this instead:
>
> diff --git a/Makefile b/Makefile
> index 7ce62e8..215abf0 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -213,6 +213,10 @@ endif
> ifeq ($(uname_O),Cygwin)
> NO_STRCASESTR = YesPlease
> NEEDS_LIBICONV = YesPlease
> + # There are conflicting reports about this.
> + # On some boxes NO_MMAP is needed, and not so elsewhere.
> + # Try uncommenting this if you see things break -- YMMV.
> + # NO_MMAP = YesPlease
> NO_IPV6 = YesPlease
> X = .exe
> endif
I did the above patch on top of "pu", which contained the patch
from Pavel Roskin and sent it out. Later I saved the message
from my mbox, went back to the "master" branch, whose Makefile
had the releveant part like this:
ifeq ($(uname_O),Cygwin)
NO_STRCASESTR = YesPlease
NEEDS_LIBICONV = YesPlease
NO_IPV6 = YesPlease
X = .exe
ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0
endif
Notice ALL_CFLAGS line? The patch does not apply cleanly and
usual e-mail patch application tool would have barfed; git-apply
would not allow any fuzz, and patch would have dropped a .rej
file.
However, I usually run "git-am" with --3way option enabled when
applying the e-mailed patches. After git-apply failed, it
noticed I am applying on top of a different blob, namely, the
Makefile from somewhere else (it reads the "index 7ce62e8"),
then fell back on 3-way merge and made a clean commit. Happy.
Back to day-job.
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: Linus Torvalds @ 2005-11-18 20:22 UTC (permalink / raw)
To: Ismail Donmez; +Cc: git
In-Reply-To: <200511182208.24248.ismail@uludag.org.tr>
On Fri, 18 Nov 2005, Ismail Donmez wrote:
>
> > And git guys, please start to think again about your insane options,
> > that cause more harm than anything good.
>
> Can git maintainer(s) comment on this please?
It's easy to say "just do the right thing", and ignore reality.
git commit logs have always been "8-bit data". It's actually gitweb that
is buggy if it claims it is UTF-8 without checking or converting it to
such.
I agree that UTF-8 is a good idea, but that's a totally different
argument.
Linus
^ permalink raw reply
* Re: Rss produced by git is not valid xml?
From: H. Peter Anvin @ 2005-11-18 20:28 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Ismail Donmez, git
In-Reply-To: <Pine.LNX.4.64.0511181220350.13959@g5.osdl.org>
Linus Torvalds wrote:
>
> It's easy to say "just do the right thing", and ignore reality.
>
> git commit logs have always been "8-bit data". It's actually gitweb that
> is buggy if it claims it is UTF-8 without checking or converting it to
> such.
>
> I agree that UTF-8 is a good idea, but that's a totally different
> argument.
>
I think the point is: what do you do with the data? If it *looks* like
valid UTF-8, you pretty much have to assume it is; if it's not (it
contains invalid UTF-8 sequences), what do you do? There are only a
small handful of alternatives, and none are really good:
- Reject it (it's kind of too late, should have been done at
checkin)
- Show them as SUBSTITUTE characters (U+FFFD).
- Show them as Latin-1 or Windows-1252
- Provide a complex configuration mechanism
I think Kay is going with the second option.
Note this problem always exists for the data contents anyway. We can't
do anything about that.
What's probably more important is that tools that rely on email or other
outside data sources (like CVS) do the necessary conversions, so one
doesn't end up with an inadvertently incorrect repository.
-hpa
^ permalink raw reply
* Re: [PATCH 1/5] Library code for user-relative paths, take three.
From: H. Peter Anvin @ 2005-11-18 20:33 UTC (permalink / raw)
To: Andreas Ericsson; +Cc: Junio C Hamano, git
In-Reply-To: <437DA828.6020207@op5.se>
Andreas Ericsson wrote:
> Junio C Hamano wrote:
>
>>
>>> + /* This is perfectly safe, and people tend to think of the
>>> directory
>>> + * where they ran git-init-db as their repository, so humour
>>> them. */
>>> + (void)chdir(".git");
>>
>>
>> It might be safe, but I think it changes the behaviour of
>> upload-pack with strict case. My gut reaction is we would want
>> "if (!strict)" in front. Thoughts?
>
> As it says in the comment; People tend to think of the directory where
> they ran "git init-db" as their repository, so humour them. It's nice
> for sharing files between devs in the office, and it *is* safe.
No, it's not.
The whole point with --strict is that it shouldn't DWIM. DWIMming is
*NOT* safe if the data has previously passed through a security screen.
Don't DWIM in strict mode, ever. If you do, you create security holes.
If not immediately, then later.
-hpa
^ permalink raw reply
* [PATCH] Remove all old packfiles when doing "git repack -a -d"
From: Lukas Sandström @ 2005-11-18 20:36 UTC (permalink / raw)
To: git; +Cc: junio C Hamano, Lukas Sandström
No point in running git-pack-redundant if we already know
which packs are redundant.
Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
This should be correct. I even tested it.
git-repack.sh | 19 ++++++++++++++++---
1 files changed, 16 insertions(+), 3 deletions(-)
applies-to: 8c987c24bed7f7a30f4e74b12e8acc2cc5eeea93
2f49d2a3a7cf0fc64edfad2febf986252392b667
diff --git a/git-repack.sh b/git-repack.sh
index e58fdd6..55a7b27 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -63,9 +63,22 @@ exit
if test "$remove_redundant" = t
then
sync
- redundant=$(git-pack-redundant --all)
- if test "$redundant" != "" ; then
- echo $redundant | xargs rm
+ if test "$all_into_one" = t
+ then
+ cd "$PACKDIR"
+ existing=`find . -type f \( -name '*.pack' -o -name '*.idx' \) -print`
+ for e in $existing
+ do
+ case "$e" in
+ ./pack-$name.pack | ./pack-$name.idx) ;;
+ *) rm -f $e ;;
+ esac
+ done
+ else
+ redundant=$(git-pack-redundant --all)
+ if test "$redundant" != "" ; then
+ echo $redundant | xargs rm
+ fi
fi
fi
---
0.99.9.GIT
^ permalink raw reply related
* Re: [ANNOUNCE] gitfs pre-release 0.03
From: Mitchell Blank Jr @ 2005-11-18 20:50 UTC (permalink / raw)
To: Paolo Teti; +Cc: git
In-Reply-To: <34a7ae040511180620v5f6ac014g@mail.gmail.com>
Paolo Teti wrote:
> A question: the gitFS in your intent has to became a "clone" of the
> Rational MultiVersion File System?
Well, I guess I can't give a real solid answer since I've never used
Rational and I'm only vaguely aware of its capabilities. However I think
the answer is "no". My personal belief is that the filesystem abstraction
isn't a good fit to be the main interface to an SCM, especially git.
That's why I'm currently working on just visualizing the contents of the
git repository and I'll add features on top of that as they seem to make
sense.
-Mitch
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox