Skip to content

Commit e10e476

Browse files
committed
Merge branch 'jk/combine-diff-binary-etc' into maint
* jk/combine-diff-binary-etc: combine-diff: respect textconv attributes refactor get_textconv to not require diff_filespec combine-diff: handle binary files as binary combine-diff: calculate mode_differs earlier combine-diff: split header printing into its own function
2 parents 2a6f08a + 0508fe5 commit e10e476

File tree

5 files changed

+376
-83
lines changed

5 files changed

+376
-83
lines changed

combine-diff.c

Lines changed: 144 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "xdiff-interface.h"
88
#include "log-tree.h"
99
#include "refs.h"
10+
#include "userdiff.h"
1011

1112
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
1213
{
@@ -92,7 +93,9 @@ struct sline {
9293
unsigned long *p_lno;
9394
};
9495

95-
static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size)
96+
static char *grab_blob(const unsigned char *sha1, unsigned int mode,
97+
unsigned long *size, struct userdiff_driver *textconv,
98+
const char *path)
9699
{
97100
char *blob;
98101
enum object_type type;
@@ -105,6 +108,11 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned lo
105108
/* deleted blob */
106109
*size = 0;
107110
return xcalloc(1, 1);
111+
} else if (textconv) {
112+
struct diff_filespec *df = alloc_filespec(path);
113+
fill_filespec(df, sha1, mode);
114+
*size = fill_textconv(textconv, df, &blob);
115+
free_filespec(df);
108116
} else {
109117
blob = read_sha1_file(sha1, &type, size);
110118
if (type != OBJ_BLOB)
@@ -204,7 +212,9 @@ static void consume_line(void *state_, char *line, unsigned long len)
204212
static void combine_diff(const unsigned char *parent, unsigned int mode,
205213
mmfile_t *result_file,
206214
struct sline *sline, unsigned int cnt, int n,
207-
int num_parent, int result_deleted)
215+
int num_parent, int result_deleted,
216+
struct userdiff_driver *textconv,
217+
const char *path)
208218
{
209219
unsigned int p_lno, lno;
210220
unsigned long nmask = (1UL << n);
@@ -217,7 +227,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
217227
if (result_deleted)
218228
return; /* result deleted */
219229

220-
parent_file.ptr = grab_blob(parent, mode, &sz);
230+
parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path);
221231
parent_file.size = sz;
222232
memset(&xpp, 0, sizeof(xpp));
223233
xpp.flags = 0;
@@ -681,6 +691,82 @@ static void dump_quoted_path(const char *head,
681691
puts(buf.buf);
682692
}
683693

694+
static void show_combined_header(struct combine_diff_path *elem,
695+
int num_parent,
696+
int dense,
697+
struct rev_info *rev,
698+
int mode_differs,
699+
int show_file_header)
700+
{
701+
struct diff_options *opt = &rev->diffopt;
702+
int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
703+
const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/";
704+
const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
705+
int use_color = DIFF_OPT_TST(opt, COLOR_DIFF);
706+
const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
707+
const char *c_reset = diff_get_color(use_color, DIFF_RESET);
708+
const char *abb;
709+
int added = 0;
710+
int deleted = 0;
711+
int i;
712+
713+
if (rev->loginfo && !rev->no_commit_id)
714+
show_log(rev);
715+
716+
dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
717+
"", elem->path, c_meta, c_reset);
718+
printf("%sindex ", c_meta);
719+
for (i = 0; i < num_parent; i++) {
720+
abb = find_unique_abbrev(elem->parent[i].sha1,
721+
abbrev);
722+
printf("%s%s", i ? "," : "", abb);
723+
}
724+
abb = find_unique_abbrev(elem->sha1, abbrev);
725+
printf("..%s%s\n", abb, c_reset);
726+
727+
if (mode_differs) {
728+
deleted = !elem->mode;
729+
730+
/* We say it was added if nobody had it */
731+
added = !deleted;
732+
for (i = 0; added && i < num_parent; i++)
733+
if (elem->parent[i].status !=
734+
DIFF_STATUS_ADDED)
735+
added = 0;
736+
if (added)
737+
printf("%snew file mode %06o",
738+
c_meta, elem->mode);
739+
else {
740+
if (deleted)
741+
printf("%sdeleted file ", c_meta);
742+
printf("mode ");
743+
for (i = 0; i < num_parent; i++) {
744+
printf("%s%06o", i ? "," : "",
745+
elem->parent[i].mode);
746+
}
747+
if (elem->mode)
748+
printf("..%06o", elem->mode);
749+
}
750+
printf("%s\n", c_reset);
751+
}
752+
753+
if (!show_file_header)
754+
return;
755+
756+
if (added)
757+
dump_quoted_path("--- ", "", "/dev/null",
758+
c_meta, c_reset);
759+
else
760+
dump_quoted_path("--- ", a_prefix, elem->path,
761+
c_meta, c_reset);
762+
if (deleted)
763+
dump_quoted_path("+++ ", "", "/dev/null",
764+
c_meta, c_reset);
765+
else
766+
dump_quoted_path("+++ ", b_prefix, elem->path,
767+
c_meta, c_reset);
768+
}
769+
684770
static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
685771
int dense, struct rev_info *rev)
686772
{
@@ -692,17 +778,22 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
692778
int mode_differs = 0;
693779
int i, show_hunks;
694780
int working_tree_file = is_null_sha1(elem->sha1);
695-
int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
696-
const char *a_prefix, *b_prefix;
697781
mmfile_t result_file;
782+
struct userdiff_driver *userdiff;
783+
struct userdiff_driver *textconv = NULL;
784+
int is_binary;
698785

699786
context = opt->context;
700-
a_prefix = opt->a_prefix ? opt->a_prefix : "a/";
701-
b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
787+
userdiff = userdiff_find_by_path(elem->path);
788+
if (!userdiff)
789+
userdiff = userdiff_find_by_name("default");
790+
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV))
791+
textconv = userdiff_get_textconv(userdiff);
702792

703793
/* Read the result of merge first */
704794
if (!working_tree_file)
705-
result = grab_blob(elem->sha1, elem->mode, &result_size);
795+
result = grab_blob(elem->sha1, elem->mode, &result_size,
796+
textconv, elem->path);
706797
else {
707798
/* Used by diff-tree to read from the working tree */
708799
struct stat st;
@@ -725,9 +816,16 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
725816
} else if (S_ISDIR(st.st_mode)) {
726817
unsigned char sha1[20];
727818
if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
728-
result = grab_blob(elem->sha1, elem->mode, &result_size);
819+
result = grab_blob(elem->sha1, elem->mode,
820+
&result_size, NULL, NULL);
729821
else
730-
result = grab_blob(sha1, elem->mode, &result_size);
822+
result = grab_blob(sha1, elem->mode,
823+
&result_size, NULL, NULL);
824+
} else if (textconv) {
825+
struct diff_filespec *df = alloc_filespec(elem->path);
826+
fill_filespec(df, null_sha1, st.st_mode);
827+
result_size = fill_textconv(textconv, df, &result);
828+
free_filespec(df);
731829
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
732830
size_t len = xsize_t(st.st_size);
733831
ssize_t done;
@@ -777,6 +875,38 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
777875
close(fd);
778876
}
779877

878+
for (i = 0; i < num_parent; i++) {
879+
if (elem->parent[i].mode != elem->mode) {
880+
mode_differs = 1;
881+
break;
882+
}
883+
}
884+
885+
if (textconv)
886+
is_binary = 0;
887+
else if (userdiff->binary != -1)
888+
is_binary = userdiff->binary;
889+
else {
890+
is_binary = buffer_is_binary(result, result_size);
891+
for (i = 0; !is_binary && i < num_parent; i++) {
892+
char *buf;
893+
unsigned long size;
894+
buf = grab_blob(elem->parent[i].sha1,
895+
elem->parent[i].mode,
896+
&size, NULL, NULL);
897+
if (buffer_is_binary(buf, size))
898+
is_binary = 1;
899+
free(buf);
900+
}
901+
}
902+
if (is_binary) {
903+
show_combined_header(elem, num_parent, dense, rev,
904+
mode_differs, 0);
905+
printf("Binary files differ\n");
906+
free(result);
907+
return;
908+
}
909+
780910
for (cnt = 0, cp = result; cp < result + result_size; cp++) {
781911
if (*cp == '\n')
782912
cnt++;
@@ -824,71 +954,15 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
824954
combine_diff(elem->parent[i].sha1,
825955
elem->parent[i].mode,
826956
&result_file, sline,
827-
cnt, i, num_parent, result_deleted);
828-
if (elem->parent[i].mode != elem->mode)
829-
mode_differs = 1;
957+
cnt, i, num_parent, result_deleted,
958+
textconv, elem->path);
830959
}
831960

832961
show_hunks = make_hunks(sline, cnt, num_parent, dense);
833962

834963
if (show_hunks || mode_differs || working_tree_file) {
835-
const char *abb;
836-
int use_color = DIFF_OPT_TST(opt, COLOR_DIFF);
837-
const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
838-
const char *c_reset = diff_get_color(use_color, DIFF_RESET);
839-
int added = 0;
840-
int deleted = 0;
841-
842-
if (rev->loginfo && !rev->no_commit_id)
843-
show_log(rev);
844-
dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
845-
"", elem->path, c_meta, c_reset);
846-
printf("%sindex ", c_meta);
847-
for (i = 0; i < num_parent; i++) {
848-
abb = find_unique_abbrev(elem->parent[i].sha1,
849-
abbrev);
850-
printf("%s%s", i ? "," : "", abb);
851-
}
852-
abb = find_unique_abbrev(elem->sha1, abbrev);
853-
printf("..%s%s\n", abb, c_reset);
854-
855-
if (mode_differs) {
856-
deleted = !elem->mode;
857-
858-
/* We say it was added if nobody had it */
859-
added = !deleted;
860-
for (i = 0; added && i < num_parent; i++)
861-
if (elem->parent[i].status !=
862-
DIFF_STATUS_ADDED)
863-
added = 0;
864-
if (added)
865-
printf("%snew file mode %06o",
866-
c_meta, elem->mode);
867-
else {
868-
if (deleted)
869-
printf("%sdeleted file ", c_meta);
870-
printf("mode ");
871-
for (i = 0; i < num_parent; i++) {
872-
printf("%s%06o", i ? "," : "",
873-
elem->parent[i].mode);
874-
}
875-
if (elem->mode)
876-
printf("..%06o", elem->mode);
877-
}
878-
printf("%s\n", c_reset);
879-
}
880-
if (added)
881-
dump_quoted_path("--- ", "", "/dev/null",
882-
c_meta, c_reset);
883-
else
884-
dump_quoted_path("--- ", a_prefix, elem->path,
885-
c_meta, c_reset);
886-
if (deleted)
887-
dump_quoted_path("+++ ", "", "/dev/null",
888-
c_meta, c_reset);
889-
else
890-
dump_quoted_path("+++ ", b_prefix, elem->path,
891-
c_meta, c_reset);
964+
show_combined_header(elem, num_parent, dense, rev,
965+
mode_differs, 1);
892966
dump_sline(sline, cnt, num_parent,
893967
DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted);
894968
}

diff.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,19 +1984,7 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one)
19841984
return NULL;
19851985

19861986
diff_filespec_load_driver(one);
1987-
if (!one->driver->textconv)
1988-
return NULL;
1989-
1990-
if (one->driver->textconv_want_cache && !one->driver->textconv_cache) {
1991-
struct notes_cache *c = xmalloc(sizeof(*c));
1992-
struct strbuf name = STRBUF_INIT;
1993-
1994-
strbuf_addf(&name, "textconv/%s", one->driver->name);
1995-
notes_cache_init(c, name.buf, one->driver->textconv);
1996-
one->driver->textconv_cache = c;
1997-
}
1998-
1999-
return one->driver;
1987+
return userdiff_get_textconv(one->driver);
20001988
}
20011989

20021990
static void builtin_diff(const char *name_a,

0 commit comments

Comments
 (0)