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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
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);
}