Commit cbe8a61d by Edward Thomson

Merge pull request #3059 from libgit2/cmn/negotiation-notify

[WIP/RFC] push: report the update plan to the caller
parents 9f73e1f3 efc2fec5
...@@ -59,6 +59,36 @@ typedef int (*git_push_transfer_progress)( ...@@ -59,6 +59,36 @@ typedef int (*git_push_transfer_progress)(
size_t bytes, size_t bytes,
void* payload); void* payload);
/**
* Represents an update which will be performed on the remote during push
*/
typedef struct {
/**
* The source name of the reference
*/
char *src_refname;
/**
* The name of the reference to update on the server
*/
char *dst_refname;
/**
* The current target of the reference
*/
git_oid src;
/**
* The new target for the reference
*/
git_oid dst;
} git_push_update;
/**
* @param updates an array containing the updates which will be sent
* as commands to the destination.
* @param len number of elements in `updates`
* @param payload Payload provided by the caller
*/
typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -521,6 +521,12 @@ struct git_remote_callbacks { ...@@ -521,6 +521,12 @@ struct git_remote_callbacks {
int (*push_update_reference)(const char *refname, const char *status, void *data); int (*push_update_reference)(const char *refname, const char *status, void *data);
/** /**
* Called once between the negotiation step and the upload. It
* provides information about what updates will be performed.
*/
git_push_negotiation push_negotiation;
/**
* This will be passed to each of the callbacks in this struct * This will be passed to each of the callbacks in this struct
* as the last parameter. * as the last parameter.
*/ */
......
...@@ -273,6 +273,7 @@ typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void ...@@ -273,6 +273,7 @@ typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void
*/ */
typedef int (*git_transport_message_cb)(const char *str, int len, void *payload); typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
/** /**
* Type of host certificate structure that is passed to the check callback * Type of host certificate structure that is passed to the check callback
*/ */
......
...@@ -54,6 +54,13 @@ int git_push_new(git_push **out, git_remote *remote) ...@@ -54,6 +54,13 @@ int git_push_new(git_push **out, git_remote *remote)
return -1; return -1;
} }
if (git_vector_init(&p->updates, 0, NULL) < 0) {
git_vector_free(&p->status);
git_vector_free(&p->specs);
git__free(p);
return -1;
}
*out = p; *out = p;
return 0; return 0;
} }
...@@ -75,7 +82,9 @@ int git_push_set_callbacks( ...@@ -75,7 +82,9 @@ int git_push_set_callbacks(
git_packbuilder_progress pack_progress_cb, git_packbuilder_progress pack_progress_cb,
void *pack_progress_cb_payload, void *pack_progress_cb_payload,
git_push_transfer_progress transfer_progress_cb, git_push_transfer_progress transfer_progress_cb,
void *transfer_progress_cb_payload) void *transfer_progress_cb_payload,
git_push_negotiation negotiation_cb,
void *negotiation_cb_payload)
{ {
if (!push) if (!push)
return -1; return -1;
...@@ -86,6 +95,9 @@ int git_push_set_callbacks( ...@@ -86,6 +95,9 @@ int git_push_set_callbacks(
push->transfer_progress_cb = transfer_progress_cb; push->transfer_progress_cb = transfer_progress_cb;
push->transfer_progress_cb_payload = transfer_progress_cb_payload; push->transfer_progress_cb_payload = transfer_progress_cb_payload;
push->negotiation_cb = negotiation_cb;
push->negotiation_cb_payload = negotiation_cb_payload;
return 0; return 0;
} }
...@@ -534,6 +546,22 @@ on_error: ...@@ -534,6 +546,22 @@ on_error:
return error; return error;
} }
static int add_update(git_push *push, push_spec *spec)
{
git_push_update *u = git__calloc(1, sizeof(git_push_update));
GITERR_CHECK_ALLOC(u);
u->src_refname = git__strdup(spec->refspec.src);
GITERR_CHECK_ALLOC(u->src_refname);
u->dst_refname = git__strdup(spec->refspec.src);
GITERR_CHECK_ALLOC(u->dst_refname);
git_oid_cpy(&u->src, &spec->loid);
git_oid_cpy(&u->dst, &spec->roid);
return git_vector_insert(&push->updates, u);
}
static int calculate_work(git_push *push) static int calculate_work(git_push *push)
{ {
git_remote_head *head; git_remote_head *head;
...@@ -559,6 +587,9 @@ static int calculate_work(git_push *push) ...@@ -559,6 +587,9 @@ static int calculate_work(git_push *push)
break; break;
} }
} }
if (add_update(push, spec) < 0)
return -1;
} }
return 0; return 0;
...@@ -590,9 +621,17 @@ static int do_push(git_push *push) ...@@ -590,9 +621,17 @@ static int do_push(git_push *push)
if ((error = git_packbuilder_set_callbacks(push->pb, push->pack_progress_cb, push->pack_progress_cb_payload)) < 0) if ((error = git_packbuilder_set_callbacks(push->pb, push->pack_progress_cb, push->pack_progress_cb_payload)) < 0)
goto on_error; goto on_error;
if ((error = calculate_work(push)) < 0 || if ((error = calculate_work(push)) < 0)
(error = queue_objects(push)) < 0 || goto on_error;
(error = transport->push(transport, push)) < 0)
if (push->negotiation_cb &&
(error = push->negotiation_cb((const git_push_update **) push->updates.contents,
push->updates.length,
push->negotiation_cb_payload)))
goto on_error;
if ((error = queue_objects(push)) < 0 ||
(error = transport->push(transport, push)) < 0)
goto on_error; goto on_error;
on_error: on_error:
......
...@@ -29,6 +29,7 @@ struct git_push { ...@@ -29,6 +29,7 @@ struct git_push {
git_packbuilder *pb; git_packbuilder *pb;
git_remote *remote; git_remote *remote;
git_vector specs; git_vector specs;
git_vector updates;
bool report_status; bool report_status;
/* report-status */ /* report-status */
...@@ -42,6 +43,8 @@ struct git_push { ...@@ -42,6 +43,8 @@ struct git_push {
void *pack_progress_cb_payload; void *pack_progress_cb_payload;
git_push_transfer_progress transfer_progress_cb; git_push_transfer_progress transfer_progress_cb;
void *transfer_progress_cb_payload; void *transfer_progress_cb_payload;
git_push_negotiation negotiation_cb;
void *negotiation_cb_payload;
}; };
/** /**
...@@ -85,6 +88,8 @@ int git_push_set_options( ...@@ -85,6 +88,8 @@ int git_push_set_options(
* the upload portion of a push. Be aware that this is called inline with * the upload portion of a push. Be aware that this is called inline with
* pack building operations, so performance may be affected. * pack building operations, so performance may be affected.
* @param transfer_progress_cb_payload Payload for the network progress callback. * @param transfer_progress_cb_payload Payload for the network progress callback.
* @param push_negotiation_cb Function to call before sending the commands to the remote.
* @param push_negotiation_cb_payload Payload for the negotiation callback
* @return 0 or an error code * @return 0 or an error code
*/ */
int git_push_set_callbacks( int git_push_set_callbacks(
...@@ -92,7 +97,9 @@ int git_push_set_callbacks( ...@@ -92,7 +97,9 @@ int git_push_set_callbacks(
git_packbuilder_progress pack_progress_cb, git_packbuilder_progress pack_progress_cb,
void *pack_progress_cb_payload, void *pack_progress_cb_payload,
git_push_transfer_progress transfer_progress_cb, git_push_transfer_progress transfer_progress_cb,
void *transfer_progress_cb_payload); void *transfer_progress_cb_payload,
git_push_negotiation negotiation_cb,
void *negotiation_cb_payload);
/** /**
* Add a refspec to be pushed * Add a refspec to be pushed
......
...@@ -2363,7 +2363,8 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi ...@@ -2363,7 +2363,8 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
cbs = &remote->callbacks; cbs = &remote->callbacks;
if ((error = git_push_set_callbacks(push, if ((error = git_push_set_callbacks(push,
cbs->pack_progress, cbs->payload, cbs->pack_progress, cbs->payload,
cbs->push_transfer_progress, cbs->payload)) < 0) cbs->push_transfer_progress, cbs->payload,
cbs->push_negotiation, cbs->payload)) < 0)
goto cleanup; goto cleanup;
if ((error = git_push_finish(push)) < 0) if ((error = git_push_finish(push)) < 0)
......
...@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; ...@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance * @param data pointer to a record_callbacks_data instance
*/ */
#define RECORD_CALLBACKS_INIT(data) \ #define RECORD_CALLBACKS_INIT(data) \
{ GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, data } { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, data }
typedef struct { typedef struct {
char *name; char *name;
......
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