Git development
 help / color / mirror / Atom feed
* Re: [PATCH] http-push: fix off-by-path_len
From: Mike Hommey @ 2009-01-18  7:49 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Kirill A. Korinskiy, git, gitster, Ray Chuan, Nick Hengeveld
In-Reply-To: <alpine.DEB.1.00.0901171632330.3586@pacific.mpi-cbg.de>

On Sat, Jan 17, 2009 at 04:36:26PM +0100, Johannes Schindelin wrote:
> 
> When getting the result of remote_ls(), we were advancing the variable
> "path" to the relative path inside the repository.
> 
> However, then we went on to malloc a bogus amount of memory: we were
> subtracting the prefix length _again_, quite possibly getting something
> negative, which xmalloc() interprets as really, really much.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
> 
> 	Note that the push in t5540 is still broken, as http-push does
> 	not handle packed-refs (when looking what branches are on the 
> 	remote side).
> 
> 	It should not even try to access the directory structure under
> 	refs/ to begin with, but read info/refs instead.

It would actually need to do both, because nothing guarantees info/refs
is up-to-date.

> 	However, that is just one example of the ugliness that is 
> 	http-push.c; it also seems to be a perfect example of a copy-pasting 
> 	hell; just look at the output of "git grep
> 	curl_easy_setopt http-push.c".

Likewise for http.c.

> 	There _has_ to be lot of room for improvement.

And I realize I have had a partial improvement on that sitting on my
harddrive, without me having time (nor motivation) to go further.

Maybe it's time I let it go and post the work in progress for someone
else to take over.

Mike

^ permalink raw reply

* [WIP Patch 02/12] Some cleanup in get_refs_via_curl()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-2-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 transport.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/transport.c b/transport.c
index 56831c5..6919ff1 100644
--- a/transport.c
+++ b/transport.c
@@ -508,6 +508,8 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 		free(ref);
 	}
 
+	http_cleanup();
+	free(refs_url);
 	return refs;
 }
 
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 04/12] Use the new http API in http_fetch_ref()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-4-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http.c |   33 ++++++++-------------------------
 1 files changed, 8 insertions(+), 25 deletions(-)

diff --git a/http.c b/http.c
index 82534cf..0c9504b 100644
--- a/http.c
+++ b/http.c
@@ -604,34 +604,17 @@ int http_fetch_ref(const char *base, struct ref *ref)
 {
 	char *url;
 	struct strbuf buffer = STRBUF_INIT;
-	struct active_request_slot *slot;
-	struct slot_results results;
-	int ret;
+	int ret = -1;
 
 	url = quote_ref_url(base, ref->name);
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result == CURLE_OK) {
-			strbuf_rtrim(&buffer);
-			if (buffer.len == 40)
-				ret = get_sha1_hex(buffer.buf, ref->old_sha1);
-			else if (!prefixcmp(buffer.buf, "ref: ")) {
-				ref->symref = xstrdup(buffer.buf + 5);
-				ret = 0;
-			} else
-				ret = 1;
-		} else {
-			ret = error("Couldn't get %s for %s\n%s",
-				    url, ref->name, curl_errorstr);
+	if (http_get_strbuf(url, &buffer, HTTP_NO_CACHE) == HTTP_OK) {
+		strbuf_rtrim(&buffer);
+		if (buffer.len == 40)
+			ret = get_sha1_hex(buffer.buf, ref->old_sha1);
+		else if (!prefixcmp(buffer.buf, "ref: ")) {
+			ref->symref = xstrdup(buffer.buf + 5);
+			ret = 0;
 		}
-	} else {
-		ret = error("Unable to start request");
 	}
 
 	strbuf_release(&buffer);
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 00/12] Refactoring the http API
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <20090118074911.GB30228@glandium.org>

> And I realize I have had a partial improvement on that sitting on my
> harddrive, without me having time (nor motivation) to go further.
>
> Maybe it's time I let it go and post the work in progress for someone
> else to take over.

Here it is. 

Note I already sent the first patch a year ago:
 http://markmail.org/message/s4w4pmla4tzjkpsf

This set of patches only deals with HTTP GET requests, so all of http-push
is not taken care of.

As it is work in progress, some error handling might have regressions, but
the original error handling is not necessarily much better.

Also note I only rebased my one-year-old work on current master, and haven't
actually tested it, though, as the code hasn't changed much, I guess it
should be fine.

I hope someone will have an itch to scratch to improve the whole thing.

Mike Hommey (12):
  Don't expect verify_pack() callers to set pack_size
  Some cleanup in get_refs_via_curl()
  Two new functions for the http API
  Use the new http API in http_fetch_ref()
  Use the new http API in get_refs_via_curl()
  Use the new http API in http-walker.c:fetch_indices()
  Use the new http API in http-push.c:fetch_indices()
  Use the new http API in update_remote_info_refs()
  Use the new http API in fetch_symref()
  Use the new http API in http-walker.c:fetch_index()
  Use the new http API in http-push.c:fetch_index()
  Use the new http API in http-walker.c:fetch_pack()

 http-push.c   |  159 ++++++++++-----------------------------------------------
 http-walker.c |  141 ++++++--------------------------------------------
 http.c        |  112 ++++++++++++++++++++++++++++++++--------
 http.h        |   17 ++++++
 pack-check.c  |    8 ++-
 transport.c   |   29 ++--------
 6 files changed, 162 insertions(+), 304 deletions(-)

^ permalink raw reply

* [WIP Patch 01/12] Don't expect verify_pack() callers to set pack_size
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-1-git-send-email-mh@glandium.org>

Since use_pack() will end up populating pack_size if it is not already set,
we can just adapt the code in verify_packfile() such that it doesn't require
pack_size to be set beforehand.

This allows callers not to have to set pack_size themselves, and we can thus
revert changes from 1c23d794 (Don't die in git-http-fetch when fetching packs).

Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-push.c   |    3 ---
 http-walker.c |    1 -
 pack-check.c  |    8 +++++---
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/http-push.c b/http-push.c
index a4b7d08..e69179b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -771,14 +771,11 @@ static void finish_request(struct transfer_request *request)
 				request->url, curl_errorstr);
 			remote->can_update_info_refs = 0;
 		} else {
-			off_t pack_size = ftell(request->local_stream);
-
 			fclose(request->local_stream);
 			request->local_stream = NULL;
 			if (!move_temp_to_file(request->tmpfile,
 					       request->filename)) {
 				target = (struct packed_git *)request->userData;
-				target->pack_size = pack_size;
 				lst = &remote->packs;
 				while (*lst != target)
 					lst = &((*lst)->next);
diff --git a/http-walker.c b/http-walker.c
index 7271c7d..0139d1e 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -785,7 +785,6 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha
 		return error("Unable to start request");
 	}
 
-	target->pack_size = ftell(packfile);
 	fclose(packfile);
 
 	ret = move_temp_to_file(tmpfile, filename);
diff --git a/pack-check.c b/pack-check.c
index 90c33b1..166ca70 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -49,7 +49,7 @@ static int verify_packfile(struct packed_git *p,
 	const unsigned char *index_base = p->index_data;
 	git_SHA_CTX ctx;
 	unsigned char sha1[20], *pack_sig;
-	off_t offset = 0, pack_sig_ofs = p->pack_size - 20;
+	off_t offset = 0, pack_sig_ofs = 0;
 	uint32_t nr_objects, i;
 	int err = 0;
 	struct idx_entry *entries;
@@ -61,14 +61,16 @@ static int verify_packfile(struct packed_git *p,
 	 */
 
 	git_SHA1_Init(&ctx);
-	while (offset < pack_sig_ofs) {
+	do {
 		unsigned int remaining;
 		unsigned char *in = use_pack(p, w_curs, offset, &remaining);
 		offset += remaining;
+		if (!pack_sig_ofs)
+			pack_sig_ofs = p->pack_size - 20;
 		if (offset > pack_sig_ofs)
 			remaining -= (unsigned int)(offset - pack_sig_ofs);
 		git_SHA1_Update(&ctx, in, remaining);
-	}
+	} while (offset < pack_sig_ofs);
 	git_SHA1_Final(sha1, &ctx);
 	pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);
 	if (hashcmp(sha1, pack_sig))
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 03/12] Two new functions for the http API
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-3-git-send-email-mh@glandium.org>

http_get_strbuf and http_get_file allow respectively to retrieve contents of
an URL to a strbuf or an opened file handle.

Both these functions are the beginning of the http code refactoring.

Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http.c |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 http.h |   17 +++++++++++++
 2 files changed, 102 insertions(+), 0 deletions(-)

diff --git a/http.c b/http.c
index ee58799..82534cf 100644
--- a/http.c
+++ b/http.c
@@ -638,3 +638,88 @@ int http_fetch_ref(const char *base, struct ref *ref)
 	free(url);
 	return ret;
 }
+
+/* http_request() targets */
+#define HTTP_REQUEST_STRBUF	0
+#define HTTP_REQUEST_FILE	1
+
+static int http_request(const char *url, void *result, int target, int options)
+{
+	struct active_request_slot *slot;
+	struct slot_results results;
+	struct curl_slist *headers = NULL;
+	struct strbuf buf = STRBUF_INIT;
+
+	slot = get_active_slot();
+	slot->results = &results;
+	curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
+
+	if (result == NULL) {
+		curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
+	} else {
+		curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
+		curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
+
+		if (target == HTTP_REQUEST_FILE) {
+			long posn = ftell(result);
+			curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
+					 fwrite);
+			if (posn > 0) {
+				strbuf_addf(&buf, "Range: bytes=%ld-", posn);
+				headers = curl_slist_append(headers, buf.buf);
+				strbuf_reset(&buf);
+			}
+			slot->local = result;
+		} else
+			curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
+					 fwrite_buffer);
+	}
+
+	strbuf_addstr(&buf, "Pragma:");
+	if (options & HTTP_NO_CACHE)
+		strbuf_addstr(&buf, " no-cache");
+
+	headers = curl_slist_append(headers, buf.buf);
+	strbuf_release(&buf);
+
+	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
+
+	if (start_active_slot(slot)) {
+		run_active_slot(slot);
+		if (results.curl_result == CURLE_OK)
+			return HTTP_OK;
+		else if (missing_target(&results))
+			return HTTP_MISSING_TARGET;
+	}
+	return HTTP_ERROR;
+}
+
+int http_get_strbuf(const char *url, struct strbuf *result, int options)
+{
+	return http_request(url, result, HTTP_REQUEST_STRBUF, options);
+}
+
+int http_get_file(const char *url, const char *filename, int options)
+{
+	int ret;
+	struct strbuf tmpfile = STRBUF_INIT;
+	FILE *result;
+
+	strbuf_addf(&tmpfile, "%s.temp", filename);
+	result = fopen(tmpfile.buf, "a");
+	if (! result) {
+		error("Unable to open local file %s", tmpfile.buf);
+		ret = HTTP_ERROR;
+		goto cleanup;
+	}
+
+	ret = http_request(url, result, HTTP_REQUEST_FILE, options);
+	fclose(result);
+
+	if ((ret == HTTP_OK) && move_temp_to_file(tmpfile.buf, filename))
+		ret = HTTP_ERROR;
+cleanup:
+	strbuf_release(&tmpfile);
+	return ret;
+}
diff --git a/http.h b/http.h
index 905b462..323c780 100644
--- a/http.h
+++ b/http.h
@@ -104,4 +104,21 @@ static inline int missing__target(int code, int result)
 
 extern int http_fetch_ref(const char *base, struct ref *ref);
 
+/* Options for http_request_*() */
+#define HTTP_NO_CACHE		1
+
+/* Return values for http_request_*() */
+#define HTTP_OK			0
+#define HTTP_MISSING_TARGET	1
+#define HTTP_ERROR		2
+
+/* Requests an url and stores the result in a strbuf.
+ * If the result pointer is NULL, a HTTP HEAD request is made instead of GET. */
+int http_get_strbuf(const char *url, struct strbuf *result, int options);
+
+/* Downloads an url and stores the result in the given file.
+ * If a previous interrupted download is detected (i.e. a previous temporary
+ * file is still around) the download is resumed. */
+int http_get_file(const char *url, const char *filename, int options);
+
 #endif /* HTTP_H */
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 06/12] Use the new http API in http-walker.c:fetch_indices()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-6-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-walker.c |   31 ++++++++-----------------------
 1 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/http-walker.c b/http-walker.c
index 0139d1e..edcb779 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -648,9 +648,6 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
 	int i = 0;
 	int ret = 0;
 
-	struct active_request_slot *slot;
-	struct slot_results results;
-
 	if (repo->got_indices)
 		return 0;
 
@@ -660,27 +657,15 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
 	url = xmalloc(strlen(repo->base) + 21);
 	sprintf(url, "%s/objects/info/packs", repo->base);
 
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			if (missing_target(&results)) {
-				repo->got_indices = 1;
-				goto cleanup;
-			} else {
-				repo->got_indices = 0;
-				ret = error("%s", curl_errorstr);
-				goto cleanup;
-			}
-		}
-	} else {
+	switch (http_get_strbuf(url, &buffer, HTTP_NO_CACHE)) {
+	case HTTP_OK:
+		break;
+	case HTTP_MISSING_TARGET:
+		repo->got_indices = 1;
+		goto cleanup;
+	default:
 		repo->got_indices = 0;
-		ret = error("Unable to start request");
+		ret = -1;
 		goto cleanup;
 	}
 
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 05/12] Use the new http API in get_refs_via_curl()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-5-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 transport.c |   27 ++++-----------------------
 1 files changed, 4 insertions(+), 23 deletions(-)

diff --git a/transport.c b/transport.c
index 6919ff1..55bf274 100644
--- a/transport.c
+++ b/transport.c
@@ -432,9 +432,6 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 	char *refs_url;
 	int i = 0;
 
-	struct active_request_slot *slot;
-	struct slot_results results;
-
 	struct ref *refs = NULL;
 	struct ref *ref = NULL;
 	struct ref *last_ref = NULL;
@@ -450,26 +447,8 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 	refs_url = xmalloc(strlen(transport->url) + 11);
 	sprintf(refs_url, "%s/info/refs", transport->url);
 
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, refs_url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			strbuf_release(&buffer);
-			if (missing_target(&results))
-				die("%s not found: did you run git update-server-info on the server?", refs_url);
-			else
-				die("%s download error - %s", refs_url, curl_errorstr);
-		}
-	} else {
-		strbuf_release(&buffer);
-		die("Unable to start HTTP request");
-	}
+	if (http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE) != HTTP_OK)
+		goto cleanup;
 
 	data = buffer.buf;
 	start = NULL;
@@ -508,6 +487,8 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 		free(ref);
 	}
 
+cleanup:
+	strbuf_release(&buffer);
 	http_cleanup();
 	free(refs_url);
 	return refs;
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 07/12] Use the new http API in http-push.c:fetch_indices()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-7-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-push.c |   32 +++++++-------------------------
 1 files changed, 7 insertions(+), 25 deletions(-)

diff --git a/http-push.c b/http-push.c
index e69179b..e0b4f5a 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1008,9 +1008,7 @@ static int fetch_indices(void)
 	struct strbuf buffer = STRBUF_INIT;
 	char *data;
 	int i = 0;
-
-	struct active_request_slot *slot;
-	struct slot_results results;
+	int ret = 0;
 
 	if (push_verbosely)
 		fprintf(stderr, "Getting pack list\n");
@@ -1018,28 +1016,10 @@ static int fetch_indices(void)
 	url = xmalloc(strlen(remote->url) + 20);
 	sprintf(url, "%sobjects/info/packs", remote->url);
 
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			strbuf_release(&buffer);
-			free(url);
-			if (results.http_code == 404)
-				return 0;
-			else
-				return error("%s", curl_errorstr);
-		}
-	} else {
-		strbuf_release(&buffer);
-		free(url);
-		return error("Unable to start request");
+	if (http_get_strbuf(url, &buffer, 0) != HTTP_OK) {
+		ret = -1;
+		goto cleanup;
 	}
-	free(url);
 
 	data = buffer.buf;
 	while (i < buffer.len) {
@@ -1061,8 +1041,10 @@ static int fetch_indices(void)
 		i++;
 	}
 
+cleanup:
 	strbuf_release(&buffer);
-	return 0;
+	free(url);
+	return ret;
 }
 
 static void one_remote_object(const char *hex)
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 09/12] Use the new http API in fetch_symref()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-9-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-push.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/http-push.c b/http-push.c
index 7627860..b32def4 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1982,27 +1982,12 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
 {
 	char *url;
 	struct strbuf buffer = STRBUF_INIT;
-	struct active_request_slot *slot;
-	struct slot_results results;
 
 	url = xmalloc(strlen(remote->url) + strlen(path) + 1);
 	sprintf(url, "%s%s", remote->url, path);
 
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			die("Couldn't get %s for remote symref\n%s",
-			    url, curl_errorstr);
-		}
-	} else {
-		die("Unable to start remote symref request");
-	}
+	if (http_get_strbuf(url, &buffer, 0) != HTTP_OK)
+		die("Couldn't get %s for remote symref\n", url);
 	free(url);
 
 	free(*symref);
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 08/12] Use the new http API in update_remote_info_refs()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-8-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-push.c |   29 ++++++++++-------------------
 1 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/http-push.c b/http-push.c
index e0b4f5a..7627860 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1960,29 +1960,20 @@ static void update_remote_info_refs(struct remote_lock *lock)
 static int remote_exists(const char *path)
 {
 	char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
-	struct active_request_slot *slot;
-	struct slot_results results;
-	int ret = -1;
+	int ret;
 
 	sprintf(url, "%s%s", remote->url, path);
 
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
-
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.http_code == 404)
-			ret = 0;
-		else if (results.curl_result == CURLE_OK)
-			ret = 1;
-		else
-			fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code);
-	} else {
-		fprintf(stderr, "Unable to start HEAD request\n");
+	switch (http_get_strbuf(url, NULL, 0)) {
+	case HTTP_OK:
+		ret = 1;
+		break;
+	case HTTP_MISSING_TARGET:
+		ret = 0;
+		break;
+	default:
+		ret = -1;
 	}
-
 	free(url);
 	return ret;
 }
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 10/12] Use the new http API in http-walker.c:fetch_index()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-10-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-walker.c |   55 +++++--------------------------------------------------
 1 files changed, 5 insertions(+), 50 deletions(-)

diff --git a/http-walker.c b/http-walker.c
index edcb779..bc1db2b 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -368,15 +368,7 @@ static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned ch
 	char *hex = sha1_to_hex(sha1);
 	char *filename;
 	char *url;
-	char tmpfile[PATH_MAX];
-	long prev_posn = 0;
-	char range[RANGE_HEADER_SIZE];
-	struct curl_slist *range_header = NULL;
-	struct walker_data *data = walker->data;
-
-	FILE *indexfile;
-	struct active_request_slot *slot;
-	struct slot_results results;
+	int ret = 0;
 
 	if (has_pack_index(sha1))
 		return 0;
@@ -388,48 +380,11 @@ static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned ch
 	sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex);
 
 	filename = sha1_pack_index_name(sha1);
-	snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
-	indexfile = fopen(tmpfile, "a");
-	if (!indexfile)
-		return error("Unable to open local file %s for pack index",
-			     tmpfile);
-
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header);
-	slot->local = indexfile;
-
-	/* If there is data present from a previous transfer attempt,
-	   resume where it left off */
-	prev_posn = ftell(indexfile);
-	if (prev_posn>0) {
-		if (walker->get_verbosely)
-			fprintf(stderr,
-				"Resuming fetch of index for pack %s at byte %ld\n",
-				hex, prev_posn);
-		sprintf(range, "Range: bytes=%ld-", prev_posn);
-		range_header = curl_slist_append(range_header, range);
-		curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
-	}
-
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			fclose(indexfile);
-			return error("Unable to get pack index %s\n%s", url,
-				     curl_errorstr);
-		}
-	} else {
-		fclose(indexfile);
-		return error("Unable to start request");
-	}
-
-	fclose(indexfile);
 
-	return move_temp_to_file(tmpfile, filename);
+	if (http_get_file(url, filename, 0) != HTTP_OK)
+		ret = error("Unable to get pack index %s\n", url);
+	free(url);
+	return ret;
 }
 
 static int setup_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 11/12] Use the new http API in http-push.c:fetch_index()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-11-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-push.c |   76 ++++++----------------------------------------------------
 1 files changed, 8 insertions(+), 68 deletions(-)

diff --git a/http-push.c b/http-push.c
index b32def4..0812f58 100644
--- a/http-push.c
+++ b/http-push.c
@@ -898,32 +898,15 @@ static int fetch_index(unsigned char *sha1)
 	char *hex = sha1_to_hex(sha1);
 	char *filename;
 	char *url;
-	char tmpfile[PATH_MAX];
-	long prev_posn = 0;
-	char range[RANGE_HEADER_SIZE];
-	struct curl_slist *range_header = NULL;
-
-	FILE *indexfile;
-	struct active_request_slot *slot;
-	struct slot_results results;
+	int ret = 0;
 
 	/* Don't use the index if the pack isn't there */
 	url = xmalloc(strlen(remote->url) + 64);
 	sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			free(url);
-			return error("Unable to verify pack %s is available",
-				     hex);
-		}
-	} else {
+	if (http_get_strbuf(url, NULL, 0)) {
 		free(url);
-		return error("Unable to start request");
+		return error("Unable to verify pack %s is available",
+			     hex);
 	}
 
 	if (has_pack_index(sha1)) {
@@ -937,55 +920,12 @@ static int fetch_index(unsigned char *sha1)
 	sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
 
 	filename = sha1_pack_index_name(sha1);
-	snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
-	indexfile = fopen(tmpfile, "a");
-	if (!indexfile) {
-		free(url);
-		return error("Unable to open local file %s for pack index",
-			     tmpfile);
-	}
-
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
-	slot->local = indexfile;
-
-	/* If there is data present from a previous transfer attempt,
-	   resume where it left off */
-	prev_posn = ftell(indexfile);
-	if (prev_posn>0) {
-		if (push_verbosely)
-			fprintf(stderr,
-				"Resuming fetch of index for pack %s at byte %ld\n",
-				hex, prev_posn);
-		sprintf(range, "Range: bytes=%ld-", prev_posn);
-		range_header = curl_slist_append(range_header, range);
-		curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
-	}
-
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			free(url);
-			fclose(indexfile);
-			return error("Unable to get pack index %s\n%s", url,
-				     curl_errorstr);
-		}
-	} else {
-		free(url);
-		fclose(indexfile);
-		return error("Unable to start request");
-	}
 
+	if (http_get_file(url, filename, 0) != HTTP_OK)
+		ret = error("Unable to get pack index %s\n", url);
+	free(filename);
 	free(url);
-	fclose(indexfile);
-
-	return move_temp_to_file(tmpfile, filename);
+	return ret;
 }
 
 static int setup_index(unsigned char *sha1)
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* [WIP Patch 12/12] Use the new http API in http-walker.c:fetch_pack()
From: Mike Hommey @ 2009-01-18  8:04 UTC (permalink / raw)
  To: git, gitster; +Cc: johannes.schindelin
In-Reply-To: <1232265877-3649-12-git-send-email-mh@glandium.org>


Signed-off-by: Mike Hommey <mh@glandium.org>
---
 http-walker.c |   54 ++++--------------------------------------------------
 1 files changed, 4 insertions(+), 50 deletions(-)

diff --git a/http-walker.c b/http-walker.c
index bc1db2b..c201463 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -656,17 +656,8 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha
 	char *url;
 	struct packed_git *target;
 	struct packed_git **lst;
-	FILE *packfile;
 	char *filename;
-	char tmpfile[PATH_MAX];
-	int ret;
-	long prev_posn = 0;
-	char range[RANGE_HEADER_SIZE];
-	struct curl_slist *range_header = NULL;
-	struct walker_data *data = walker->data;
-
-	struct active_request_slot *slot;
-	struct slot_results results;
+	int ret = 0;
 
 	if (fetch_indices(walker, repo))
 		return -1;
@@ -686,48 +677,11 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha
 		repo->base, sha1_to_hex(target->sha1));
 
 	filename = sha1_pack_name(target->sha1);
-	snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
-	packfile = fopen(tmpfile, "a");
-	if (!packfile)
-		return error("Unable to open local file %s for pack",
-			     tmpfile);
-
-	slot = get_active_slot();
-	slot->results = &results;
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header);
-	slot->local = packfile;
-
-	/* If there is data present from a previous transfer attempt,
-	   resume where it left off */
-	prev_posn = ftell(packfile);
-	if (prev_posn>0) {
-		if (walker->get_verbosely)
-			fprintf(stderr,
-				"Resuming fetch of pack %s at byte %ld\n",
-				sha1_to_hex(target->sha1), prev_posn);
-		sprintf(range, "Range: bytes=%ld-", prev_posn);
-		range_header = curl_slist_append(range_header, range);
-		curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
-	}
 
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (results.curl_result != CURLE_OK) {
-			fclose(packfile);
-			return error("Unable to get pack file %s\n%s", url,
-				     curl_errorstr);
-		}
-	} else {
-		fclose(packfile);
-		return error("Unable to start request");
-	}
-
-	fclose(packfile);
+	if (http_get_file(url, filename, 0) != HTTP_OK)
+		ret = error("Unable to get pack file %s\n", url);
+	free(url);
 
-	ret = move_temp_to_file(tmpfile, filename);
 	if (ret)
 		return ret;
 
-- 
1.6.1.141.gb32a

^ permalink raw reply related

* Re: [WIP Patch 00/12] Refactoring the http API
From: Junio C Hamano @ 2009-01-18  8:30 UTC (permalink / raw)
  To: Mike Hommey; +Cc: git, johannes.schindelin
In-Reply-To: <1232265877-3649-1-git-send-email-mh@glandium.org>

Mike Hommey <mh@glandium.org> writes:

> As it is work in progress, some error handling might have regressions, but
> the original error handling is not necessarily much better.
>
> Also note I only rebased my one-year-old work on current master, and haven't
> actually tested it, though, as the code hasn't changed much, I guess it
> should be fine.
> ...
>  6 files changed, 162 insertions(+), 304 deletions(-)

Thanks.

This looks like a very nice code reduction, and the first few patches
looked obviously correct, too ;-)

But I am puzzled by what you mean by "haven't actually tested it".  Do you
mean you do not use http transport very much yourself, or even when you do
you do not use a version of git with these patches applied?

^ permalink raw reply

* Re: [WIP Patch 00/12] Refactoring the http API
From: Mike Hommey @ 2009-01-18  9:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, johannes.schindelin
In-Reply-To: <7v8wp9yq23.fsf@gitster.siamese.dyndns.org>

On Sun, Jan 18, 2009 at 12:30:12AM -0800, Junio C Hamano wrote:
> Mike Hommey <mh@glandium.org> writes:
> 
> > As it is work in progress, some error handling might have regressions, but
> > the original error handling is not necessarily much better.
> >
> > Also note I only rebased my one-year-old work on current master, and haven't
> > actually tested it, though, as the code hasn't changed much, I guess it
> > should be fine.
> > ...
> >  6 files changed, 162 insertions(+), 304 deletions(-)
> 
> Thanks.
> 
> This looks like a very nice code reduction, and the first few patches
> looked obviously correct, too ;-)
> 
> But I am puzzled by what you mean by "haven't actually tested it".  Do you
> mean you do not use http transport very much yourself, or even when you do
> you do not use a version of git with these patches applied?

I mean I haven't tested the rebased version. The original version was
tested extensively a year ago. I don't use http transport that much
now.

Mike

^ permalink raw reply

* Re: [PATCH/RFC] git-am: Make it easier to see which patch failed
From: Stephan Beyer @ 2009-01-18  9:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jonas Flodén, git, Johannes Schindelin
In-Reply-To: <7vhc3x1874.fsf@gitster.siamese.dyndns.org>

> > diff --git a/git-am.sh b/git-am.sh
> > index 4b157fe..09c2f9c 100755
> > --- a/git-am.sh
> > +++ b/git-am.sh
> > @@ -501,7 +501,7 @@ do
> >  	fi
> >  	if test $apply_status != 0
> >  	then
> > -		echo Patch failed at $msgnum.
> > +		printf '\nPatch failed at %s (%s)\n' "$msgnum" "$FIRSTLINE"
> >  		stop_here_user_resolve $this
> >  	fi
> 
> Looks sane except that I do not think you need printf nor the leading
> blank line, i.e.
> 
> 	echo "Patch failed at $msgnum ($FIRSTLINE)"

Hmm, IIRC if $FIRSTLINE contains \n or something like that, it will
interpret this as newline in some shell/echo implementations.

So printf "...%s..." "$FOO" is always sane for user input.

Regards,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply

* Re: [PATCH/RFC] git-am: Make it easier to see which patch failed
From: Stephan Beyer @ 2009-01-18  9:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jonas Flodén, git, Johannes Schindelin
In-Reply-To: <20090118094113.GE11992@leksak.fem-net>

Stephan Beyer wrote:
> Hmm, IIRC if $FIRSTLINE contains \n or something like that, it will
> interpret this as newline in some shell/echo implementations.

Just in case someone wonders but doesn't dare ask:

bash as expected:
	$ echo 'foo\nbar'
	foo\nbar
	$ echo -e 'foo\nbar'
	foo
	bar

But dash:
	$ echo 'foo\nbar'
	foo
	bar
	$ echo -e 'foo\nbar'
	-e foo
	bar

(According to Debian Popularity Contest[1] "dash" is used in more than
10.000 Debian installations, although it doesn't say if it is used for
/bin/sh.)

 1. http://qa.debian.org/popcon.php?package=dash

Regards,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply

* [PATCH 2/3] Teach read_tree_recursive() how to traverse into submodules
From: Lars Hjemli @ 2009-01-18 10:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <1232275999-14852-2-git-send-email-hjemli@gmail.com>

The traversal of submodules is only triggered if the current submodule
HEAD commit object is accessible. To this end, read_tree_recursive()
will try to insert the submodule odb as an alternate odb but the lack
of such an odb is not treated as an error since it is then assumed that
the user is not interested in the submodule content. However, if the
submodule odb is found it is treated as an error if the HEAD commit
object is missing.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cache.h       |    2 +
 environment.c |   12 ++++++++
 tree.c        |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/cache.h b/cache.h
index daa2d4e..6728467 100644
--- a/cache.h
+++ b/cache.h
@@ -382,6 +382,8 @@ extern int set_git_dir(const char *path);
 extern const char *get_git_work_tree(void);
 extern const char *read_gitfile_gently(const char *path);
 extern void set_git_work_tree(const char *tree);
+extern int get_traverse_gitlinks();
+extern void set_traverse_gitlinks(int traverse);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
diff --git a/environment.c b/environment.c
index e278bce..35cc557 100644
--- a/environment.c
+++ b/environment.c
@@ -53,6 +53,8 @@ static char *work_tree;
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
 
+static int traverse_gitlinks = 0;
+
 static void setup_git_env(void)
 {
 	git_dir = getenv(GIT_DIR_ENVIRONMENT);
@@ -159,3 +161,13 @@ int set_git_dir(const char *path)
 	setup_git_env();
 	return 0;
 }
+
+int get_traverse_gitlinks()
+{
+	return traverse_gitlinks;
+}
+
+void set_traverse_gitlinks(int traverse)
+{
+	traverse_gitlinks = traverse;
+}
diff --git a/tree.c b/tree.c
index 03e782a..87cf309 100644
--- a/tree.c
+++ b/tree.c
@@ -5,6 +5,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "tree-walk.h"
+#include "refs.h"
 
 const char *tree_type = "tree";
 
@@ -89,6 +90,61 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
 	return 0;
 }
 
+/* Try to add the objectdb of a submodule */
+int add_gitlink_odb(char *relpath)
+{
+	const char *odbpath;
+	struct stat st;
+
+	odbpath = read_gitfile_gently(mkpath("%s/.git", relpath));
+	if (!odbpath)
+		odbpath = mkpath("%s/.git/objects", relpath);
+
+	if (stat(odbpath, &st))
+		return 1;
+
+	return add_alt_odb(odbpath);
+}
+
+/* Check if we should recurse into the specified submodule */
+int traverse_gitlink(char *path, const unsigned char *commit_sha1,
+		     struct tree **subtree)
+{
+	unsigned char sha1[20];
+	int linked_odb = 0;
+	struct commit *commit;
+	void *buffer;
+	enum object_type type;
+	unsigned long size;
+
+	hashcpy(sha1, commit_sha1);
+	if (!add_gitlink_odb(path)) {
+		linked_odb = 1;
+		if (resolve_gitlink_ref(path, "HEAD", sha1))
+			die("Unable to lookup HEAD in %s", path);
+	}
+
+	buffer = read_sha1_file(sha1, &type, &size);
+	if (!buffer) {
+		if (linked_odb)
+			die("Unable to read object %s in submodule %s",
+			    sha1_to_hex(sha1), path);
+		else
+			return 0;
+	}
+
+	commit = lookup_commit(sha1);
+	if (!commit)
+		die("traverse_gitlink(): internal error");
+
+	if (parse_commit_buffer(commit, buffer, size))
+		die("Failed to parse commit %s in submodule %s",
+		    sha1_to_hex(sha1), path);
+
+	*subtree = commit->tree;
+	return 1;
+}
+
 int read_tree_recursive(struct tree *tree,
 			const char *base, int baselen,
 			int stage, const char **match,
@@ -132,6 +188,30 @@ int read_tree_recursive(struct tree *tree,
 				return -1;
 			continue;
 		}
+		if (S_ISGITLINK(entry.mode) && get_traverse_gitlinks()) {
+			int retval;
+			char *newbase;
+			struct tree *subtree;
+			unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
+
+			newbase = xmalloc(baselen + 1 + pathlen);
+			memcpy(newbase, base, baselen);
+			memcpy(newbase + baselen, entry.path, pathlen);
+			newbase[baselen + pathlen] = 0;
+			if (!traverse_gitlink(newbase, entry.sha1, &subtree)) {
+				free(newbase);
+				continue;
+			}
+			newbase[baselen + pathlen] = '/';
+			retval = read_tree_recursive(subtree,
+						     newbase,
+						     baselen + pathlen + 1,
+						     stage, match, fn, context);
+			free(newbase);
+			if (retval)
+				return -1;
+			continue;
+		}
 	}
 	return 0;
 }
-- 
1.6.1.150.g5e733b

^ permalink raw reply related

* [PATCH 1/3] sha1_file: add function to insert alternate object db
From: Lars Hjemli @ 2009-01-18 10:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <1232275999-14852-1-git-send-email-hjemli@gmail.com>

This function will be used when implementing traversal into submodules.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cache.h     |    1 +
 sha1_file.c |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/cache.h b/cache.h
index 8e1af26..daa2d4e 100644
--- a/cache.h
+++ b/cache.h
@@ -724,6 +724,7 @@ extern struct alternate_object_database {
 	char base[FLEX_ARRAY]; /* more */
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
+extern int add_alt_odb(const char *path);
 extern void add_to_alternates_file(const char *reference);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 extern void foreach_alt_odb(alt_odb_fn, void*);
diff --git a/sha1_file.c b/sha1_file.c
index f08493f..19f9725 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -356,6 +356,11 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
 	}
 }
 
+int add_alt_odb(const char *path)
+{
+	return link_alt_odb_entry(path, strlen(path), NULL, 0);
+}
+
 static void read_info_alternates(const char * relative_base, int depth)
 {
 	char *map;
-- 
1.6.1.150.g5e733b

^ permalink raw reply related

* [PATCH 0/3] Implement 'git archive --submodules'
From: Lars Hjemli @ 2009-01-18 10:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

This series teaches read_tree_recursive() how to traverse into gitlinked
repositories by automatically adding submodule object databases as
alternates during traversal. It is still perfectly legal for a submodule
not to be checked out, in which case the submodule will be ignored.

On top of this, the implementation of 'git archive --submodules' simply
activates the new feature in read_tree_recursive().

Lars Hjemli (3):
  sha1_file: add function to insert alternate object db
  Teach read_tree_recursive() how to traverse into submodules
  git-archive: add support for --submodules

 Documentation/git-archive.txt |    7 +++-
 archive.c                     |    4 ++
 cache.h                       |    3 ++
 environment.c                 |   12 ++++++
 sha1_file.c                   |    5 +++
 t/t5001-archive-submodules.sh |   78 +++++++++++++++++++++++++++++++++++++++
 tree.c                        |   80 +++++++++++++++++++++++++++++++++++++++++
 7 files changed, 187 insertions(+), 2 deletions(-)
 create mode 100755 t/t5001-archive-submodules.sh

^ permalink raw reply

* [PATCH 3/3] git-archive: add support for --submodules
From: Lars Hjemli @ 2009-01-18 10:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <1232275999-14852-3-git-send-email-hjemli@gmail.com>

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 Documentation/git-archive.txt |    7 +++-
 archive.c                     |    4 ++
 t/t5001-archive-submodules.sh |   78 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100755 t/t5001-archive-submodules.sh

diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 41cbf9c..84e0b43 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -10,8 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
-	      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
-	      [path...]
+	      [--remote=<repo> [--exec=<git-upload-archive>]] [--submodules]
+	      <tree-ish> [path...]
 
 DESCRIPTION
 -----------
@@ -59,6 +59,9 @@ OPTIONS
 	Used with --remote to specify the path to the
 	'git-upload-archive' on the remote side.
 
+--submodules::
+	Include files from checked out submodules.
+
 <tree-ish>::
 	The tree or commit to produce an archive for.
 
diff --git a/archive.c b/archive.c
index 9ac455d..0c024b8 100644
--- a/archive.c
+++ b/archive.c
@@ -255,6 +255,7 @@ static int parse_archive_args(int argc, const char **argv,
 	const char *exec = NULL;
 	int compression_level = -1;
 	int verbose = 0;
+	int submodules = 0;
 	int i;
 	int list = 0;
 	struct option opts[] = {
@@ -262,6 +263,8 @@ static int parse_archive_args(int argc, const char **argv,
 		OPT_STRING(0, "format", &format, "fmt", "archive format"),
 		OPT_STRING(0, "prefix", &base, "prefix",
 			"prepend prefix to each pathname in the archive"),
+		OPT_BOOLEAN(0, "submodules", &submodules,
+			"recurse into submodules"),
 		OPT__VERBOSE(&verbose),
 		OPT__COMPR('0', &compression_level, "store only", 0),
 		OPT__COMPR('1', &compression_level, "compress faster", 1),
@@ -320,6 +323,7 @@ static int parse_archive_args(int argc, const char **argv,
 	args->base = base;
 	args->baselen = strlen(base);
 
+	set_traverse_gitlinks(submodules);
 	return argc;
 }
 
diff --git a/t/t5001-archive-submodules.sh b/t/t5001-archive-submodules.sh
new file mode 100755
index 0000000..5a499a4
--- /dev/null
+++ b/t/t5001-archive-submodules.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+test_description='git archive can include submodule content'
+
+. ./test-lib.sh
+
+add_file()
+{
+	git add $1 &&
+	git commit -m "added $1"
+}
+
+add_submodule()
+{
+	mkdir $1 && (
+		cd $1 &&
+		git init &&
+		echo "File $2" >$2 &&
+		add_file $2
+	) &&
+	add_file $1
+}
+
+test_expect_success 'setup submodules' '
+	echo "File 1" >1 &&
+	add_file 1 &&
+	add_submodule 2 3 &&
+	add_submodule 4 5 &&
+	(cd 4 && add_submodule 6 7)
+'
+
+test_expect_success 'git archive usually ignores submodules' '
+	cat <<EOF >expected &&
+1
+2/
+4/
+EOF
+	git archive HEAD >normal.tar &&
+	tar -tf normal.tar >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'git archive includes submodules when requested' '
+	cat <<EOF >expected &&
+1
+2/
+2/3
+4/
+4/5
+4/6/
+4/6/7
+EOF
+	git archive --submodules HEAD >full.tar &&
+	tar -tf full.tar >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'git archive ignores uninteresting submodules' '
+	cat <<EOF >expected &&
+1
+2/
+4/
+4/5
+4/6/
+4/6/7
+EOF
+	rm -rf 2/.git &&
+	git archive --submodules HEAD >partial.tar &&
+	tar -tf partial.tar >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'git archive fails on missing object in interesting submodule' '
+	find 4/.git/objects -type f | xargs rm &&
+	test_must_fail git archive --submodules HEAD
+'
+
+test_done
-- 
1.6.1.150.g5e733b

^ permalink raw reply related

* easy way to make tracking branches?
From: Stephan Beyer @ 2009-01-18 10:55 UTC (permalink / raw)
  To: git

Hi,

assume I have a branch "foo" in my local repo, a remote "srv", and
a branch "bar" on srv (i.e. generated with "git push srv foo:bar").

Now I want to make "foo" a tracking branch for "bar".
I do:

	git config branch.foo.remote srv
	git config branch.foo.merge refs/heads/bar

And to get a comfortable git-push, I do:

	git config --add remote.srv.push foo:bar


Because I do not always remember the sequence, I have to look it
up or I just do

	git checkout -b foo2 srv/bar
	git branch -d foo
	git branch -m foo

which is suboptimal because deleting foo can remove some
other settings for the branch, e.g. mergeoptions.


So I wonder if there is some easier-to-remind way to let my branch
foo track my remote branch bar, or, if not, could it be useful to
have something like

	git push --make-tracking srv foo:bar
	# push foo -> bar and let foo track bar...
	# if foo already tracks bar, ignore the option

or should I just write a tiny script for me and shut up? :-)


Regards,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply

* Re: [WIP Patch 00/12] Refactoring the http API
From: Boyd Stephen Smith Jr. @ 2009-01-18 11:29 UTC (permalink / raw)
  To: Mike Hommey; +Cc: Junio C Hamano, git, johannes.schindelin
In-Reply-To: <20090118091219.GA6505@glandium.org>

[-- Attachment #1: Type: text/plain, Size: 1287 bytes --]

On Sunday 18 January 2009, Mike Hommey <mh@glandium.org> wrote about 'Re: 
[WIP Patch 00/12] Refactoring the http API':
>On Sun, Jan 18, 2009 at 12:30:12AM -0800, Junio C Hamano wrote:
>> Mike Hommey <mh@glandium.org> writes:
>> > [I]
>> > haven't actually tested it, though, as the code hasn't changed much,
>> > I guess it should be fine.
>> >  6 files changed, 162 insertions(+), 304 deletions(-)
>>
>> Thanks.
>> But I am puzzled by what you mean by "haven't actually tested it".  Do
>> you mean you do not use http transport very much yourself, or even when
>> you do you do not use a version of git with these patches applied?
>I mean I haven't tested the rebased version. The original version was
>tested extensively a year ago. I don't use http transport that much
>now.

I know it's uncool of me to ask to do this, BUT... Do we have a good 
test-suite for this?  If so, I can always run it against any number of 
different WEBDAV implementations.  I have a glut of CPU time on many of my 
systems and enjoy breaking things.
-- 
Boyd Stephen Smith Jr.                     ,= ,-_-. =. 
bss@iguanasuicide.net                     ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy           `-'(. .)`-' 
http://iguanasuicide.net/                      \_/     

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* [PATCH] http-push: support full URI in handle_remote_ls_ctx()
From: Kirill A. Korinskiy @ 2009-01-18 11:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Kirill A. Korinskiy

The program calls remote_ls() to get list of files from the server
over HTTP; handle_remote_ls_ctx() is used to parse its response to
populate "struct remote_ls_ctx" that is returned from remote_ls().

The handle_remote_ls_ctx() function assumed that the server returns a
local path in href field, but RFC 4918 (14.7) demand of support full
URI (e.g. "http://localhost:8080/repo.git").

This resulted in push failure (e.g. git-http-push issues a PROPFIND
request to "/repo.git/alhost:8080/repo.git/refs/" to the server).

Signed-off-by: Kirill A. Korinskiy <catap@catap.ru>
---
 http-push.c |   24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/http-push.c b/http-push.c
index 7c6460919bf3eba10c46cede11ffdd9c53fd2dd2..2cb925a9ad857b6d79858d5187f14072167282e7 100644
--- a/http-push.c
+++ b/http-push.c
@@ -87,6 +87,7 @@ static struct object_list *objects;
 struct repo
 {
 	char *url;
+	char *path;
 	int path_len;
 	int has_info_refs;
 	int can_update_info_refs;
@@ -1424,9 +1425,18 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
 				ls->userFunc(ls);
 			}
 		} else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
-			ls->dentry_name = xmalloc(strlen(ctx->cdata) -
+			char *path = ctx->cdata;
+			if (!strcmp(ctx->cdata, "http://")) {
+				path = strchr(path + sizeof("http://") - 1, '/');
+			} else if (!strcmp(ctx->cdata, "https://")) {
+				path = strchr(path + sizeof("https://") - 1, '/');
+			}
+
+			path += remote->path_len;
+
+			ls->dentry_name = xmalloc(strlen(path) -
 						  remote->path_len + 1);
-			strcpy(ls->dentry_name, ctx->cdata + remote->path_len);
+			strcpy(ls->dentry_name, path + remote->path_len);
 		} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
 			ls->dentry_flags |= IS_DIR;
 		}
@@ -2206,10 +2216,11 @@ int main(int argc, char **argv)
 		if (!remote->url) {
 			char *path = strstr(arg, "//");
 			remote->url = arg;
+			remote->path_len = strlen(arg);
 			if (path) {
-				path = strchr(path+2, '/');
-				if (path)
-					remote->path_len = strlen(path);
+				remote->path = strchr(path+2, '/');
+				if (remote->path)
+					remote->path_len = strlen(remote->path);
 			}
 			continue;
 		}
@@ -2238,8 +2249,9 @@ int main(int argc, char **argv)
 		rewritten_url = xmalloc(strlen(remote->url)+2);
 		strcpy(rewritten_url, remote->url);
 		strcat(rewritten_url, "/");
+		remote->path = rewritten_url + (remote->path - remote->url);
+		remote->path_len++;
 		remote->url = rewritten_url;
-		++remote->path_len;
 	}
 
 	/* Verify DAV compliance/lock support */
-- 
1.5.6.5

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox