Merge branch 'jh/checkout-auto-tracking' into maint
[gitweb.git] / pretty.c
index f7c6442e711d07cb8941a6a2b5d9f7f8b9b7ea2d..9e431545d8e6c14401faea5e76296974ca1d6649 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -393,36 +393,36 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
        strbuf_addstr(sb, "?=");
 }
 
+static const char *show_ident_date(const struct ident_split *ident,
+                                  enum date_mode mode)
+{
+       unsigned long date = 0;
+       int tz = 0;
+
+       if (ident->date_begin && ident->date_end)
+               date = strtoul(ident->date_begin, NULL, 10);
+       if (ident->tz_begin && ident->tz_end)
+               tz = strtol(ident->tz_begin, NULL, 10);
+       return show_date(date, tz, mode);
+}
+
 void pp_user_info(const struct pretty_print_context *pp,
                  const char *what, struct strbuf *sb,
                  const char *line, const char *encoding)
 {
-       struct strbuf name;
-       struct strbuf mail;
        struct ident_split ident;
-       int linelen;
-       char *line_end, *date;
+       char *line_end;
        const char *mailbuf, *namebuf;
        size_t namelen, maillen;
        int max_length = 78; /* per rfc2822 */
-       unsigned long time;
-       int tz;
 
        if (pp->fmt == CMIT_FMT_ONELINE)
                return;
 
-       line_end = strchr(line, '\n');
-       if (!line_end) {
-               line_end = strchr(line, '\0');
-               if (!line_end)
-                       return;
-       }
-
-       linelen = ++line_end - line;
-       if (split_ident_line(&ident, line, linelen))
+       line_end = strchrnul(line, '\n');
+       if (split_ident_line(&ident, line, line_end - line))
                return;
 
-
        mailbuf = ident.mail_begin;
        maillen = ident.mail_end - ident.mail_begin;
        namebuf = ident.name_begin;
@@ -431,54 +431,45 @@ void pp_user_info(const struct pretty_print_context *pp,
        if (pp->mailmap)
                map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
 
-       strbuf_init(&mail, 0);
-       strbuf_init(&name, 0);
-
-       strbuf_add(&mail, mailbuf, maillen);
-       strbuf_add(&name, namebuf, namelen);
-
-       namelen = name.len + mail.len + 3; /* ' ' + '<' + '>' */
-       time = strtoul(ident.date_begin, &date, 10);
-       tz = strtol(date, NULL, 10);
-
        if (pp->fmt == CMIT_FMT_EMAIL) {
                strbuf_addstr(sb, "From: ");
-               if (needs_rfc2047_encoding(name.buf, name.len, RFC2047_ADDRESS)) {
-                       add_rfc2047(sb, name.buf, name.len,
+               if (needs_rfc2047_encoding(namebuf, namelen, RFC2047_ADDRESS)) {
+                       add_rfc2047(sb, namebuf, namelen,
                                    encoding, RFC2047_ADDRESS);
                        max_length = 76; /* per rfc2047 */
-               } else if (needs_rfc822_quoting(name.buf, name.len)) {
+               } else if (needs_rfc822_quoting(namebuf, namelen)) {
                        struct strbuf quoted = STRBUF_INIT;
-                       add_rfc822_quoted(&quoted, name.buf, name.len);
+                       add_rfc822_quoted(&quoted, namebuf, namelen);
                        strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
                                                        -6, 1, max_length);
                        strbuf_release(&quoted);
                } else {
-                       strbuf_add_wrapped_bytes(sb, name.buf, name.len,
+                       strbuf_add_wrapped_bytes(sb, namebuf, namelen,
                                                 -6, 1, max_length);
                }
-               if (namelen - name.len + last_line_length(sb) > max_length)
-                       strbuf_addch(sb, '\n');
 
-               strbuf_addf(sb, " <%s>\n", mail.buf);
+               if (max_length <
+                   last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
+                       strbuf_addch(sb, '\n');
+               strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
        } else {
-               strbuf_addf(sb, "%s: %.*s%s <%s>\n", what,
-                             (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0,
-                             "    ", name.buf, mail.buf);
+               strbuf_addf(sb, "%s: %.*s%.*s <%.*s>\n", what,
+                           (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0, "    ",
+                           (int)namelen, namebuf, (int)maillen, mailbuf);
        }
 
-       strbuf_release(&mail);
-       strbuf_release(&name);
-
        switch (pp->fmt) {
        case CMIT_FMT_MEDIUM:
-               strbuf_addf(sb, "Date:   %s\n", show_date(time, tz, pp->date_mode));
+               strbuf_addf(sb, "Date:   %s\n",
+                           show_ident_date(&ident, pp->date_mode));
                break;
        case CMIT_FMT_EMAIL:
-               strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822));
+               strbuf_addf(sb, "Date: %s\n",
+                           show_ident_date(&ident, DATE_RFC2822));
                break;
        case CMIT_FMT_FULLER:
-               strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, pp->date_mode));
+               strbuf_addf(sb, "%sDate: %s\n", what,
+                           show_ident_date(&ident, pp->date_mode));
                break;
        default:
                /* notin' */
@@ -696,8 +687,6 @@ static size_t format_person_part(struct strbuf *sb, char part,
 {
        /* currently all placeholders have same length */
        const int placeholder_len = 2;
-       int tz;
-       unsigned long date = 0;
        struct ident_split s;
        const char *name, *mail;
        size_t maillen, namelen;
@@ -724,30 +713,23 @@ static size_t format_person_part(struct strbuf *sb, char part,
        if (!s.date_begin)
                goto skip;
 
-       date = strtoul(s.date_begin, NULL, 10);
-
        if (part == 't') {      /* date, UNIX timestamp */
                strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
                return placeholder_len;
        }
 
-       /* parse tz */
-       tz = strtoul(s.tz_begin + 1, NULL, 10);
-       if (*s.tz_begin == '-')
-               tz = -tz;
-
        switch (part) {
        case 'd':       /* date */
-               strbuf_addstr(sb, show_date(date, tz, dmode));
+               strbuf_addstr(sb, show_ident_date(&s, dmode));
                return placeholder_len;
        case 'D':       /* date, RFC2822 style */
-               strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_RFC2822));
                return placeholder_len;
        case 'r':       /* date, relative */
-               strbuf_addstr(sb, show_date(date, tz, DATE_RELATIVE));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_RELATIVE));
                return placeholder_len;
        case 'i':       /* date, ISO 8601 */
-               strbuf_addstr(sb, show_date(date, tz, DATE_ISO8601));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601));
                return placeholder_len;
        }
 
@@ -773,6 +755,7 @@ enum flush_type {
        no_flush,
        flush_right,
        flush_left,
+       flush_left_and_steal,
        flush_both
 };
 
@@ -1026,6 +1009,9 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
                if (*ch == '<') {
                        flush_type = flush_both;
                        ch++;
+               } else if (*ch == '>') {
+                       flush_type = flush_left_and_steal;
+                       ch++;
                } else
                        flush_type = flush_left;
                break;
@@ -1334,6 +1320,36 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
                total_consumed++;
        }
        len = utf8_strnwidth(local_sb.buf, -1, 1);
+
+       if (c->flush_type == flush_left_and_steal) {
+               const char *ch = sb->buf + sb->len - 1;
+               while (len > padding && ch > sb->buf) {
+                       const char *p;
+                       if (*ch == ' ') {
+                               ch--;
+                               padding++;
+                               continue;
+                       }
+                       /* check for trailing ansi sequences */
+                       if (*ch != 'm')
+                               break;
+                       p = ch - 1;
+                       while (ch - p < 10 && *p != '\033')
+                               p--;
+                       if (*p != '\033' ||
+                           ch + 1 - p != display_mode_esc_sequence_len(p))
+                               break;
+                       /*
+                        * got a good ansi sequence, put it back to
+                        * local_sb as we're cutting sb
+                        */
+                       strbuf_insert(&local_sb, 0, p, ch + 1 - p);
+                       ch = p - 1;
+               }
+               strbuf_setlen(sb, ch + 1 - sb->buf);
+               c->flush_type = flush_left;
+       }
+
        if (len > padding) {
                switch (c->truncate) {
                case trunc_left: