@matheusbsbs / matheus-bagliano / commits / 7dae8b21c2
Fork 0

diff -c -p: do not die on submodules

The combine diff logic knew only about blobs (and their checked-out form in the work tree, either regular files or symlinks), and barfed when fed submodules. This "externalizes" gitlinks in the same way as the normal patch generation codepath does (i.e. "Subproject commit Xxx\n") to fix the issue. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Apr 29, 2009 at 12:49 UTC 7dae8b21c2fe39a59661c709f0dc17090dafa5a4
2 files changed +65 -12
combine-diff.c
+26 -12
@@ -6,6 +6,7 @@
6 #include "quote.h"
7 #include "xdiff-interface.h"
8 #include "log-tree.h"
9 +#include "refs.h"
10
11 static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
12 {
@@ -90,18 +91,24 @@ struct sline {
91 unsigned long *p_lno;
92 };
93
93 -static char *grab_blob(const unsigned char *sha1, unsigned long *size)
94 +static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size)
95 {
96 char *blob;
97 enum object_type type;
97 - if (is_null_sha1(sha1)) {
98 +
99 + if (S_ISGITLINK(mode)) {
100 + blob = xmalloc(100);
101 + *size = snprintf(blob, 100,
102 + "Subproject commit %s\n", sha1_to_hex(sha1));
103 + } else if (is_null_sha1(sha1)) {
104 /* deleted blob */
105 *size = 0;
106 return xcalloc(1, 1);
107 + } else {
108 + blob = read_sha1_file(sha1, &type, size);
109 + if (type != OBJ_BLOB)
110 + die("object '%s' is not a blob!", sha1_to_hex(sha1));
111 }
102 - blob = read_sha1_file(sha1, &type, size);
103 - if (type != OBJ_BLOB)
104 - die("object '%s' is not a blob!", sha1_to_hex(sha1));
112 return blob;
113 }
114
@@ -197,7 +204,8 @@ static void consume_line(void *state_, char *line, unsigned long len)
204 }
205 }
206
200 -static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
207 +static void combine_diff(const unsigned char *parent, unsigned int mode,
208 + mmfile_t *result_file,
209 struct sline *sline, unsigned int cnt, int n,
210 int num_parent)
211 {
@@ -213,7 +221,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
221 if (!cnt)
222 return; /* result deleted */
223
216 - parent_file.ptr = grab_blob(parent, &sz);
224 + parent_file.ptr = grab_blob(parent, mode, &sz);
225 parent_file.size = sz;
226 xpp.flags = XDF_NEED_MINIMAL;
227 memset(&xecfg, 0, sizeof(xecfg));
@@ -692,7 +700,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
700 context = opt->context;
701 /* Read the result of merge first */
702 if (!working_tree_file)
695 - result = grab_blob(elem->sha1, &result_size);
703 + result = grab_blob(elem->sha1, elem->mode, &result_size);
704 else {
705 /* Used by diff-tree to read from the working tree */
706 struct stat st;
@@ -712,9 +720,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
720 }
721 result[len] = 0;
722 elem->mode = canon_mode(st.st_mode);
715 - }
716 - else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
717 - !fstat(fd, &st)) {
723 + } else if (S_ISDIR(st.st_mode)) {
724 + unsigned char sha1[20];
725 + if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
726 + result = grab_blob(elem->sha1, elem->mode, &result_size);
727 + else
728 + result = grab_blob(sha1, elem->mode, &result_size);
729 + } else if (0 <= (fd = open(elem->path, O_RDONLY))) {
730 size_t len = xsize_t(st.st_size);
731 ssize_t done;
732 int is_file, i;
@@ -807,7 +819,9 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
819 }
820 }
821 if (i <= j)
810 - combine_diff(elem->parent[i].sha1, &result_file, sline,
822 + combine_diff(elem->parent[i].sha1,
823 + elem->parent[i].mode,
824 + &result_file, sline,
825 cnt, i, num_parent);
826 if (elem->parent[i].mode != elem->mode)
827 mode_differs = 1;
t/t4027-diff-submodule.sh
+39
@@ -57,4 +57,43 @@ test_expect_success 'git diff (empty submodule dir)' '
57 test_cmp empty actual.empty
58 '
59
60 +test_expect_success 'conflicted submodule setup' '
61 +
62 + # 39 efs
63 + c=fffffffffffffffffffffffffffffffffffffff
64 + (
65 + echo "000000 $_z40 0 sub"
66 + echo "160000 1$c 1 sub"
67 + echo "160000 2$c 2 sub"
68 + echo "160000 3$c 3 sub"
69 + ) | git update-index --index-info &&
70 + echo >expect.nosub '\''diff --cc sub
71 +index 2ffffff,3ffffff..0000000
72 +--- a/sub
73 ++++ b/sub
74 +@@@ -1,1 -1,1 +1,1 @@@
75 +- Subproject commit 2fffffffffffffffffffffffffffffffffffffff
76 + -Subproject commit 3fffffffffffffffffffffffffffffffffffffff
77 +++Subproject commit 0000000000000000000000000000000000000000'\'' &&
78 +
79 + hh=$(git rev-parse HEAD) &&
80 + sed -e "s/$_z40/$hh/" expect.nosub >expect.withsub
81 +
82 +'
83 +
84 +test_expect_success 'combined (empty submodule)' '
85 + rm -fr sub && mkdir sub &&
86 + git diff >actual &&
87 + test_cmp expect.nosub actual
88 +'
89 +
90 +test_expect_success 'combined (with submodule)' '
91 + rm -fr sub &&
92 + git clone --no-checkout . sub &&
93 + git diff >actual &&
94 + test_cmp expect.withsub actual
95 +'
96 +
97 +
98 +
99 test_done