summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-02-14 18:28:48 (GMT)
committerJunio C Hamano <gitster@pobox.com>2013-02-14 18:28:48 (GMT)
commitd3354cde33e2674493969a1870c9771ea0921084 (patch)
tree3b4263648fbabd785a5f3c3cd0f784fc17affe78 /builtin
parent260adc87b3d6c00650ba2dd493abd9a6603ca4f1 (diff)
parent5e026920a9465c6c3e026c5bf0d1c4d9d3f05cfa (diff)
downloadgit-d3354cde33e2674493969a1870c9771ea0921084.zip
git-d3354cde33e2674493969a1870c9771ea0921084.tar.gz
git-d3354cde33e2674493969a1870c9771ea0921084.tar.bz2
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')
-rw-r--r--builtin/apply.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/builtin/apply.c b/builtin/apply.c
index 080ce2e..06f5320 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 */