1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-06-09 16:26:46 +02:00

Merge branch 'fc/transport-helper-error-reporting'

Update transport helper to report errors and maintain ref hierarchy
used to keep track of remote helper state better.

* fc/transport-helper-error-reporting:
  transport-helper: fix remote helper namespace regression
  test: remote-helper: add missing and
  t5801: "VAR=VAL shell_func args" is forbidden
  transport-helper: update remote helper namespace
  transport-helper: trivial code shuffle
  transport-helper: warn when refspec is not used
  transport-helper: clarify pushing without refspecs
  transport-helper: update refspec documentation
  transport-helper: clarify *:* refspec
  transport-helper: improve push messages
  transport-helper: mention helper name when it dies
  transport-helper: report errors properly
This commit is contained in:
Junio C Hamano 2013-05-29 14:20:16 -07:00
commit 766f0f8ef7
4 changed files with 118 additions and 43 deletions

View File

@ -159,11 +159,11 @@ Miscellaneous capabilities
carried out.
'refspec' <refspec>::
This modifies the 'import' capability, allowing the produced
fast-import stream to modify refs in a private namespace
instead of writing to refs/heads or refs/remotes directly.
For remote helpers that implement 'import' or 'export', this capability
allows the refs to be constrained to a private namespace, instead of
writing to refs/heads or refs/remotes directly.
It is recommended that all importers providing the 'import'
capability use this.
capability use this. It's mandatory for 'export'.
+
A helper advertising the capability
`refspec refs/heads/*:refs/svn/origin/branches/*`
@ -174,8 +174,8 @@ ref.
This capability can be advertised multiple times. The first
applicable refspec takes precedence. The left-hand of refspecs
advertised with this capability must cover all refs reported by
the list command. If a helper does not need a specific 'refspec'
capability then it should advertise `refspec *:*`.
the list command. If no 'refspec' capability is advertised,
there is an implied `refspec *:*`.
'bidi-import'::
This modifies the 'import' capability.

View File

@ -62,12 +62,31 @@ do
echo "feature import-marks=$gitmarks"
echo "feature export-marks=$gitmarks"
fi
if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
then
echo "feature done"
exit 1
fi
echo "feature done"
git fast-export "${testgitmarks_args[@]}" $refs |
sed -e "s#refs/heads/#${prefix}/heads/#g"
echo "done"
;;
export)
if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
then
# consume input so fast-export doesn't get SIGPIPE;
# git would also notice that case, but we want
# to make sure we are exercising the later
# error checks
while read line; do
test "done" = "$line" && break
done
exit 1
fi
before=$(git for-each-ref --format='%(refname) %(objectname)')
git fast-import "${testgitmarks_args[@]}" --quiet
@ -79,7 +98,12 @@ do
while read ref a b
do
test $a == $b && continue
echo "ok $ref"
if test -z "$GIT_REMOTE_TESTGIT_PUSH_ERROR"
then
echo "ok $ref"
else
echo "error $ref $GIT_REMOTE_TESTGIT_PUSH_ERROR"
fi
done
echo

View File

@ -101,39 +101,28 @@ test_expect_failure 'push new branch with old:new refspec' '
test_expect_success 'cloning without refspec' '
GIT_REMOTE_TESTGIT_REFSPEC="" \
git clone "testgit::${PWD}/server" local2 &&
git clone "testgit::${PWD}/server" local2 2>error &&
grep "This remote helper should implement refspec capability" error &&
compare_refs local2 HEAD server HEAD
'
test_expect_success 'pulling without refspecs' '
(cd local2 &&
git reset --hard &&
GIT_REMOTE_TESTGIT_REFSPEC="" git pull) &&
GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) &&
grep "This remote helper should implement refspec capability" error &&
compare_refs local2 HEAD server HEAD
'
test_expect_failure 'pushing without refspecs' '
test_expect_success 'pushing without refspecs' '
test_when_finished "(cd local2 && git reset --hard origin)" &&
(cd local2 &&
echo content >>file &&
git commit -a -m ten &&
GIT_REMOTE_TESTGIT_REFSPEC="" git push) &&
compare_refs local2 HEAD server HEAD
'
test_expect_success 'pulling with straight refspec' '
(cd local2 &&
GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) &&
compare_refs local2 HEAD server HEAD
'
test_expect_failure 'pushing with straight refspec' '
test_when_finished "(cd local2 && git reset --hard origin)" &&
(cd local2 &&
echo content >>file &&
git commit -a -m eleven &&
GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) &&
compare_refs local2 HEAD server HEAD
GIT_REMOTE_TESTGIT_REFSPEC="" &&
export GIT_REMOTE_TESTGIT_REFSPEC &&
test_must_fail git push 2>../error) &&
grep "remote-helper doesn.t support push; refspec needed" error
'
test_expect_success 'pulling without marks' '
@ -186,6 +175,52 @@ test_expect_success GPG 'push signed tag with signed-tags capability' '
compare_refs local signed-tag-2 server signed-tag-2
'
test_expect_success 'push update refs' '
(cd local &&
git checkout -b update master &&
echo update >>file &&
git commit -a -m update &&
git push origin update &&
git rev-parse --verify remotes/origin/update >expect &&
git rev-parse --verify testgit/origin/heads/update >actual &&
test_cmp expect actual
)
'
test_expect_success 'push update refs failure' '
(cd local &&
git checkout update &&
echo "update fail" >>file &&
git commit -a -m "update fail" &&
git rev-parse --verify testgit/origin/heads/update >expect &&
GIT_REMOTE_TESTGIT_PUSH_ERROR="non-fast forward" &&
export GIT_REMOTE_TESTGIT_PUSH_ERROR &&
test_expect_code 1 git push origin update &&
git rev-parse --verify testgit/origin/heads/update >actual &&
test_cmp expect actual
)
'
test_expect_success 'proper failure checks for fetching' '
(GIT_REMOTE_TESTGIT_FAILURE=1 &&
export GIT_REMOTE_TESTGIT_FAILURE &&
cd local &&
test_must_fail git fetch 2> error &&
cat error &&
grep -q "Error while running fast-import" error
)
'
test_expect_success 'proper failure checks for pushing' '
(GIT_REMOTE_TESTGIT_FAILURE=1 &&
export GIT_REMOTE_TESTGIT_FAILURE &&
cd local &&
test_must_fail git push --all 2> error &&
cat error &&
grep -q "Reading from helper .git-remote-testgit. failed" error
)
'
test_expect_success 'push messages' '
(cd local &&
git checkout -b new_branch master &&

View File

@ -11,6 +11,7 @@
#include "thread-utils.h"
#include "sigchain.h"
#include "argv-array.h"
#include "refs.h"
static int debug;
@ -47,7 +48,7 @@ static void sendline(struct helper_data *helper, struct strbuf *buffer)
die_errno("Full write to remote helper failed");
}
static int recvline_fh(FILE *helper, struct strbuf *buffer)
static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
{
strbuf_reset(buffer);
if (debug)
@ -55,7 +56,7 @@ static int recvline_fh(FILE *helper, struct strbuf *buffer)
if (strbuf_getline(buffer, helper, '\n') == EOF) {
if (debug)
fprintf(stderr, "Debug: Remote helper quit.\n");
exit(128);
die("Reading from helper 'git-remote-%s' failed", name);
}
if (debug)
@ -65,7 +66,7 @@ static int recvline_fh(FILE *helper, struct strbuf *buffer)
static int recvline(struct helper_data *helper, struct strbuf *buffer)
{
return recvline_fh(helper->out, buffer);
return recvline_fh(helper->out, buffer, helper->name);
}
static void xchgline(struct helper_data *helper, struct strbuf *buffer)
@ -217,6 +218,8 @@ static struct child_process *get_helper(struct transport *transport)
for (i = 0; i < refspec_nr; i++)
free((char *)refspecs[i]);
free(refspecs);
} else if (data->import || data->bidi_import || data->export) {
warning("This remote helper should implement refspec capability.");
}
strbuf_release(&buf);
if (debug)
@ -473,7 +476,7 @@ static int fetch_with_import(struct transport *transport,
* were fetching.
*
* (If no "refspec" capability was specified, for historical
* reasons we default to *:*.)
* reasons we default to the equivalent of *:*.)
*
* Store the result in to_fetch[i].old_sha1. Callers such
* as "git fetch" can use the value to write feedback to the
@ -540,7 +543,7 @@ static int process_connect_service(struct transport *transport,
goto exit;
sendline(data, &cmdbuf);
recvline_fh(input, &cmdbuf);
recvline_fh(input, &cmdbuf, name);
if (!strcmp(cmdbuf.buf, "")) {
data->no_disconnect_req = 1;
if (debug)
@ -622,7 +625,7 @@ static int fetch(struct transport *transport,
return -1;
}
static void push_update_ref_status(struct strbuf *buf,
static int push_update_ref_status(struct strbuf *buf,
struct ref **ref,
struct ref *remote_refs)
{
@ -688,7 +691,7 @@ static void push_update_ref_status(struct strbuf *buf,
*ref = find_ref_by_name(remote_refs, refname);
if (!*ref) {
warning("helper reported unexpected status of %s", refname);
return;
return 1;
}
if ((*ref)->status != REF_STATUS_NONE) {
@ -697,11 +700,12 @@ static void push_update_ref_status(struct strbuf *buf,
* status reported by the remote helper if the latter is 'no match'.
*/
if (status == REF_STATUS_NONE)
return;
return 1;
}
(*ref)->status = status;
(*ref)->remote_status = msg;
return !(status == REF_STATUS_OK);
}
static void push_update_refs_status(struct helper_data *data,
@ -710,11 +714,24 @@ static void push_update_refs_status(struct helper_data *data,
struct strbuf buf = STRBUF_INIT;
struct ref *ref = remote_refs;
for (;;) {
char *private;
recvline(data, &buf);
if (!buf.len)
break;
push_update_ref_status(&buf, &ref, remote_refs);
if (push_update_ref_status(&buf, &ref, remote_refs))
continue;
if (!data->refspecs)
continue;
/* propagate back the update to the remote namespace */
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (!private)
continue;
update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0);
free(private);
}
strbuf_release(&buf);
}
@ -789,6 +806,9 @@ static int push_refs_with_export(struct transport *transport,
struct string_list revlist_args = STRING_LIST_INIT_NODUP;
struct strbuf buf = STRBUF_INIT;
if (!data->refspecs)
die("remote-helper doesn't support push; refspec needed");
helper = get_helper(transport);
write_constant(helper->in, "export\n");
@ -799,8 +819,9 @@ static int push_refs_with_export(struct transport *transport,
char *private;
unsigned char sha1[20];
if (!data->refspecs)
continue;
if (ref->deletion)
die("remote-helpers do not support ref deletion");
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (private && !get_sha1(private, sha1)) {
strbuf_addf(&buf, "^%s", private);
@ -809,13 +830,8 @@ static int push_refs_with_export(struct transport *transport,
}
free(private);
if (ref->deletion) {
die("remote-helpers do not support ref deletion");
}
if (ref->peer_ref)
string_list_append(&revlist_args, ref->peer_ref->name);
}
if (get_exporter(transport, &exporter, &revlist_args))