mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 02:56:17 +00:00
push: support push-options
Push options are an optional capability of a git server. If they are listed in the servers capabilities, when the client lists push-options in it's list of capabilities, then the client sends it's list of push options followed by a flush-pkt. So, If we have any declared push options, then we will list it as a client capability, and send the options. If the request contains push options but the server has no push options capability, then error.
This commit is contained in:
@@ -812,6 +812,11 @@ typedef struct {
|
||||
* Extra headers for this push operation
|
||||
*/
|
||||
git_strarray custom_headers;
|
||||
|
||||
/**
|
||||
* Push options
|
||||
*/
|
||||
git_strarray push_options;
|
||||
} git_push_options;
|
||||
|
||||
#define GIT_PUSH_OPTIONS_VERSION 1
|
||||
|
||||
@@ -26,6 +26,9 @@ typedef enum {
|
||||
|
||||
/** Remote supports fetching an individual reachable object. */
|
||||
GIT_REMOTE_CAPABILITY_REACHABLE_OID = (1 << 1),
|
||||
|
||||
/** Remote supports push options. */
|
||||
GIT_REMOTE_CAPABILITY_PUSH_OPTIONS = (1 << 2),
|
||||
} git_remote_capability_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,6 +68,14 @@ int git_push_new(git_push **out, git_remote *remote, const git_push_options *opt
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_vector_init(&p->push_options, 0, git__strcmp_cb) < 0) {
|
||||
git_vector_free(&p->status);
|
||||
git_vector_free(&p->specs);
|
||||
git_vector_free(&p->updates);
|
||||
git__free(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = p;
|
||||
return 0;
|
||||
}
|
||||
@@ -472,12 +480,23 @@ static int filter_refs(git_remote *remote)
|
||||
int git_push_finish(git_push *push)
|
||||
{
|
||||
int error;
|
||||
unsigned int remote_caps;
|
||||
|
||||
if (!git_remote_connected(push->remote)) {
|
||||
git_error_set(GIT_ERROR_NET, "remote is disconnected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = git_remote_capabilities(&remote_caps, push->remote)) < 0){
|
||||
git_error_set(GIT_ERROR_INVALID, "remote capabilities not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_vector_length(&push->push_options) > 0 && !(remote_caps & GIT_REMOTE_CAPABILITY_PUSH_OPTIONS)) {
|
||||
git_error_set(GIT_ERROR_INVALID, "push-options not supported by remote");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = filter_refs(push->remote)) < 0 ||
|
||||
(error = do_push(push)) < 0)
|
||||
return error;
|
||||
@@ -521,6 +540,7 @@ void git_push_free(git_push *push)
|
||||
push_spec *spec;
|
||||
push_status *status;
|
||||
git_push_update *update;
|
||||
char *option;
|
||||
unsigned int i;
|
||||
|
||||
if (push == NULL)
|
||||
@@ -543,6 +563,11 @@ void git_push_free(git_push *push)
|
||||
}
|
||||
git_vector_free(&push->updates);
|
||||
|
||||
git_vector_foreach(&push->push_options, i, option) {
|
||||
git__free(option);
|
||||
}
|
||||
git_vector_free(&push->push_options);
|
||||
|
||||
git__free(push);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ struct git_push {
|
||||
git_vector specs;
|
||||
git_vector updates;
|
||||
bool report_status;
|
||||
git_vector push_options;
|
||||
|
||||
/* report-status */
|
||||
bool unpack_ok;
|
||||
|
||||
@@ -2958,6 +2958,13 @@ int git_remote_upload(
|
||||
}
|
||||
}
|
||||
|
||||
if (opts && opts->push_options.count > 0)
|
||||
for (i = 0; i < opts->push_options.count; ++i) {
|
||||
if ((error = git_vector_insert(&push->push_options, git__strdup(opts->push_options.strings[i]))) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = git_push_finish(push)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
@@ -233,6 +233,9 @@ static int git_smart__capabilities(unsigned int *capabilities, git_transport *tr
|
||||
|
||||
*capabilities = 0;
|
||||
|
||||
if (t->caps.push_options)
|
||||
*capabilities |= GIT_REMOTE_CAPABILITY_PUSH_OPTIONS;
|
||||
|
||||
if (t->caps.want_tip_sha1)
|
||||
*capabilities |= GIT_REMOTE_CAPABILITY_TIP_OID;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define GIT_CAP_SYMREF "symref"
|
||||
#define GIT_CAP_WANT_TIP_SHA1 "allow-tip-sha1-in-want"
|
||||
#define GIT_CAP_WANT_REACHABLE_SHA1 "allow-reachable-sha1-in-want"
|
||||
#define GIT_CAP_PUSH_OPTIONS "push-options"
|
||||
|
||||
extern bool git_smart__ofs_delta_enabled;
|
||||
|
||||
@@ -132,7 +133,8 @@ typedef struct transport_smart_caps {
|
||||
report_status:1,
|
||||
thin_pack:1,
|
||||
want_tip_sha1:1,
|
||||
want_reachable_sha1:1;
|
||||
want_reachable_sha1:1,
|
||||
push_options:1;
|
||||
} transport_smart_caps;
|
||||
|
||||
typedef int (*packetsize_cb)(size_t received, void *payload);
|
||||
|
||||
@@ -190,6 +190,12 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!git__prefixcmp(ptr, GIT_CAP_PUSH_OPTIONS)) {
|
||||
caps->common = caps->push_options = 1;
|
||||
ptr += strlen(GIT_CAP_PUSH_OPTIONS);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!git__prefixcmp(ptr, GIT_CAP_THIN_PACK)) {
|
||||
caps->common = caps->thin_pack = 1;
|
||||
ptr += strlen(GIT_CAP_THIN_PACK);
|
||||
@@ -642,6 +648,7 @@ done:
|
||||
static int gen_pktline(git_str *buf, git_push *push)
|
||||
{
|
||||
push_spec *spec;
|
||||
char *option;
|
||||
size_t i, len;
|
||||
char old_id[GIT_OID_SHA1_HEXSIZE+1], new_id[GIT_OID_SHA1_HEXSIZE+1];
|
||||
|
||||
@@ -654,6 +661,8 @@ static int gen_pktline(git_str *buf, git_push *push)
|
||||
++len; /* '\0' */
|
||||
if (push->report_status)
|
||||
len += strlen(GIT_CAP_REPORT_STATUS) + 1;
|
||||
if (git_vector_length(&push->push_options) > 0)
|
||||
len += strlen(GIT_CAP_PUSH_OPTIONS) + 1;
|
||||
len += strlen(GIT_CAP_SIDE_BAND_64K) + 1;
|
||||
}
|
||||
|
||||
@@ -669,6 +678,10 @@ static int gen_pktline(git_str *buf, git_push *push)
|
||||
git_str_putc(buf, ' ');
|
||||
git_str_printf(buf, GIT_CAP_REPORT_STATUS);
|
||||
}
|
||||
if (git_vector_length(&push->push_options) > 0) {
|
||||
git_str_putc(buf, ' ');
|
||||
git_str_printf(buf, GIT_CAP_PUSH_OPTIONS);
|
||||
}
|
||||
git_str_putc(buf, ' ');
|
||||
git_str_printf(buf, GIT_CAP_SIDE_BAND_64K);
|
||||
}
|
||||
@@ -676,6 +689,12 @@ static int gen_pktline(git_str *buf, git_push *push)
|
||||
git_str_putc(buf, '\n');
|
||||
}
|
||||
|
||||
if (git_vector_length(&push->push_options) > 0) {
|
||||
git_str_printf(buf, "0000");
|
||||
git_vector_foreach(&push->push_options, i, option) {
|
||||
git_str_printf(buf, "%04"PRIxZ"%s", strlen(option) + 4 , option);
|
||||
}
|
||||
}
|
||||
git_str_puts(buf, "0000");
|
||||
return git_str_oom(buf) ? -1 : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user