|
15 | 15 | #include "remote.h"
|
16 | 16 | #include "refspec.h"
|
17 | 17 | #include "fetch.h"
|
| 18 | +#include "netops.h" |
18 | 19 |
|
19 | 20 | static int filter_wants(git_remote *remote)
|
20 | 21 | {
|
@@ -131,3 +132,60 @@ int git_fetch_download_pack(char **out, git_remote *remote)
|
131 | 132 |
|
132 | 133 | return remote->transport->download_pack(out, remote->transport, remote->repo);
|
133 | 134 | }
|
| 135 | + |
| 136 | +/* Receiving data from a socket and storing it is pretty much the same for git and HTTP */ |
| 137 | +int git_fetch__download_pack(char **out, const char *buffered, size_t buffered_size, |
| 138 | + GIT_SOCKET fd, git_repository *repo) |
| 139 | +{ |
| 140 | + git_filebuf file; |
| 141 | + int error; |
| 142 | + char buff[1024], path[GIT_PATH_MAX]; |
| 143 | + static const char suff[] = "/objects/pack/pack-received"; |
| 144 | + gitno_buffer buf; |
| 145 | + |
| 146 | + |
| 147 | + git_path_join(path, repo->path_repository, suff); |
| 148 | + |
| 149 | + gitno_buffer_setup(&buf, buff, sizeof(buff), fd); |
| 150 | + |
| 151 | + if (memcmp(buffered, "PACK", strlen("PACK"))) { |
| 152 | + return git__throw(GIT_ERROR, "The pack doesn't start with the signature"); |
| 153 | + } |
| 154 | + |
| 155 | + error = git_filebuf_open(&file, path, GIT_FILEBUF_TEMPORARY); |
| 156 | + if (error < GIT_SUCCESS) |
| 157 | + goto cleanup; |
| 158 | + |
| 159 | + /* Part of the packfile has been received, don't loose it */ |
| 160 | + error = git_filebuf_write(&file, buffered, buffered_size); |
| 161 | + if (error < GIT_SUCCESS) |
| 162 | + goto cleanup; |
| 163 | + |
| 164 | + while (1) { |
| 165 | + error = git_filebuf_write(&file, buf.data, buf.offset); |
| 166 | + if (error < GIT_SUCCESS) |
| 167 | + goto cleanup; |
| 168 | + |
| 169 | + gitno_consume_n(&buf, buf.offset); |
| 170 | + error = gitno_recv(&buf); |
| 171 | + if (error < GIT_SUCCESS) |
| 172 | + goto cleanup; |
| 173 | + if (error == 0) /* Orderly shutdown */ |
| 174 | + break; |
| 175 | + } |
| 176 | + |
| 177 | + *out = git__strdup(file.path_lock); |
| 178 | + if (*out == NULL) { |
| 179 | + error = GIT_ENOMEM; |
| 180 | + goto cleanup; |
| 181 | + } |
| 182 | + |
| 183 | + /* A bit dodgy, but we need to keep the pack at the temporary path */ |
| 184 | + error = git_filebuf_commit_at(&file, file.path_lock); |
| 185 | +cleanup: |
| 186 | + if (error < GIT_SUCCESS) |
| 187 | + git_filebuf_cleanup(&file); |
| 188 | + |
| 189 | + return error; |
| 190 | + |
| 191 | +} |
0 commit comments