git-archive: work in bare repos
[gitweb.git] / combine-diff.c
index b6af32455c30964516ffd2cc01576bed7d8e98ec..aa9d79ea0bf011ea45ef629ef713e6c977781431 100644 (file)
@@ -500,6 +500,18 @@ static int hunk_comment_line(const char *bol)
        return (isalpha(ch) || ch == '_' || ch == '$');
 }
 
+static void show_line_to_eol(const char *line, int len, const char *reset)
+{
+       int saw_cr_at_eol = 0;
+       if (len < 0)
+               len = strlen(line);
+       saw_cr_at_eol = (len && line[len-1] == '\r');
+
+       printf("%.*s%s%s\n", len - saw_cr_at_eol, line,
+              reset,
+              saw_cr_at_eol ? "\r" : "");
+}
+
 static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
                       int use_color)
 {
@@ -593,7 +605,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
                                        else
                                                putchar(' ');
                                }
-                               printf("%s%s\n", ll->line, c_reset);
+                               show_line_to_eol(ll->line, -1, c_reset);
                                ll = ll->next;
                        }
                        if (cnt < lno)
@@ -617,7 +629,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
                                        putchar(' ');
                                p_mask <<= 1;
                        }
-                       printf("%.*s%s\n", sl->len, sl->bol, c_reset);
+                       show_line_to_eol(sl->bol, sl->len, c_reset);
                }
        }
 }
@@ -704,7 +716,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
                         !fstat(fd, &st)) {
                        size_t len = xsize_t(st.st_size);
-                       size_t sz = 0;
+                       ssize_t done;
                        int is_file, i;
 
                        elem->mode = canon_mode(st.st_mode);
@@ -719,15 +731,26 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 
                        result_size = len;
                        result = xmalloc(len + 1);
-                       while (sz < len) {
-                               ssize_t done = xread(fd, result+sz, len-sz);
-                               if (done == 0)
-                                       break;
-                               if (done < 0)
-                                       die("read error '%s'", elem->path);
-                               sz += done;
-                       }
+
+                       done = read_in_full(fd, result, len);
+                       if (done < 0)
+                               die("read error '%s'", elem->path);
+                       else if (done < len)
+                               die("early EOF '%s'", elem->path);
+
                        result[len] = 0;
+
+                       /* If not a fake symlink, apply filters, e.g. autocrlf */
+                       if (is_file) {
+                               struct strbuf buf;
+
+                               strbuf_init(&buf, 0);
+                               if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
+                                       free(result);
+                                       result = strbuf_detach(&buf, &len);
+                                       result_size = len;
+                               }
+                       }
                }
                else {
                deleted_file:
@@ -801,7 +824,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                int deleted = 0;
 
                if (rev->loginfo && !rev->no_commit_id)
-                       show_log(rev, opt->msg_sep);
+                       show_log(rev);
                dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
                                 "", elem->path, c_meta, c_reset);
                printf("%sindex ", c_meta);
@@ -884,7 +907,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
                inter_name_termination = 0;
 
        if (rev->loginfo && !rev->no_commit_id)
-               show_log(rev, opt->msg_sep);
+               show_log(rev);
 
        if (opt->output_format & DIFF_FORMAT_RAW) {
                offset = strlen(COLONS) - num_parent;
@@ -965,7 +988,7 @@ void diff_tree_combined(const unsigned char *sha1,
                paths = intersect_paths(paths, i, num_parent);
 
                if (show_log_first && i == 0) {
-                       show_log(rev, opt->msg_sep);
+                       show_log(rev);
                        if (rev->verbose_header && opt->output_format)
                                putchar(opt->line_termination);
                }