* @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);
+GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats);
/**
* Check whether the remote is connected
#include "git2/oid.h"
#include "git2/refs.h"
#include "git2/revwalk.h"
+#include "git2/indexer.h"
#include "common.h"
#include "transport.h"
return t->negotiate_fetch(t, remote->repo, &remote->refs);
}
-int git_fetch_download_pack(char **out, git_remote *remote)
+int git_fetch_download_pack(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats)
{
- if(!remote->need_pack) {
- *out = NULL;
+ if(!remote->need_pack)
return 0;
- }
- return remote->transport->download_pack(out, remote->transport, remote->repo);
+ return remote->transport->download_pack(remote->transport, remote->repo, bytes, stats);
}
/* Receiving data from a socket and storing it is pretty much the same for git and HTTP */
int git_fetch__download_pack(
- char **out,
const char *buffered,
size_t buffered_size,
GIT_SOCKET fd,
- git_repository *repo)
+ git_repository *repo,
+ git_off_t *bytes,
+ git_indexer_stats *stats)
{
- git_filebuf file = GIT_FILEBUF_INIT;
- int error;
+ int recvd;
char buff[1024];
- git_buf path = GIT_BUF_INIT;
- static const char suff[] = "/objects/pack/pack-received";
gitno_buffer buf;
+ git_indexer_stream *idx;
gitno_buffer_setup(&buf, buff, sizeof(buff), fd);
return -1;
}
- if (git_buf_joinpath(&path, repo->path_repository, suff) < 0)
- goto on_error;
+ if (git_indexer_stream_new(&idx, git_repository_path(repo)) < 0)
+ return -1;
- if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_TEMPORARY) < 0)
+ memset(stats, 0, sizeof(git_indexer_stats));
+ if (git_indexer_stream_add(idx, buffered, buffered_size, stats) < 0)
goto on_error;
- /* Part of the packfile has been received, don't loose it */
- if (git_filebuf_write(&file, buffered, buffered_size) < 0)
- goto on_error;
+ *bytes = buffered_size;
- while (1) {
- if (git_filebuf_write(&file, buf.data, buf.offset) < 0)
+ do {
+ if (git_indexer_stream_add(idx, buf.data, buf.offset, stats) < 0)
goto on_error;
gitno_consume_n(&buf, buf.offset);
- error = gitno_recv(&buf);
- if (error < GIT_SUCCESS)
+ if ((recvd = gitno_recv(&buf)) < 0)
goto on_error;
- if (error == 0) /* Orderly shutdown */
- break;
- }
- *out = git__strdup(file.path_lock);
- if (*out == NULL)
- goto on_error;
+ *bytes += recvd;
+ } while(recvd > 0);
- /* A bit dodgy, but we need to keep the pack at the temporary path */
- if (git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE) < 0)
+ if (git_indexer_stream_finalize(idx, stats))
goto on_error;
- git_buf_free(&path);
-
+ git_indexer_stream_free(idx);
return 0;
+
on_error:
- git_buf_free(&path);
- git_filebuf_cleanup(&file);
+ git_indexer_stream_free(idx);
return -1;
}
#include "netops.h"
int git_fetch_negotiate(git_remote *remote);
-int git_fetch_download_pack(char **out, git_remote *remote);
+int git_fetch_download_pack(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats);
-int git_fetch__download_pack(char **out, const char *buffered, size_t buffered_size,
- GIT_SOCKET fd, git_repository *repo);
+int git_fetch__download_pack(const char *buffered, size_t buffered_size, GIT_SOCKET fd,
+ git_repository *repo, git_off_t *bytes, git_indexer_stats *stats);
#endif
return remote->transport->ls(remote->transport, list_cb, payload);
}
-int git_remote_download(char **filename, git_remote *remote)
+int git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats)
{
int error;
- assert(filename && remote);
+ assert(remote && bytes && stats);
if ((error = git_fetch_negotiate(remote)) < 0)
return error;
- return git_fetch_download_pack(filename, remote);
+ return git_fetch_download_pack(remote, bytes, stats);
}
int git_remote_update_tips(git_remote *remote)
/**
* Download the packfile
*/
- int (*download_pack)(char **out, struct git_transport *transport, git_repository *repo);
+ int (*download_pack)(struct git_transport *transport, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats);
/**
* Fetch the changes
*/
return git_pkt_send_done(t->socket);
}
-static int git_download_pack(char **out, git_transport *transport, git_repository *repo)
+static int git_download_pack(git_transport *transport, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats)
{
transport_git *t = (transport_git *) transport;
int error = 0, read_bytes;
if (pkt->type == GIT_PKT_PACK) {
git__free(pkt);
- return git_fetch__download_pack(out, buf->data, buf->offset, t->socket, repo);
+ return git_fetch__download_pack(buf->data, buf->offset, t->socket, repo, bytes, stats);
}
/* For now we don't care about anything */
}
typedef struct {
- git_filebuf *file;
+ git_indexer_stream *idx;
+ git_indexer_stats *stats;
transport_http *transport;
} download_pack_cbdata;
{
download_pack_cbdata *data = (download_pack_cbdata *) parser->data;
transport_http *t = data->transport;
- git_filebuf *file = data->file;
+ git_indexer_stream *idx = data->idx;
+ git_indexer_stats *stats = data->stats;
-
- return t->error = git_filebuf_write(file, str, len);
+ return t->error = git_indexer_stream_add(idx, str, len, stats);
}
/*
* the simple downloader. Furthermore, we're using keep-alive
* connections, so the simple downloader would just hang.
*/
-static int http_download_pack(char **out, git_transport *transport, git_repository *repo)
+static int http_download_pack(git_transport *transport, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats)
{
transport_http *t = (transport_http *) transport;
git_buf *oldbuf = &t->buf;
- int ret = 0;
+ int recvd;
http_parser_settings settings;
char buffer[1024];
gitno_buffer buf;
+ git_indexer_stream *idx = NULL;
download_pack_cbdata data;
- git_filebuf file = GIT_FILEBUF_INIT;
- git_buf path = GIT_BUF_INIT;
- char suff[] = "/objects/pack/pack-received\0";
+
+ gitno_buffer_setup(&buf, buffer, sizeof(buffer), t->socket);
+
+ if (memcmp(oldbuf->ptr, "PACK", strlen("PACK"))) {
+ giterr_set(GITERR_NET, "The pack doesn't start with a pack signature");
+ return -1;
+ }
+
+ if (git_indexer_stream_new(&idx, git_repository_path(repo)) < 0)
+ return -1;
+
/*
* This is part of the previous response, so we don't want to
* re-init the parser, just set these two callbacks.
*/
- data.file = &file;
+ memset(stats, 0, sizeof(git_indexer_stats));
+ data.stats = stats;
+ data.idx = idx;
data.transport = t;
t->parser.data = &data;
t->transfer_finished = 0;
memset(&settings, 0x0, sizeof(settings));
settings.on_message_complete = on_message_complete_download_pack;
settings.on_body = on_body_download_pack;
+ *bytes = oldbuf->size;
- gitno_buffer_setup(&buf, buffer, sizeof(buffer), t->socket);
-
- if (memcmp(oldbuf->ptr, "PACK", strlen("PACK"))) {
- giterr_set(GITERR_NET, "The pack doesn't start with a pack signature");
- return -1;
- }
-
- if (git_buf_joinpath(&path, repo->path_repository, suff) < 0)
- goto on_error;
-
- if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_TEMPORARY) < 0)
- goto on_error;
-
- /* Part of the packfile has been received, don't loose it */
- if (git_filebuf_write(&file, oldbuf->ptr, oldbuf->size) < 0)
+ if (git_indexer_stream_add(idx, oldbuf->ptr, oldbuf->size, stats) < 0)
goto on_error;
- while(1) {
+ do {
size_t parsed;
- ret = gitno_recv(&buf);
- if (ret < 0)
+ if ((recvd = gitno_recv(&buf)) < 0)
goto on_error;
parsed = http_parser_execute(&t->parser, &settings, buf.data, buf.offset);
- /* Both should happen at the same time */
if (parsed != buf.offset || t->error < 0)
- return t->error;
+ goto on_error;
+ *bytes += recvd;
gitno_consume_n(&buf, parsed);
+ } while (recvd > 0 && !t->transfer_finished);
- if (ret == 0 || t->transfer_finished) {
- break;
- }
- }
-
- *out = git__strdup(file.path_lock);
- GITERR_CHECK_ALLOC(*out);
-
- /* A bit dodgy, but we need to keep the pack at the temporary path */
- ret = git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE);
-
- git_buf_free(&path);
+ if (git_indexer_stream_finalize(idx, stats) < 0)
+ goto on_error;
+ git_indexer_stream_free(idx);
return 0;
on_error:
- git_filebuf_cleanup(&file);
- git_buf_free(&path);
+ git_indexer_stream_free(idx);
return -1;
}