X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=combine-diff.c;h=ea3ca5f950561a92fdd3be1a4ee4bbd726656118;hb=8960b5a7dfb160be65dc9122df8c7603a5f8aced;hp=29d0c9cf953fdc13bd44bef451d242c762e1c611;hpb=58a1e0e83bcdbf063fb708ee9a8a563c0aa14f87;p=git.git diff --git a/combine-diff.c b/combine-diff.c index 29d0c9cf9..ea3ca5f95 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -92,14 +92,14 @@ struct sline { static char *grab_blob(const unsigned char *sha1, unsigned long *size) { char *blob; - char type[20]; + enum object_type type; if (is_null_sha1(sha1)) { /* deleted blob */ *size = 0; return xcalloc(1, 1); } - blob = read_sha1_file(sha1, type, size); - if (strcmp(type, blob_type)) + blob = read_sha1_file(sha1, &type, size); + if (type != OBJ_BLOB) die("object '%s' is not a blob!", sha1_to_hex(sha1)); return blob; } @@ -482,11 +482,11 @@ static int make_hunks(struct sline *sline, unsigned long cnt, return has_interesting; } -static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long l1, int n) +static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long l1, int n, unsigned long null_context) { l0 = sline[l0].p_lno[n]; l1 = sline[l1].p_lno[n]; - printf(" -%lu,%lu", l0, l1-l0); + printf(" -%lu,%lu", l0, l1-l0-null_context); } static int hunk_comment_line(const char *bol) @@ -519,6 +519,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, unsigned long hunk_end; unsigned long rlines; const char *hunk_comment = NULL; + unsigned long null_context = 0; while (lno <= cnt && !(sline[lno].flag & mark)) { if (hunk_comment_line(sline[lno].bol)) @@ -535,10 +536,28 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, rlines = hunk_end - lno; if (cnt < hunk_end) rlines--; /* pointing at the last delete hunk */ + + if (!context) { + /* + * Even when running with --unified=0, all + * lines in the hunk needs to be processed in + * the loop below in order to show the + * deletion recorded in lost_head. However, + * we do not want to show the resulting line + * with all blank context markers in such a + * case. Compensate. + */ + unsigned long j; + for (j = lno; j < hunk_end; j++) + if (!(sline[j].flag & (mark-1))) + null_context++; + rlines -= null_context; + } + fputs(c_frag, stdout); for (i = 0; i <= num_parent; i++) putchar(combine_marker); for (i = 0; i < num_parent; i++) - show_parent_lno(sline, lno, hunk_end, i); + show_parent_lno(sline, lno, hunk_end, i, null_context); printf(" +%lu,%lu ", lno+1, rlines); for (i = 0; i <= num_parent; i++) putchar(combine_marker); @@ -578,8 +597,15 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, if (cnt < lno) break; p_mask = 1; - if (!(sl->flag & (mark-1))) + if (!(sl->flag & (mark-1))) { + /* + * This sline was here to hang the + * lost lines in front of it. + */ + if (!context) + continue; fputs(c_plain, stdout); + } else fputs(c_new, stdout); for (j = 0; j < num_parent; j++) { @@ -652,17 +678,43 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, else { /* Used by diff-tree to read from the working tree */ struct stat st; - int fd; - if (0 <= (fd = open(elem->path, O_RDONLY)) && - !fstat(fd, &st)) { - int len = st.st_size; - int sz = 0; + int fd = -1; + + if (lstat(elem->path, &st) < 0) + goto deleted_file; + + if (S_ISLNK(st.st_mode)) { + size_t len = xsize_t(st.st_size); + result_size = len; + result = xmalloc(len + 1); + if (result_size != readlink(elem->path, result, len)) { + error("readlink(%s): %s", elem->path, + strerror(errno)); + return; + } + result[len] = 0; + elem->mode = canon_mode(st.st_mode); + } + else if (0 <= (fd = open(elem->path, O_RDONLY)) && + !fstat(fd, &st)) { + size_t len = xsize_t(st.st_size); + size_t sz = 0; + int is_file, i; elem->mode = canon_mode(st.st_mode); + /* if symlinks don't work, assume symlink if all parents + * are symlinks + */ + is_file = has_symlinks; + for (i = 0; !is_file && i < num_parent; i++) + is_file = !S_ISLNK(elem->parent[i].mode); + if (!is_file) + elem->mode = canon_mode(S_IFLNK); + result_size = len; result = xmalloc(len + 1); while (sz < len) { - int done = xread(fd, result+sz, len-sz); + ssize_t done = xread(fd, result+sz, len-sz); if (done == 0) break; if (done < 0) @@ -672,11 +724,12 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, result[len] = 0; } else { - /* deleted file */ + deleted_file: result_size = 0; elem->mode = 0; result = xcalloc(1, 1); } + if (0 <= fd) close(fd); } @@ -890,6 +943,7 @@ void diff_tree_combined(const unsigned char *sha1, diffopts = *opt; diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; diffopts.recursive = 1; + diffopts.allow_external = 0; show_log_first = !!rev->loginfo && !rev->no_commit_id; needsep = 0;