merge-recursive: don't segfault while handling rename clashes
[gitweb.git] / sideband.c
index 756bbc28d71448781294151cbacd30f68b2bb97b..cca3360546dabf9f018b882f690bd1dea9de534d 100644 (file)
  */
 
 #define PREFIX "remote:"
-#define SUFFIX "\033[K"  /* change to "        " if ANSI sequences don't work */
+
+#define ANSI_SUFFIX "\033[K"
+#define DUMB_SUFFIX "        "
+
+#define FIX_SIZE 10  /* large enough for any of the above */
 
 int recv_sideband(const char *me, int in_stream, int out, int err)
 {
        unsigned pf = strlen(PREFIX);
-       unsigned sf = strlen(SUFFIX);
-       char buf[pf + LARGE_PACKET_MAX + sf + 1];
+       unsigned sf;
+       char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
+       char *suffix, *term;
+       int skip_pf = 0;
+
        memcpy(buf, PREFIX, pf);
+       term = getenv("TERM");
+       if (term && strcmp(term, "dumb"))
+               suffix = ANSI_SUFFIX;
+       else
+               suffix = DUMB_SUFFIX;
+       sf = strlen(suffix);
+
        while (1) {
                int band, len;
                len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX);
@@ -41,39 +55,58 @@ int recv_sideband(const char *me, int in_stream, int out, int err)
                        return SIDEBAND_REMOTE_ERROR;
                case 2:
                        buf[pf] = ' ';
-                       len += pf+1;
-                       while (1) {
-                               int brk = pf+1;
+                       do {
+                               char *b = buf;
+                               int brk = 0;
+
+                               /*
+                                * If the last buffer didn't end with a line
+                                * break then we should not print a prefix
+                                * this time around.
+                                */
+                               if (skip_pf) {
+                                       b += pf+1;
+                               } else {
+                                       len += pf+1;
+                                       brk += pf+1;
+                               }
 
-                               /* Break the buffer into separate lines. */
-                               while (brk < len) {
+                               /* Look for a line break. */
+                               for (;;) {
                                        brk++;
-                                       if (buf[brk-1] == '\n' ||
-                                           buf[brk-1] == '\r')
+                                       if (brk > len) {
+                                               brk = 0;
+                                               break;
+                                       }
+                                       if (b[brk-1] == '\n' ||
+                                           b[brk-1] == '\r')
                                                break;
                                }
 
                                /*
                                 * Let's insert a suffix to clear the end
-                                * of the screen line, but only if current
-                                * line data actually contains something.
+                                * of the screen line if a line break was
+                                * found.  Also, if we don't skip the
+                                * prefix, then a non-empty string must be
+                                * present too.
                                 */
-                               if (brk > pf+1 + 1) {
-                                       char save[sf];
-                                       memcpy(save, buf + brk, sf);
-                                       buf[brk + sf - 1] = buf[brk - 1];
-                                       memcpy(buf + brk - 1, SUFFIX, sf);
-                                       safe_write(err, buf, brk + sf);
-                                       memcpy(buf + brk, save, sf);
-                               } else
-                                       safe_write(err, buf, brk);
+                               if (brk > (skip_pf ? 0 : (pf+1 + 1))) {
+                                       char save[FIX_SIZE];
+                                       memcpy(save, b + brk, sf);
+                                       b[brk + sf - 1] = b[brk - 1];
+                                       memcpy(b + brk - 1, suffix, sf);
+                                       safe_write(err, b, brk + sf);
+                                       memcpy(b + brk, save, sf);
+                                       len -= brk;
+                               } else {
+                                       int l = brk ? brk : len;
+                                       safe_write(err, b, l);
+                                       len -= l;
+                               }
 
-                               if (brk < len) {
-                                       memmove(buf + pf+1, buf + brk, len - brk);
-                                       len = len - brk + pf+1;
-                               } else
-                                       break;
-                       }
+                               skip_pf = !brk;
+                               memmove(buf + pf+1, b + brk, len);
+                       } while (len);
                        continue;
                case 1:
                        safe_write(out, buf + pf+1, len);