commit - 2dd71cdd72c0c6c4ce607fdc73ae38fa898bfeb2
commit + 3fe5d0fee4a9e03753cf693bf839bf26cb872d54
blob - 8f5652bc11cd7acbd00b1be84dd5bb45e953f855
blob + dad0b7d03fbf6b57cc05881f0936f42db930e358
--- got/got.c
+++ got/got.c
static const struct got_error *
send_progress(void *arg, int ncolored, int nfound, int ntrees,
off_t packfile_size, int ncommits, int nobj_total, int nobj_deltify,
- int nobj_written, off_t bytes_sent, const char *refname, int success)
+ int nobj_written, off_t bytes_sent, const char *refname,
+ const char *errmsg, int success)
{
struct got_send_progress_arg *a = arg;
char scaled_packsize[FMT_SCALED_STRSIZE];
if (a->printed_something)
putchar('\n');
printf("Server has %s %s", status, refname);
+ if (errmsg)
+ printf(": %s", errmsg);
a->printed_something = 1;
return NULL;
}
blob - 19e9e4f116e70c354ec4bbff8ce7e5a1615acd1f
blob + 038b51f30308b8ca6879fdbddcfd64c6c83b7594
--- include/got_send.h
+++ include/got_send.h
typedef const struct got_error *(*got_send_progress_cb)(void *,
int ncolored, int nfound, int ntrees, off_t packfile_size, int ncommits,
int nobj_total, int nobj_deltify, int nobj_written, off_t bytes_sent,
- const char *refname, int success);
+ const char *refname, const char *, int success);
/*
* Attempt to generate a pack file and sent it to a server.
blob - c9234999b21b43c91b7595360c597b1d528f69c1
blob + 44f8d7667b1d387ae50d548b69f48ae1afba27e9
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
struct got_imsg_send_ref_status {
int success;
size_t name_len;
+ size_t errmsg_len;
/* Followed by name_len data bytes. */
+ /* Followed by errmsg_len data bytes. */
} __attribute__((__packed__));
/* Structure for GOT_IMSG_IDXPACK_REQUEST data. */
struct got_pathlist_head *, struct imsgbuf *);
const struct got_error *got_privsep_send_packfd(struct imsgbuf *, int);
const struct got_error *got_privsep_recv_send_progress(int *, off_t *,
- int *, char **, struct imsgbuf *);
+ int *, char **, char **, struct imsgbuf *);
const struct got_error *got_privsep_get_imsg_obj(struct got_object **,
struct imsg *, struct imsgbuf *);
const struct got_error *got_privsep_recv_obj(struct got_object **,
blob - 097787082caaa1182b3a16d565c2bdee8e33d6de
blob + 5462fb412f766dfe4181df6346d61dc9b5a584fb
--- lib/privsep.c
+++ lib/privsep.c
const struct got_error *
got_privsep_recv_send_progress(int *done, off_t *bytes_sent,
- int *success, char **refname, struct imsgbuf *ibuf)
+ int *success, char **refname, char **errmsg, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
struct imsg imsg;
*done = 0;
*success = 0;
*refname = NULL;
+ *errmsg = NULL;
err = got_privsep_recv_imsg(&imsg, ibuf, 0);
if (err)
break;
}
memcpy(&iref_status, imsg.data, sizeof(iref_status));
- if (datalen != sizeof(iref_status) + iref_status.name_len) {
+ if (datalen != sizeof(iref_status) + iref_status.name_len +
+ iref_status.errmsg_len) {
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
*success = iref_status.success;
*refname = strndup(imsg.data + sizeof(iref_status),
iref_status.name_len);
+
+ if (iref_status.errmsg_len != 0)
+ *errmsg = strndup(imsg.data + sizeof(iref_status) +
+ iref_status.name_len, iref_status.errmsg_len);
break;
case GOT_IMSG_SEND_DONE:
if (datalen != 0) {
blob - e2c9a83e2c62b08256e2396c00578d4f47c9aa35
blob + edb3e20183d33860e39b8ec07038fcae745ceb0f
--- lib/send.c
+++ lib/send.c
err = a->progress_cb(a->progress_arg, ncolored, nfound, ntrees,
packfile_size, ncommits, nobj_total, nobj_deltify,
- nobj_written, 0, NULL, 0);
+ nobj_written, 0, NULL, NULL, 0);
if (err)
return err;
while (!done) {
int success = 0;
char *refname = NULL;
+ char *errmsg = NULL;
+
if (cancel_cb) {
err = (*cancel_cb)(cancel_arg);
if (err)
goto done;
}
err = got_privsep_recv_send_progress(&done, &bytes_sent,
- &success, &refname, &sendibuf);
+ &success, &refname, &errmsg, &sendibuf);
if (err)
goto done;
if (refname && got_ref_name_is_valid(refname) && success &&
ppa.nfound, ppa.ntrees, ppa.packfile_size,
ppa.ncommits, ppa.nobj_total, ppa.nobj_deltify,
ppa.nobj_written, bytes_sent,
- refname, success);
+ refname, errmsg, success);
if (err) {
free(refname);
+ free(errmsg);
goto done;
}
bytes_sent_cur = bytes_sent;
}
free(refname);
+ free(errmsg);
}
done:
if (sendpid != -1) {
blob - 885867f78e6977f47b4133b83b2d41c0603514ef
blob + 40bd3e57d66c071b282b6f8d8bd9fec8fa887d49
--- libexec/got-send-pack/got-send-pack.c
+++ libexec/got-send-pack/got-send-pack.c
struct got_pathlist_head *refs, struct got_pathlist_head *delete_refs)
{
struct ibuf *wbuf;
- size_t len, reflen = strlen(refname);
+ size_t i, len, reflen, errmsglen = 0;
struct got_pathlist_entry *pe;
int ref_valid = 0;
- char *eol;
+ char *eol, *sp;
+ const char *errmsg = "";
eol = strchr(refname, '\n');
if (eol == NULL) {
"unexpected message from server");
}
*eol = '\0';
+
+ sp = strchr(refname, ' ');
+ if (sp != NULL) {
+ *sp++ = '\0';
+ errmsg = sp;
+ errmsglen = strlen(errmsg);
+
+ for (i = 0; i < errmsglen; ++i) {
+ if (!isprint((unsigned char)errmsg[i])) {
+ return got_error_msg(GOT_ERR_BAD_PACKET,
+ "non-printable error message received "
+ "from the server");
+ }
+ }
+ }
+ reflen = strlen(refname);
+ if (!got_ref_name_is_valid(refname)) {
+ return got_error_msg(GOT_ERR_BAD_PACKET,
+ "unexpected message from server");
+ }
+
TAILQ_FOREACH(pe, refs, entry) {
if (strcmp(refname, pe->path) == 0) {
ref_valid = 1;
"unexpected message from server");
}
- len = sizeof(struct got_imsg_send_ref_status) + reflen;
+ len = sizeof(struct got_imsg_send_ref_status) + reflen + errmsglen;
if (len >= MAX_IMSGSIZE - IMSG_HEADER_SIZE)
return got_error(GOT_ERR_NO_SPACE);
return got_error_from_errno("imsg_add SEND_REF_STATUS");
if (imsg_add(wbuf, &reflen, sizeof(reflen)) == -1)
return got_error_from_errno("imsg_add SEND_REF_STATUS");
+ if (imsg_add(wbuf, &errmsglen, sizeof(errmsglen)) == -1)
+ return got_error_from_errno("imsg_add SEND_REF_STATUS");
if (imsg_add(wbuf, refname, reflen) == -1)
return got_error_from_errno("imsg_add SEND_REF_STATUS");
+ if (imsg_add(wbuf, errmsg, errmsglen) == -1)
+ return got_error_from_errno("imsg_add SEND_REF_STATUS");
wbuf->fd = -1;
imsg_close(ibuf, wbuf);
blob - f989b0dbd6a3ca710184d881f574e55a5eb83e78
blob + 2bfbfe22cdf4a0255e78921e2da2bfcc76ffb03c
--- regress/cmdline/send.sh
+++ regress/cmdline/send.sh
git_fsck "$testroot" "$testroot/repo-clone"
ret=$?
test_done "$testroot" "$ret"
+}
+
+test_send_rejected() {
+ local testroot=`test_init send_rejected`
+ local testurl=ssh://127.0.0.1/$testroot
+ local commit_id=`git_show_head $testroot/repo`
+
+ if ! got clone -q "$testurl/repo" "$testroot/repo-clone"; then
+ echo "got clone command failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ mkdir "$testroot/repo-clone/hooks"
+ cat <<'EOF' >$testroot/repo-clone/hooks/update
+case "$1" in
+*master*)
+ echo "rejecting push on master branch"
+ exit 1
+ ;;
+esac
+exit 0
+EOF
+ chmod +x "$testroot/repo-clone/hooks/update"
+
+ cat > $testroot/repo/.git/got.conf <<EOF
+remote "origin" {
+ protocol ssh
+ server 127.0.0.1
+ repository "$testroot/repo-clone"
+}
+EOF
+
+ echo "modified alpha" >$testroot/repo/alpha
+ git_commit "$testroot/repo" -m "modified alpha"
+
+ got send -q -r "$testroot/repo" >$testroot/stdout 2>$testroot/stderr
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got send command failed unexpectedly" >&2
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ touch "$testroot/stdout.expected"
+ if ! cmp -s "$testroot/stdout.expected" "$testroot/stdout"; then
+ diff -u "$testroot/stdout.expected" "$testroot/stdout"
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ cat <<EOF >$testroot/stderr.expected
+rejecting push on master branch
+error: hook declined to update refs/heads/master
+EOF
+
+ if ! cmp -s "$testroot/stderr.expected" "$testroot/stderr"; then
+ diff -u "$testroot/stderr.expected" "$testroot/stderr"
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ test_done "$testroot" 0
}
test_parseargs "$@"
run_test test_send_to_empty_repo
run_test test_send_and_fetch_config
run_test test_send_config
+run_test test_send_rejected