diff options
author | Junio C Hamano <gitster@pobox.com> | 2013-02-14 10:28:48 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-02-14 10:28:48 -0800 |
commit | d3354cde33e2674493969a1870c9771ea0921084 (patch) | |
tree | 3b4263648fbabd785a5f3c3cd0f784fc17affe78 /builtin/apply.c | |
parent | 260adc87b3d6c00650ba2dd493abd9a6603ca4f1 (diff) | |
parent | 5e026920a9465c6c3e026c5bf0d1c4d9d3f05cfa (diff) | |
download | git-d3354cde33e2674493969a1870c9771ea0921084.tar.gz |
Merge branch 'jc/extended-fake-ancestor-for-gitlink'
Instead of requiring the full 40-hex object names on the index
line, we can read submodule commit object names from the textual
diff when synthesizing a fake ancestore tree for "git am -3".
* jc/extended-fake-ancestor-for-gitlink:
apply: verify submodule commit object name better
Diffstat (limited to 'builtin/apply.c')
-rw-r--r-- | builtin/apply.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/builtin/apply.c b/builtin/apply.c index 080ce2ea3e..06f5320b18 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -3600,6 +3600,40 @@ static int get_current_sha1(const char *path, unsigned char *sha1) return 0; } +static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20]) +{ + /* + * A usable gitlink patch has only one fragment (hunk) that looks like: + * @@ -1 +1 @@ + * -Subproject commit <old sha1> + * +Subproject commit <new sha1> + * or + * @@ -1 +0,0 @@ + * -Subproject commit <old sha1> + * for a removal patch. + */ + struct fragment *hunk = p->fragments; + static const char heading[] = "-Subproject commit "; + char *preimage; + + if (/* does the patch have only one hunk? */ + hunk && !hunk->next && + /* is its preimage one line? */ + hunk->oldpos == 1 && hunk->oldlines == 1 && + /* does preimage begin with the heading? */ + (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL && + !prefixcmp(++preimage, heading) && + /* does it record full SHA-1? */ + !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) && + preimage[sizeof(heading) + 40 - 1] == '\n' && + /* does the abbreviated name on the index line agree with it? */ + !prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) + return 0; /* it all looks fine */ + + /* we may have full object name on the index line */ + return get_sha1_hex(p->old_sha1_prefix, sha1); +} + /* Build an index that contains the just the files needed for a 3way merge */ static void build_fake_ancestor(struct patch *list, const char *filename) { @@ -3620,8 +3654,10 @@ static void build_fake_ancestor(struct patch *list, const char *filename) continue; if (S_ISGITLINK(patch->old_mode)) { - if (get_sha1_hex(patch->old_sha1_prefix, sha1)) - die("submoule change for %s without full index name", + if (!preimage_sha1_in_gitlink_patch(patch, sha1)) + ; /* ok, the textual part looks sane */ + else + die("sha1 information is lacking or useless for submoule %s", name); } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) { ; /* ok */ |