Skip to content

Commit

Permalink
diff -c -p: do not die on submodules
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
gitster committed Apr 29, 2009
1 parent c922b01 commit 7dae8b2
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 12 deletions.
38 changes: 26 additions & 12 deletions combine-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "quote.h"
#include "xdiff-interface.h"
#include "log-tree.h"
#include "refs.h"

static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
{
Expand Down Expand Up @@ -90,18 +91,24 @@ struct sline {
unsigned long *p_lno;
};

static char *grab_blob(const unsigned char *sha1, unsigned long *size)
static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size)
{
char *blob;
enum object_type type;
if (is_null_sha1(sha1)) {

if (S_ISGITLINK(mode)) {
blob = xmalloc(100);
*size = snprintf(blob, 100,
"Subproject commit %s\n", sha1_to_hex(sha1));
} else if (is_null_sha1(sha1)) {
/* deleted blob */
*size = 0;
return xcalloc(1, 1);
} else {
blob = read_sha1_file(sha1, &type, size);
if (type != OBJ_BLOB)
die("object '%s' is not a blob!", sha1_to_hex(sha1));
}
blob = read_sha1_file(sha1, &type, size);
if (type != OBJ_BLOB)
die("object '%s' is not a blob!", sha1_to_hex(sha1));
return blob;
}

Expand Down Expand Up @@ -197,7 +204,8 @@ static void consume_line(void *state_, char *line, unsigned long len)
}
}

static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
static void combine_diff(const unsigned char *parent, unsigned int mode,
mmfile_t *result_file,
struct sline *sline, unsigned int cnt, int n,
int num_parent)
{
Expand All @@ -213,7 +221,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
if (!cnt)
return; /* result deleted */

parent_file.ptr = grab_blob(parent, &sz);
parent_file.ptr = grab_blob(parent, mode, &sz);
parent_file.size = sz;
xpp.flags = XDF_NEED_MINIMAL;
memset(&xecfg, 0, sizeof(xecfg));
Expand Down Expand Up @@ -692,7 +700,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
context = opt->context;
/* Read the result of merge first */
if (!working_tree_file)
result = grab_blob(elem->sha1, &result_size);
result = grab_blob(elem->sha1, elem->mode, &result_size);
else {
/* Used by diff-tree to read from the working tree */
struct stat st;
Expand All @@ -712,9 +720,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
}
result[len] = 0;
elem->mode = canon_mode(st.st_mode);
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) {
} else if (S_ISDIR(st.st_mode)) {
unsigned char sha1[20];
if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
result = grab_blob(elem->sha1, elem->mode, &result_size);
else
result = grab_blob(sha1, elem->mode, &result_size);
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
size_t len = xsize_t(st.st_size);
ssize_t done;
int is_file, i;
Expand Down Expand Up @@ -807,7 +819,9 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
}
}
if (i <= j)
combine_diff(elem->parent[i].sha1, &result_file, sline,
combine_diff(elem->parent[i].sha1,
elem->parent[i].mode,
&result_file, sline,
cnt, i, num_parent);
if (elem->parent[i].mode != elem->mode)
mode_differs = 1;
Expand Down
39 changes: 39 additions & 0 deletions t/t4027-diff-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,43 @@ test_expect_success 'git diff (empty submodule dir)' '
test_cmp empty actual.empty
'

test_expect_success 'conflicted submodule setup' '
# 39 efs
c=fffffffffffffffffffffffffffffffffffffff
(
echo "000000 $_z40 0 sub"
echo "160000 1$c 1 sub"
echo "160000 2$c 2 sub"
echo "160000 3$c 3 sub"
) | git update-index --index-info &&
echo >expect.nosub '\''diff --cc sub
index 2ffffff,3ffffff..0000000
--- a/sub
+++ b/sub
@@@ -1,1 -1,1 +1,1 @@@
- Subproject commit 2fffffffffffffffffffffffffffffffffffffff
-Subproject commit 3fffffffffffffffffffffffffffffffffffffff
++Subproject commit 0000000000000000000000000000000000000000'\'' &&
hh=$(git rev-parse HEAD) &&
sed -e "s/$_z40/$hh/" expect.nosub >expect.withsub
'

test_expect_success 'combined (empty submodule)' '
rm -fr sub && mkdir sub &&
git diff >actual &&
test_cmp expect.nosub actual
'

test_expect_success 'combined (with submodule)' '
rm -fr sub &&
git clone --no-checkout . sub &&
git diff >actual &&
test_cmp expect.withsub actual
'



test_done

0 comments on commit 7dae8b2

Please sign in to comment.