Merge branch 'bc/blame-crlf-test' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:46:44 +0000 (11:46 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:46:45 +0000 (11:46 -0700)
"git blame" assigned the blame to the copy in the working-tree if
the repository is set to core.autocrlf=input and the file used CRLF
line endings.

* bc/blame-crlf-test:
blame: correctly handle files regardless of autocrlf

1  2 
builtin/blame.c
diff --combined builtin/blame.c
index 128fc64d64f46af010ffcc1cf83b98705c60dabc,7468df4a41651ab9bcd8acc54daf3e6acf7a17ae..d8b276048eee8b557a7d3dc0294587913cd66a45
@@@ -74,7 -74,7 +74,7 @@@ static unsigned blame_copy_score
  #define BLAME_DEFAULT_MOVE_SCORE      20
  #define BLAME_DEFAULT_COPY_SCORE      40
  
 -/* bits #0..7 in revision.h, #8..11 used for merge_bases() in commit.c */
 +/* Remember to update object flag allocation in object.h */
  #define METAINFO_SHOWN                (1u<<12)
  #define MORE_THAN_ONE_PATH    (1u<<13)
  
@@@ -197,6 -197,7 +197,6 @@@ static void drop_origin_blob(struct ori
   * scoreboard structure, sorted by the target line number.
   */
  struct blame_entry {
 -      struct blame_entry *prev;
        struct blame_entry *next;
  
        /* the first line of this group in the final image;
@@@ -255,6 -256,15 +255,6 @@@ struct scoreboard 
        int *lineno;
  };
  
 -static inline int same_suspect(struct origin *a, struct origin *b)
 -{
 -      if (a == b)
 -              return 1;
 -      if (a->commit != b->commit)
 -              return 0;
 -      return !strcmp(a->path, b->path);
 -}
 -
  static void sanity_check_refcnt(struct scoreboard *);
  
  /*
@@@ -267,11 -277,13 +267,11 @@@ static void coalesce(struct scoreboard 
        struct blame_entry *ent, *next;
  
        for (ent = sb->ent; ent && (next = ent->next); ent = next) {
 -              if (same_suspect(ent->suspect, next->suspect) &&
 +              if (ent->suspect == next->suspect &&
                    ent->guilty == next->guilty &&
                    ent->s_lno + ent->num_lines == next->s_lno) {
                        ent->num_lines += next->num_lines;
                        ent->next = next->next;
 -                      if (ent->next)
 -                              ent->next->prev = ent;
                        origin_decref(next->suspect);
                        free(next);
                        ent->score = 0;
@@@ -522,7 -534,7 +522,7 @@@ static void add_blame_entry(struct scor
                prev = ent;
  
        /* prev, if not NULL, is the last one that is below e */
 -      e->prev = prev;
 +
        if (prev) {
                e->next = prev->next;
                prev->next = e;
                e->next = sb->ent;
                sb->ent = e;
        }
 -      if (e->next)
 -              e->next->prev = e;
  }
  
  /*
   */
  static void dup_entry(struct blame_entry *dst, struct blame_entry *src)
  {
 -      struct blame_entry *p, *n;
 +      struct blame_entry *n;
  
 -      p = dst->prev;
        n = dst->next;
        origin_incref(src->suspect);
        origin_decref(dst->suspect);
        memcpy(dst, src, sizeof(*src));
 -      dst->prev = p;
        dst->next = n;
        dst->score = 0;
  }
@@@ -726,7 -742,7 +726,7 @@@ static int find_last_in_target(struct s
        int last_in_target = -1;
  
        for (e = sb->ent; e; e = e->next) {
 -              if (e->guilty || !same_suspect(e->suspect, target))
 +              if (e->guilty || e->suspect != target)
                        continue;
                if (last_in_target < e->s_lno + e->num_lines)
                        last_in_target = e->s_lno + e->num_lines;
@@@ -746,7 -762,7 +746,7 @@@ static void blame_chunk(struct scoreboa
        struct blame_entry *e;
  
        for (e = sb->ent; e; e = e->next) {
 -              if (e->guilty || !same_suspect(e->suspect, target))
 +              if (e->guilty || e->suspect != target)
                        continue;
                if (same <= e->s_lno)
                        continue;
@@@ -923,6 -939,7 +923,6 @@@ static void find_copy_in_blob(struct sc
                              mmfile_t *file_p)
  {
        const char *cp;
 -      int cnt;
        mmfile_t file_o;
        struct handle_split_cb_data d;
  
         */
        cp = nth_line(sb, ent->lno);
        file_o.ptr = (char *) cp;
 -      cnt = ent->num_lines;
 -
 -      while (cnt && cp < sb->final_buf + sb->final_buf_size) {
 -              if (*cp++ == '\n')
 -                      cnt--;
 -      }
 -      file_o.size = cp - file_o.ptr;
 +      file_o.size = nth_line(sb, ent->lno + ent->num_lines) - cp;
  
        /*
         * file_o is a part of final image we are annotating.
@@@ -969,7 -992,7 +969,7 @@@ static int find_move_in_parent(struct s
        while (made_progress) {
                made_progress = 0;
                for (e = sb->ent; e; e = e->next) {
 -                      if (e->guilty || !same_suspect(e->suspect, target) ||
 +                      if (e->guilty || e->suspect != target ||
                            ent_score(sb, e) < blame_move_score)
                                continue;
                        find_copy_in_blob(sb, e, parent, split, &file_p);
@@@ -1004,14 -1027,14 +1004,14 @@@ static struct blame_list *setup_blame_l
  
        for (e = sb->ent, num_ents = 0; e; e = e->next)
                if (!e->scanned && !e->guilty &&
 -                  same_suspect(e->suspect, target) &&
 +                  e->suspect == target &&
                    min_score < ent_score(sb, e))
                        num_ents++;
        if (num_ents) {
                blame_list = xcalloc(num_ents, sizeof(struct blame_list));
                for (e = sb->ent, i = 0; e; e = e->next)
                        if (!e->scanned && !e->guilty &&
 -                          same_suspect(e->suspect, target) &&
 +                          e->suspect == target &&
                            min_score < ent_score(sb, e))
                                blame_list[i++].ent = e;
        }
@@@ -1155,7 -1178,7 +1155,7 @@@ static void pass_whole_blame(struct sco
                origin->file.ptr = NULL;
        }
        for (e = sb->ent; e; e = e->next) {
 -              if (!same_suspect(e->suspect, origin))
 +              if (e->suspect != origin)
                        continue;
                origin_incref(porigin);
                origin_decref(e->suspect);
@@@ -1544,7 -1567,7 +1544,7 @@@ static void assign_blame(struct scorebo
  
                /* Take responsibility for the remaining entries */
                for (ent = sb->ent; ent; ent = ent->next)
 -                      if (same_suspect(ent->suspect, suspect))
 +                      if (ent->suspect == suspect)
                                found_guilty_entry(ent);
                origin_decref(suspect);
  
  static const char *format_time(unsigned long time, const char *tz_str,
                               int show_raw_time)
  {
 -      static char time_buf[128];
 -      const char *time_str;
 -      int time_len;
 -      int tz;
 +      static struct strbuf time_buf = STRBUF_INIT;
  
 +      strbuf_reset(&time_buf);
        if (show_raw_time) {
 -              snprintf(time_buf, sizeof(time_buf), "%lu %s", time, tz_str);
 +              strbuf_addf(&time_buf, "%lu %s", time, tz_str);
        }
        else {
 +              const char *time_str;
 +              size_t time_width;
 +              int tz;
                tz = atoi(tz_str);
                time_str = show_date(time, tz, blame_date_mode);
 -              time_len = strlen(time_str);
 -              memcpy(time_buf, time_str, time_len);
 -              memset(time_buf + time_len, ' ', blame_date_width - time_len);
 +              strbuf_addstr(&time_buf, time_str);
 +              /*
 +               * Add space paddings to time_buf to display a fixed width
 +               * string, and use time_width for display width calibration.
 +               */
 +              for (time_width = utf8_strwidth(time_str);
 +                   time_width < blame_date_width;
 +                   time_width++)
 +                      strbuf_addch(&time_buf, ' ');
        }
 -      return time_buf;
 +      return time_buf.buf;
  }
  
  #define OUTPUT_ANNOTATE_COMPAT        001
@@@ -1756,41 -1772,25 +1756,41 @@@ static int prepare_lines(struct scorebo
  {
        const char *buf = sb->final_buf;
        unsigned long len = sb->final_buf_size;
 -      int num = 0, incomplete = 0, bol = 1;
 +      const char *end = buf + len;
 +      const char *p;
 +      int *lineno;
 +      int num = 0, incomplete = 0;
  
 -      if (len && buf[len-1] != '\n')
 -              incomplete++; /* incomplete line at the end */
 -      while (len--) {
 -              if (bol) {
 -                      sb->lineno = xrealloc(sb->lineno,
 -                                            sizeof(int *) * (num + 1));
 -                      sb->lineno[num] = buf - sb->final_buf;
 -                      bol = 0;
 -              }
 -              if (*buf++ == '\n') {
 +      for (p = buf;;) {
 +              p = memchr(p, '\n', end - p);
 +              if (p) {
 +                      p++;
                        num++;
 -                      bol = 1;
 +                      continue;
                }
 +              break;
        }
 -      sb->lineno = xrealloc(sb->lineno,
 -                            sizeof(int *) * (num + incomplete + 1));
 -      sb->lineno[num + incomplete] = buf - sb->final_buf;
 +
 +      if (len && end[-1] != '\n')
 +              incomplete++; /* incomplete line at the end */
 +
 +      sb->lineno = xmalloc(sizeof(*sb->lineno) * (num + incomplete + 1));
 +      lineno = sb->lineno;
 +
 +      *lineno++ = 0;
 +      for (p = buf;;) {
 +              p = memchr(p, '\n', end - p);
 +              if (p) {
 +                      p++;
 +                      *lineno++ = p - buf;
 +                      continue;
 +              }
 +              break;
 +      }
 +
 +      if (incomplete)
 +              *lineno++ = len;
 +
        sb->num_lines = num + incomplete;
        return sb->num_lines;
  }
@@@ -2095,7 -2095,6 +2095,6 @@@ static struct commit *fake_working_tree
                if (strbuf_read(&buf, 0, 0) < 0)
                        die_errno("failed to read from stdin");
        }
-       convert_to_git(path, buf.buf, buf.len, &buf, 0);
        origin->file.ptr = buf.buf;
        origin->file.size = buf.len;
        pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
@@@ -2338,14 -2337,7 +2337,14 @@@ parse_done
                blame_date_width = sizeof("2006-10-19");
                break;
        case DATE_RELATIVE:
 -              /* "normal" is used as the fallback for "relative" */
 +              /* TRANSLATORS: This string is used to tell us the maximum
 +                 display width for a relative timestamp in "git blame"
 +                 output.  For C locale, "4 years, 11 months ago", which
 +                 takes 22 places, is the longest among various forms of
 +                 relative timestamps, but your language may need more or
 +                 fewer display columns. */
 +              blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */
 +              break;
        case DATE_LOCAL:
        case DATE_NORMAL:
                blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
                ent->suspect = o;
                ent->s_lno = bottom;
                ent->next = next;
 -              if (next)
 -                      next->prev = ent;
                origin_incref(o);
        }
        origin_decref(o);