Commit 8443ed6c by Vicent Marti

Merge pull request #2284 from jacquesg/push-progress-callback

Fire progress and update tips callbacks also for pushes.
parents 332e4f20 f70cfd34
...@@ -97,7 +97,7 @@ int fetch(git_repository *repo, int argc, char **argv) ...@@ -97,7 +97,7 @@ int fetch(git_repository *repo, int argc, char **argv)
// Set up the callbacks (only update_tips for now) // Set up the callbacks (only update_tips for now)
callbacks.update_tips = &update_cb; callbacks.update_tips = &update_cb;
callbacks.progress = &progress_cb; callbacks.sideband_progress = &progress_cb;
callbacks.credentials = cred_acquire_cb; callbacks.credentials = cred_acquire_cb;
git_remote_set_callbacks(remote, &callbacks); git_remote_set_callbacks(remote, &callbacks);
......
...@@ -32,7 +32,7 @@ GIT_EXTERN(int) git_indexer_new( ...@@ -32,7 +32,7 @@ GIT_EXTERN(int) git_indexer_new(
const char *path, const char *path,
unsigned int mode, unsigned int mode,
git_odb *odb, git_odb *odb,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_cb_payload); void *progress_cb_payload);
/** /**
......
...@@ -338,7 +338,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const gi ...@@ -338,7 +338,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const gi
GIT_EXTERN(int) git_odb_write_pack( GIT_EXTERN(int) git_odb_write_pack(
git_odb_writepack **out, git_odb_writepack **out,
git_odb *db, git_odb *db,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload); void *progress_payload);
/** /**
......
...@@ -140,7 +140,7 @@ GIT_EXTERN(int) git_packbuilder_write( ...@@ -140,7 +140,7 @@ GIT_EXTERN(int) git_packbuilder_write(
git_packbuilder *pb, git_packbuilder *pb,
const char *path, const char *path,
unsigned int mode, unsigned int mode,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_cb_payload); void *progress_cb_payload);
/** /**
......
...@@ -457,7 +457,7 @@ struct git_remote_callbacks { ...@@ -457,7 +457,7 @@ struct git_remote_callbacks {
* progress side-band will be passed to this function (this is * progress side-band will be passed to this function (this is
* the 'counting objects' output. * the 'counting objects' output.
*/ */
int (*progress)(const char *str, int len, void *data); git_transport_message_cb sideband_progress;
/** /**
* Completion is called when different parts of the download * Completion is called when different parts of the download
...@@ -472,14 +472,14 @@ struct git_remote_callbacks { ...@@ -472,14 +472,14 @@ struct git_remote_callbacks {
* Returning GIT_PASSTHROUGH will make libgit2 behave as * Returning GIT_PASSTHROUGH will make libgit2 behave as
* though this field isn't set. * though this field isn't set.
*/ */
int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); git_cred_acquire_cb credentials;
/** /**
* During the download of new data, this will be regularly * During the download of new data, this will be regularly
* called with the current count of progress done by the * called with the current count of progress done by the
* indexer. * indexer.
*/ */
int (*transfer_progress)(const git_transfer_progress *stats, void *data); git_transfer_progress_cb transfer_progress;
/** /**
* Each time a reference is updated locally, this function * Each time a reference is updated locally, this function
......
...@@ -81,7 +81,7 @@ struct git_odb_backend { ...@@ -81,7 +81,7 @@ struct git_odb_backend {
int (* writepack)( int (* writepack)(
git_odb_writepack **, git_odb_backend *, git_odb *odb, git_odb_writepack **, git_odb_backend *, git_odb *odb,
git_transfer_progress_callback progress_cb, void *progress_payload); git_transfer_progress_cb progress_cb, void *progress_payload);
void (* free)(git_odb_backend *); void (* free)(git_odb_backend *);
}; };
......
...@@ -287,7 +287,7 @@ struct git_transport { ...@@ -287,7 +287,7 @@ struct git_transport {
git_transport *transport, git_transport *transport,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload); void *progress_payload);
/* Checks to see if the transport is connected */ /* Checks to see if the transport is connected */
......
...@@ -241,7 +241,7 @@ typedef struct git_transfer_progress { ...@@ -241,7 +241,7 @@ typedef struct git_transfer_progress {
* @param stats Structure containing information about the state of the transfer * @param stats Structure containing information about the state of the transfer
* @param payload Payload provided by caller * @param payload Payload provided by caller
*/ */
typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload); typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
/** /**
* Opaque structure representing a submodule. * Opaque structure representing a submodule.
......
...@@ -17,7 +17,7 @@ int git_fetch__download_pack( ...@@ -17,7 +17,7 @@ int git_fetch__download_pack(
git_transport *t, git_transport *t,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload); void *progress_payload);
int git_fetch_setup_walk(git_revwalk **out, git_repository *repo); int git_fetch_setup_walk(git_revwalk **out, git_repository *repo);
......
...@@ -45,7 +45,7 @@ struct git_indexer { ...@@ -45,7 +45,7 @@ struct git_indexer {
unsigned int fanout[256]; unsigned int fanout[256];
git_hash_ctx hash_ctx; git_hash_ctx hash_ctx;
git_oid hash; git_oid hash;
git_transfer_progress_callback progress_cb; git_transfer_progress_cb progress_cb;
void *progress_payload; void *progress_payload;
char objbuf[8*1024]; char objbuf[8*1024];
...@@ -120,7 +120,7 @@ int git_indexer_new( ...@@ -120,7 +120,7 @@ int git_indexer_new(
const char *prefix, const char *prefix,
unsigned int mode, unsigned int mode,
git_odb *odb, git_odb *odb,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload) void *progress_payload)
{ {
git_indexer *idx; git_indexer *idx;
......
...@@ -1051,7 +1051,7 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi ...@@ -1051,7 +1051,7 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
return error; return error;
} }
int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer_progress_callback progress_cb, void *progress_payload) int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer_progress_cb progress_cb, void *progress_payload)
{ {
size_t i, writes = 0; size_t i, writes = 0;
int error = GIT_ERROR; int error = GIT_ERROR;
......
...@@ -563,7 +563,7 @@ static void pack_backend__writepack_free(struct git_odb_writepack *_writepack) ...@@ -563,7 +563,7 @@ static void pack_backend__writepack_free(struct git_odb_writepack *_writepack)
static int pack_backend__writepack(struct git_odb_writepack **out, static int pack_backend__writepack(struct git_odb_writepack **out,
git_odb_backend *_backend, git_odb_backend *_backend,
git_odb *odb, git_odb *odb,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload) void *progress_payload)
{ {
struct pack_backend *backend; struct pack_backend *backend;
......
...@@ -1288,7 +1288,7 @@ int git_packbuilder_write( ...@@ -1288,7 +1288,7 @@ int git_packbuilder_write(
git_packbuilder *pb, git_packbuilder *pb,
const char *path, const char *path,
unsigned int mode, unsigned int mode,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_cb_payload) void *progress_cb_payload)
{ {
git_indexer *indexer; git_indexer *indexer;
......
...@@ -208,9 +208,7 @@ int git_push_update_tips( ...@@ -208,9 +208,7 @@ int git_push_update_tips(
int error = 0; int error = 0;
git_vector_foreach(&push->status, i, status) { git_vector_foreach(&push->status, i, status) {
/* If this ref update was successful (ok, not ng), it will have an empty message */ int fire_callback = 1;
if (status->msg)
continue;
/* Find the corresponding remote ref */ /* Find the corresponding remote ref */
fetch_spec = git_remote__matching_refspec(push->remote, status->ref); fetch_spec = git_remote__matching_refspec(push->remote, status->ref);
...@@ -230,25 +228,39 @@ int git_push_update_tips( ...@@ -230,25 +228,39 @@ int git_push_update_tips(
if (j == push->specs.length) if (j == push->specs.length)
continue; continue;
/* If this ref update was successful (ok, not ng), it will have an empty message */
if (status->msg == NULL) {
/* Update the remote ref */ /* Update the remote ref */
if (git_oid_iszero(&push_spec->loid)) { if (git_oid_iszero(&push_spec->loid)) {
error = git_reference_lookup(&remote_ref, push->remote->repo, git_buf_cstr(&remote_ref_name)); error = git_reference_lookup(&remote_ref, push->remote->repo, git_buf_cstr(&remote_ref_name));
if (!error) { if (error >= 0) {
if ((error = git_reference_delete(remote_ref)) < 0) { error = git_reference_delete(remote_ref);
git_reference_free(remote_ref); git_reference_free(remote_ref);
goto on_error;
} }
git_reference_free(remote_ref); } else {
} else if (error == GIT_ENOTFOUND) error = git_reference_create(NULL, push->remote->repo,
giterr_clear();
else
goto on_error;
} else if ((error = git_reference_create(NULL, push->remote->repo,
git_buf_cstr(&remote_ref_name), &push_spec->loid, 1, signature, git_buf_cstr(&remote_ref_name), &push_spec->loid, 1, signature,
reflog_message ? reflog_message : "update by push")) < 0) reflog_message ? reflog_message : "update by push");
}
}
if (error < 0) {
if (error != GIT_ENOTFOUND)
goto on_error;
giterr_clear();
fire_callback = 0;
}
if (fire_callback && push->remote->callbacks.update_tips) {
error = push->remote->callbacks.update_tips(git_buf_cstr(&remote_ref_name),
&push_spec->roid, &push_spec->loid, push->remote->callbacks.payload);
if (error < 0)
goto on_error; goto on_error;
} }
}
error = 0; error = 0;
...@@ -677,9 +689,7 @@ void git_push_status_free(push_status *status) ...@@ -677,9 +689,7 @@ void git_push_status_free(push_status *status)
if (status == NULL) if (status == NULL)
return; return;
if (status->msg)
git__free(status->msg); git__free(status->msg);
git__free(status->ref); git__free(status->ref);
git__free(status); git__free(status);
} }
......
...@@ -663,7 +663,7 @@ int git_remote_connect(git_remote *remote, git_direction direction) ...@@ -663,7 +663,7 @@ int git_remote_connect(git_remote *remote, git_direction direction)
return error; return error;
if (t->set_callbacks && if (t->set_callbacks &&
(error = t->set_callbacks(t, remote->callbacks.progress, NULL, remote->callbacks.payload)) < 0) (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.payload)) < 0)
goto on_error; goto on_error;
if (!remote->check_cert) if (!remote->check_cert)
...@@ -1246,7 +1246,7 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal ...@@ -1246,7 +1246,7 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal
if (remote->transport && remote->transport->set_callbacks) if (remote->transport && remote->transport->set_callbacks)
return remote->transport->set_callbacks(remote->transport, return remote->transport->set_callbacks(remote->transport,
remote->callbacks.progress, remote->callbacks.sideband_progress,
NULL, NULL,
remote->callbacks.payload); remote->callbacks.payload);
......
...@@ -472,7 +472,7 @@ on_error: ...@@ -472,7 +472,7 @@ on_error:
typedef struct foreach_data { typedef struct foreach_data {
git_transfer_progress *stats; git_transfer_progress *stats;
git_transfer_progress_callback progress_cb; git_transfer_progress_cb progress_cb;
void *progress_payload; void *progress_payload;
git_odb_writepack *writepack; git_odb_writepack *writepack;
} foreach_data; } foreach_data;
...@@ -489,7 +489,7 @@ static int local_download_pack( ...@@ -489,7 +489,7 @@ static int local_download_pack(
git_transport *transport, git_transport *transport,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload) void *progress_payload)
{ {
transport_local *t = (transport_local*)transport; transport_local *t = (transport_local*)transport;
......
...@@ -167,7 +167,7 @@ int git_smart__download_pack( ...@@ -167,7 +167,7 @@ int git_smart__download_pack(
git_transport *transport, git_transport *transport,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload); void *progress_payload);
/* smart.c */ /* smart.c */
......
...@@ -153,7 +153,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len) ...@@ -153,7 +153,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
return 0; return 0;
} }
static int progress_pkt(git_pkt **out, const char *line, size_t len) static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
{ {
git_pkt_progress *pkt; git_pkt_progress *pkt;
...@@ -403,7 +403,7 @@ int git_pkt_parse_line( ...@@ -403,7 +403,7 @@ int git_pkt_parse_line(
if (*line == GIT_SIDE_BAND_DATA) if (*line == GIT_SIDE_BAND_DATA)
ret = data_pkt(head, line, len); ret = data_pkt(head, line, len);
else if (*line == GIT_SIDE_BAND_PROGRESS) else if (*line == GIT_SIDE_BAND_PROGRESS)
ret = progress_pkt(head, line, len); ret = sideband_progress_pkt(head, line, len);
else if (*line == GIT_SIDE_BAND_ERROR) else if (*line == GIT_SIDE_BAND_ERROR)
ret = sideband_error_pkt(head, line, len); ret = sideband_error_pkt(head, line, len);
else if (!git__prefixcmp(line, "ACK")) else if (!git__prefixcmp(line, "ACK"))
......
...@@ -450,7 +450,7 @@ static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, ...@@ -450,7 +450,7 @@ static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack,
struct network_packetsize_payload struct network_packetsize_payload
{ {
git_transfer_progress_callback callback; git_transfer_progress_cb callback;
void *payload; void *payload;
git_transfer_progress *stats; git_transfer_progress *stats;
size_t last_fired_bytes; size_t last_fired_bytes;
...@@ -478,7 +478,7 @@ int git_smart__download_pack( ...@@ -478,7 +478,7 @@ int git_smart__download_pack(
git_transport *transport, git_transport *transport,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb transfer_progress_cb,
void *progress_payload) void *progress_payload)
{ {
transport_smart *t = (transport_smart *)transport; transport_smart *t = (transport_smart *)transport;
...@@ -490,8 +490,8 @@ int git_smart__download_pack( ...@@ -490,8 +490,8 @@ int git_smart__download_pack(
memset(stats, 0, sizeof(git_transfer_progress)); memset(stats, 0, sizeof(git_transfer_progress));
if (progress_cb) { if (transfer_progress_cb) {
npp.callback = progress_cb; npp.callback = transfer_progress_cb;
npp.payload = progress_payload; npp.payload = progress_payload;
npp.stats = stats; npp.stats = stats;
t->packetsize_cb = &network_packetsize; t->packetsize_cb = &network_packetsize;
...@@ -504,7 +504,7 @@ int git_smart__download_pack( ...@@ -504,7 +504,7 @@ int git_smart__download_pack(
} }
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)) ((error = git_odb_write_pack(&writepack, odb, transfer_progress_cb, progress_payload)) != 0))
goto done; goto done;
/* /*
...@@ -518,7 +518,7 @@ int git_smart__download_pack( ...@@ -518,7 +518,7 @@ int git_smart__download_pack(
} }
do { do {
git_pkt *pkt; git_pkt *pkt = NULL;
/* Check cancellation before network call */ /* Check cancellation before network call */
if (t->cancelled.val) { if (t->cancelled.val) {
...@@ -527,40 +527,34 @@ int git_smart__download_pack( ...@@ -527,40 +527,34 @@ int git_smart__download_pack(
goto done; goto done;
} }
if ((error = recv_pkt(&pkt, buf)) < 0) if ((error = recv_pkt(&pkt, buf)) >= 0) {
goto done;
/* Check cancellation after network call */ /* Check cancellation after network call */
if (t->cancelled.val) { if (t->cancelled.val) {
giterr_clear(); giterr_clear();
error = GIT_EUSER; error = GIT_EUSER;
goto done; } else if (pkt->type == GIT_PKT_PROGRESS) {
}
if (pkt->type == GIT_PKT_PROGRESS) {
if (t->progress_cb) { if (t->progress_cb) {
git_pkt_progress *p = (git_pkt_progress *) pkt; git_pkt_progress *p = (git_pkt_progress *) pkt;
error = t->progress_cb(p->data, p->len, t->message_cb_payload); error = t->progress_cb(p->data, p->len, t->message_cb_payload);
if (error)
goto done;
} }
git__free(pkt);
} else if (pkt->type == GIT_PKT_DATA) { } else if (pkt->type == GIT_PKT_DATA) {
git_pkt_data *p = (git_pkt_data *) pkt; git_pkt_data *p = (git_pkt_data *) pkt;
error = writepack->append(writepack, p->data, p->len, stats); error = writepack->append(writepack, p->data, p->len, stats);
git__free(pkt);
if (error != 0)
goto done;
} else if (pkt->type == GIT_PKT_FLUSH) { } else if (pkt->type == GIT_PKT_FLUSH) {
/* A flush indicates the end of the packfile */ /* A flush indicates the end of the packfile */
git__free(pkt); git__free(pkt);
break; break;
} }
}
git__free(pkt);
if (error < 0)
goto done;
} while (1); } while (1);
/* /*
* Trailing execution of progress_cb, if necessary... * Trailing execution of transfer_progress_cb, if necessary...
* Only the callback through the npp datastructure currently * Only the callback through the npp datastructure currently
* updates the last_fired_bytes value. It is possible that * updates the last_fired_bytes value. It is possible that
* progress has already been reported with the correct * progress has already been reported with the correct
...@@ -579,7 +573,7 @@ int git_smart__download_pack( ...@@ -579,7 +573,7 @@ int git_smart__download_pack(
done: done:
if (writepack) if (writepack)
writepack->free(writepack); writepack->free(writepack);
if (progress_cb) { if (transfer_progress_cb) {
t->packetsize_cb = NULL; t->packetsize_cb = NULL;
t->packetsize_payload = NULL; t->packetsize_payload = NULL;
} }
...@@ -634,7 +628,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt) ...@@ -634,7 +628,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
switch (pkt->type) { switch (pkt->type) {
case GIT_PKT_OK: case GIT_PKT_OK:
status = git__calloc(1, sizeof(push_status)); status = git__calloc(sizeof(push_status), 1);
GITERR_CHECK_ALLOC(status); GITERR_CHECK_ALLOC(status);
status->msg = NULL; status->msg = NULL;
status->ref = git__strdup(((git_pkt_ok *)pkt)->ref); status->ref = git__strdup(((git_pkt_ok *)pkt)->ref);
...@@ -696,10 +690,11 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt) ...@@ -696,10 +690,11 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
return 0; return 0;
} }
static int parse_report(gitno_buffer *buf, git_push *push) static int parse_report(transport_smart *transport, git_push *push)
{ {
git_pkt *pkt = NULL; git_pkt *pkt = NULL;
const char *line_end = NULL; const char *line_end = NULL;
gitno_buffer *buf = &transport->buffer;
int error, recvd; int error, recvd;
for (;;) { for (;;) {
...@@ -738,6 +733,10 @@ static int parse_report(gitno_buffer *buf, git_push *push) ...@@ -738,6 +733,10 @@ static int parse_report(gitno_buffer *buf, git_push *push)
error = -1; error = -1;
break; break;
case GIT_PKT_PROGRESS: case GIT_PKT_PROGRESS:
if (transport->progress_cb) {
git_pkt_progress *p = (git_pkt_progress *) pkt;
error = transport->progress_cb(p->data, p->len, transport->message_cb_payload);
}
break; break;
default: default:
error = add_push_report_pkt(push, pkt); error = add_push_report_pkt(push, pkt);
...@@ -883,10 +882,7 @@ static int stream_thunk(void *buf, size_t size, void *data) ...@@ -883,10 +882,7 @@ static int stream_thunk(void *buf, size_t size, void *data)
if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
payload->last_progress_report_time = current_time; payload->last_progress_report_time = current_time;
if (payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload)) { error = payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload);
giterr_clear();
error = GIT_EUSER;
}
} }
} }
...@@ -953,12 +949,19 @@ int git_smart__push(git_transport *transport, git_push *push) ...@@ -953,12 +949,19 @@ int git_smart__push(git_transport *transport, git_push *push)
* we consider the pack to have been unpacked successfully */ * we consider the pack to have been unpacked successfully */
if (!push->specs.length || !push->report_status) if (!push->specs.length || !push->report_status)
push->unpack_ok = 1; push->unpack_ok = 1;
else if ((error = parse_report(&t->buffer, push)) < 0) else if ((error = parse_report(t, push)) < 0)
goto done; goto done;
/* If progress is being reported write the final report */ /* If progress is being reported write the final report */
if (push->transfer_progress_cb) { if (push->transfer_progress_cb) {
push->transfer_progress_cb(push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, push->transfer_progress_cb_payload); error = push->transfer_progress_cb(
push->pb->nr_written,
push->pb->nr_objects,
packbuilder_payload.last_bytes,
push->transfer_progress_cb_payload);
if (error < 0)
goto done;
} }
if (push->status.length) { if (push->status.length) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment