mirror of https://github.com/git/git.git
Merge branch 'bc/smart-http-atomic-push'
The atomic push over smart HTTP transport did not work, which has been corrected. * bc/smart-http-atomic-push: remote-curl: pass on atomic capability to remote side
This commit is contained in:
commit
d45d771978
|
@ -509,6 +509,11 @@ set by Git if the remote helper has the 'option' capability.
|
||||||
Indicate that only the objects wanted need to be fetched, not
|
Indicate that only the objects wanted need to be fetched, not
|
||||||
their dependents.
|
their dependents.
|
||||||
|
|
||||||
|
'option atomic' {'true'|'false'}::
|
||||||
|
When pushing, request the remote server to update refs in a single atomic
|
||||||
|
transaction. If successful, all refs will be updated, or none will. If the
|
||||||
|
remote side does not support this capability, the push will fail.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkgit:git-remote[1]
|
linkgit:git-remote[1]
|
||||||
|
|
|
@ -40,7 +40,8 @@ struct options {
|
||||||
push_cert : 2,
|
push_cert : 2,
|
||||||
deepen_relative : 1,
|
deepen_relative : 1,
|
||||||
from_promisor : 1,
|
from_promisor : 1,
|
||||||
no_dependents : 1;
|
no_dependents : 1,
|
||||||
|
atomic : 1;
|
||||||
};
|
};
|
||||||
static struct options options;
|
static struct options options;
|
||||||
static struct string_list cas_options = STRING_LIST_INIT_DUP;
|
static struct string_list cas_options = STRING_LIST_INIT_DUP;
|
||||||
|
@ -148,6 +149,14 @@ static int set_option(const char *name, const char *value)
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (!strcmp(name, "atomic")) {
|
||||||
|
if (!strcmp(value, "true"))
|
||||||
|
options.atomic = 1;
|
||||||
|
else if (!strcmp(value, "false"))
|
||||||
|
options.atomic = 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
} else if (!strcmp(name, "push-option")) {
|
} else if (!strcmp(name, "push-option")) {
|
||||||
if (*value != '"')
|
if (*value != '"')
|
||||||
string_list_append(&options.push_options, value);
|
string_list_append(&options.push_options, value);
|
||||||
|
@ -1196,6 +1205,8 @@ static int push_git(struct discovery *heads, int nr_spec, const char **specs)
|
||||||
argv_array_push(&args, "--signed=yes");
|
argv_array_push(&args, "--signed=yes");
|
||||||
else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
|
else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
|
||||||
argv_array_push(&args, "--signed=if-asked");
|
argv_array_push(&args, "--signed=if-asked");
|
||||||
|
if (options.atomic)
|
||||||
|
argv_array_push(&args, "--atomic");
|
||||||
if (options.verbosity == 0)
|
if (options.verbosity == 0)
|
||||||
argv_array_push(&args, "--quiet");
|
argv_array_push(&args, "--quiet");
|
||||||
else if (options.verbosity > 1)
|
else if (options.verbosity > 1)
|
||||||
|
|
|
@ -184,11 +184,12 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat
|
||||||
test_config -C "$d" http.receivepack true &&
|
test_config -C "$d" http.receivepack true &&
|
||||||
up="$HTTPD_URL"/smart/atomic-branches.git &&
|
up="$HTTPD_URL"/smart/atomic-branches.git &&
|
||||||
|
|
||||||
# Tell "$up" about two branches for now
|
# Tell "$up" about three branches for now
|
||||||
test_commit atomic1 &&
|
test_commit atomic1 &&
|
||||||
test_commit atomic2 &&
|
test_commit atomic2 &&
|
||||||
git branch collateral &&
|
git branch collateral &&
|
||||||
git push "$up" master collateral &&
|
git branch other &&
|
||||||
|
git push "$up" master collateral other &&
|
||||||
|
|
||||||
# collateral is a valid push, but should be failed by atomic push
|
# collateral is a valid push, but should be failed by atomic push
|
||||||
git checkout collateral &&
|
git checkout collateral &&
|
||||||
|
@ -226,6 +227,41 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat
|
||||||
grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output
|
grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'push --atomic fails on server-side errors' '
|
||||||
|
# Use previously set up repository
|
||||||
|
d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
|
||||||
|
test_config -C "$d" http.receivepack true &&
|
||||||
|
up="$HTTPD_URL"/smart/atomic-branches.git &&
|
||||||
|
|
||||||
|
# break ref updates for other on the remote site
|
||||||
|
mkdir "$d/refs/heads/other.lock" &&
|
||||||
|
|
||||||
|
# add the new commit to other
|
||||||
|
git branch -f other collateral &&
|
||||||
|
|
||||||
|
# --atomic should cause entire push to be rejected
|
||||||
|
test_must_fail git push --atomic "$up" atomic other 2>output &&
|
||||||
|
|
||||||
|
# the new branch should not have been created upstream
|
||||||
|
test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
|
||||||
|
|
||||||
|
# upstream should still reflect atomic2, the last thing we pushed
|
||||||
|
# successfully
|
||||||
|
git rev-parse atomic2 >expected &&
|
||||||
|
# ...to other.
|
||||||
|
git -C "$d" rev-parse refs/heads/other >actual &&
|
||||||
|
test_cmp expected actual &&
|
||||||
|
|
||||||
|
# the new branch should not have been created upstream
|
||||||
|
test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
|
||||||
|
|
||||||
|
# the failed refs should be indicated to the user
|
||||||
|
grep "^ ! .*rejected.* other -> other .*atomic transaction failed" output &&
|
||||||
|
|
||||||
|
# the collateral failure refs should be indicated to the user
|
||||||
|
grep "^ ! .*rejected.* atomic -> atomic .*atomic transaction failed" output
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'push --all can push to empty repo' '
|
test_expect_success 'push --all can push to empty repo' '
|
||||||
d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
|
d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
|
||||||
git init --bare "$d" &&
|
git init --bare "$d" &&
|
||||||
|
|
|
@ -854,6 +854,10 @@ static void set_common_push_options(struct transport *transport,
|
||||||
die(_("helper %s does not support --signed=if-asked"), name);
|
die(_("helper %s does not support --signed=if-asked"), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & TRANSPORT_PUSH_ATOMIC)
|
||||||
|
if (set_helper_option(transport, TRANS_OPT_ATOMIC, "true") != 0)
|
||||||
|
die(_("helper %s does not support --atomic"), name);
|
||||||
|
|
||||||
if (flags & TRANSPORT_PUSH_OPTIONS) {
|
if (flags & TRANSPORT_PUSH_OPTIONS) {
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
for_each_string_list_item(item, transport->push_options)
|
for_each_string_list_item(item, transport->push_options)
|
||||||
|
|
|
@ -208,6 +208,9 @@ void transport_check_allowed(const char *type);
|
||||||
/* Filter objects for partial clone and fetch */
|
/* Filter objects for partial clone and fetch */
|
||||||
#define TRANS_OPT_LIST_OBJECTS_FILTER "filter"
|
#define TRANS_OPT_LIST_OBJECTS_FILTER "filter"
|
||||||
|
|
||||||
|
/* Request atomic (all-or-nothing) updates when pushing */
|
||||||
|
#define TRANS_OPT_ATOMIC "atomic"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns 0 if the option was used, non-zero otherwise. Prints a
|
* Returns 0 if the option was used, non-zero otherwise. Prints a
|
||||||
* message to stderr if the option is not used.
|
* message to stderr if the option is not used.
|
||||||
|
|
Loading…
Reference in New Issue