[RFC/PATCH 2/2] make remote hangup warnings more friendly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a user asks to do a remote operation but the remote
side thinks the operation is invalid (e.g., because the user
pointed to a directory which is not actually a repository),
then we generally end up showing the user two fatal
messages: one from the remote explaining what went wrong, and
one from the local side complaining of an unexpected hangup.

For example:

  $ git push /nonexistent master
  fatal: '/nonexistent' does not appear to be a git repository
  fatal: The remote end hung up unexpectedly

In this case, the second message is useless noise, and the
user is better off seeing just the first.

This patch tries to suppress the "hung up" message when it
is redundant (but still exits with an error code, of
course).

One heuristic would be to suppress it whenever the remote
has said something on stderr. Unfortunately, in many
transports we don't actually handle stderr ourselves; it
is simply a clone of the parent program's stderr and goes
straight to the terminal.

Instead, we note that the remote end will typically perform
such an "expected" hangup at the beginning of a packet
instead of in the middle. Therefore if we are expecting a
packet and get an end-of-file from the remote, we assume
they have printed something useful and exit without further
messages. Any other short read or eof is reported as before.

Signed-off-by: Jeff King <peff@xxxxxxxx>
---
There are two possible problems with this patch:

  1. The "beginning of packet" heuristic may not be the best. I
     tried a few obvious test cases like pushing and fetching with
     invalid repos and bogus --receive-pack= settings. All of them have
     useful output from the remote. You would of course get no message
     if the remote was cut off randomly at just the right spot.

    The "remote said something on stderr" heuristic does seem better.
    But we would have to start processing stderr for local and ssh
    connections, which we don't do currently. On the other hand, that
    might be nicer in the long run, because you can mark the remote
    errors as remote, which makes it more obvious what is going on.
    E.g.,:

      $ git push host:bogus master
      remote: fatal: 'bogus' does not appear to be a git repository

  2. Even "remote said something on stderr" may not be a desirable
     heuristic. In the case of a bogus --receive-pack, you get:

       $ git push --receive-pack=bogus host:repo master
       sh: bogus: command not found

     So you are losing the part where git says "fatal: ". Maybe it
     is obvious that such an error is fatal. It is to me, but I am not
     the intended audience.

     I think this would be improved somewhat with stderr processing to:

       remote: sh: bogus: command not found

     Or you could even trigger the suppression only if stderr had a line
     matching "^fatal:".

     Or it may even be that adding "remote:" is enough to make things
     less confusing:

       remote: fatal: 'bogus' does not appear to be a git repository
       fatal: The remote end hung up unexpectedly

     I think I still favor suppression in that case, but it is at least
     more clear why there are two fatals.

So you can see, the possibilities are endless. The perfect bikeshed. ;)

 pkt-line.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index f5d0086..f2b387c 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -63,13 +63,16 @@ void packet_write(int fd, const char *fmt, ...)
 	safe_write(fd, buffer, n);
 }
 
-static void safe_read(int fd, void *buffer, unsigned size)
+static void safe_read(int fd, void *buffer, unsigned size, int eof_warn)
 {
 	ssize_t ret = read_in_full(fd, buffer, size);
 	if (ret < 0)
 		die("read error (%s)", strerror(errno));
-	else if (ret < size)
+	else if (ret < size) {
+		if (ret == 0 && !eof_warn)
+			exit(128);
 		die("The remote end hung up unexpectedly");
+	}
 }
 
 int packet_read_line(int fd, char *buffer, unsigned size)
@@ -78,7 +81,7 @@ int packet_read_line(int fd, char *buffer, unsigned size)
 	unsigned len;
 	char linelen[4];
 
-	safe_read(fd, linelen, 4);
+	safe_read(fd, linelen, 4, 0);
 
 	len = 0;
 	for (n = 0; n < 4; n++) {
@@ -103,7 +106,7 @@ int packet_read_line(int fd, char *buffer, unsigned size)
 	len -= 4;
 	if (len >= size)
 		die("protocol error: bad line length %d", len);
-	safe_read(fd, buffer, len);
+	safe_read(fd, buffer, len, 1);
 	buffer[len] = 0;
 	return len;
 }
-- 
1.6.2.rc2.24.g55bc2
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux