Commit 48a65a071d9d6689a0ebb7891a20e8dab5fd3cdd

Carlos Martín Nieto 2011-08-04T22:42:58

Only wait for pack if we need it Provide the git_remote_download function to instruct the library to downlad the packfile and let the user know the temporary location. Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>

diff --git a/include/git2/remote.h b/include/git2/remote.h
index 207fe27..74b0a05 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -121,6 +121,20 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headarray *refs);
 GIT_EXTERN(int) git_remote_negotiate(git_remote *remote);
 
 /**
+ * Download the packfile
+ *
+ * The packfile is downloaded with a temporary filename, as it's final
+ * name is not known yet. If there was no packfile needed (all the
+ * objects were available locally), filename will be NULL and the
+ * function will return success.
+ *
+ * @param remote the remote to download from
+ * @param filename where to store the temproray filename
+ * @return GIT_SUCCESS or an error code
+ */
+GIT_EXTERN(int) git_remote_download(char **filename, git_remote *remote);
+
+/**
  * Free the memory associated with a remote
  *
  * @param remote the remote to free
diff --git a/src/fetch.c b/src/fetch.c
index 7e671b7..7abc196 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -45,7 +45,7 @@ static int whn_cmp(const void *a, const void *b)
 	return headb->type - heada->type;
 }
 
-int filter_wants(git_remote *remote)
+static int filter_wants(git_remote *remote)
 {
 	git_vector list;
 	git_headarray refs;
@@ -61,13 +61,13 @@ int filter_wants(git_remote *remote)
 
 	error = git_transport_ls(t, &refs);
 	if (error < GIT_SUCCESS) {
-		error = git__rethrow(error, "Failed to list local refs");
+		error = git__rethrow(error, "Failed to get remote ref list");
 		goto cleanup;
 	}
 
 	spec = git_remote_fetchspec(remote);
 	if (spec == NULL) {
-		error = git__throw(GIT_ERROR, "The remote has to fetchspec");
+		error = git__throw(GIT_ERROR, "The remote has no fetchspec");
 		goto cleanup;
 	}
 
@@ -152,11 +152,11 @@ int git_fetch_negotiate(git_remote *remote)
 	/* Don't try to negotiate when we don't want anything */
 	if (list->len == 0)
 		return GIT_SUCCESS;
-
 	/*
 	 * Now we have everything set up so we can start tell the server
 	 * what we want and what we have.
 	 */
+	remote->need_pack = 1;
 	git_transport_send_wants(remote->transport, list);
 
 	error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
@@ -201,5 +201,10 @@ cleanup:
 
 int git_fetch_download_pack(char **out, git_remote *remote)
 {
+	if(!remote->need_pack) {
+		*out = NULL;
+		return GIT_SUCCESS;
+	}
+
 	return git_transport_download_pack(out, remote->transport, remote->repo);
 }
diff --git a/src/remote.c b/src/remote.c
index 07628d8..75f2dc7 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -208,6 +208,11 @@ int git_remote_negotiate(git_remote *remote)
 	return git_fetch_negotiate(remote);
 }
 
+int git_remote_download(char **filename, git_remote *remote)
+{
+	return git_fetch_download_pack(filename, remote);
+}
+
 git_headarray *git_remote_tips(git_remote *remote)
 {
 	return &remote->refs;
diff --git a/src/remote.h b/src/remote.h
index f5686a2..21313ac 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -13,6 +13,7 @@ struct git_remote {
 	struct git_refspec push;
 	git_transport *transport;
 	git_repository *repo;
+	int need_pack:1;
 };
 
 #endif
diff --git a/src/transport_git.c b/src/transport_git.c
index 871c797..46678a2 100644
--- a/src/transport_git.c
+++ b/src/transport_git.c
@@ -320,7 +320,10 @@ static int store_pack(char **out, gitno_buffer *buf, git_repository *repo)
 		goto cleanup;
 
 	while (1) {
-		if (buf->offset == 0)
+		error = gitno_recv(buf);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+		if (error == 0) /* Orderly shutdown */
 			break;
 
 		error = git_filebuf_write(&file, buf->data, buf->offset);
@@ -331,12 +334,17 @@ static int store_pack(char **out, gitno_buffer *buf, git_repository *repo)
 	}
 
 	*out = git__strdup(file.path_lock);
-	if (*out == NULL)
+	if (*out == NULL) {
 		error = GIT_ENOMEM;
+		goto cleanup;
+	}
 
+	/* A bit dodgy, but we need to keep the pack at the temporary path */
+	error = git_filebuf_commit_at(&file, file.path_lock);
 cleanup:
 	if (error < GIT_SUCCESS)
 		git_filebuf_cleanup(&file);
+
 	return error;
 }
 
@@ -357,7 +365,7 @@ static int git_download_pack(char **out, git_transport *transport, git_repositor
 		error = gitno_recv(&buf);
 		if (error < GIT_SUCCESS)
 			return git__rethrow(GIT_EOSERR, "Failed to receive data");
-		if (error < GIT_SUCCESS) /* Orderly shutdown */
+		if (error == 0) /* Orderly shutdown */
 			return GIT_SUCCESS;
 
 		ptr = buf.data;
@@ -382,7 +390,6 @@ static int git_download_pack(char **out, git_transport *transport, git_repositor
 		 * No we have the packet, let's just put anything we get now
 		 * into a packfile
 		 */
-
 		return store_pack(out, &buf, repo);
 	}