Skip to content

Commit d3354cd

Browse files
committed
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
2 parents 260adc8 + 5e02692 commit d3354cd

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

builtin/apply.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3600,6 +3600,40 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
36003600
return 0;
36013601
}
36023602

3603+
static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20])
3604+
{
3605+
/*
3606+
* A usable gitlink patch has only one fragment (hunk) that looks like:
3607+
* @@ -1 +1 @@
3608+
* -Subproject commit <old sha1>
3609+
* +Subproject commit <new sha1>
3610+
* or
3611+
* @@ -1 +0,0 @@
3612+
* -Subproject commit <old sha1>
3613+
* for a removal patch.
3614+
*/
3615+
struct fragment *hunk = p->fragments;
3616+
static const char heading[] = "-Subproject commit ";
3617+
char *preimage;
3618+
3619+
if (/* does the patch have only one hunk? */
3620+
hunk && !hunk->next &&
3621+
/* is its preimage one line? */
3622+
hunk->oldpos == 1 && hunk->oldlines == 1 &&
3623+
/* does preimage begin with the heading? */
3624+
(preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL &&
3625+
!prefixcmp(++preimage, heading) &&
3626+
/* does it record full SHA-1? */
3627+
!get_sha1_hex(preimage + sizeof(heading) - 1, sha1) &&
3628+
preimage[sizeof(heading) + 40 - 1] == '\n' &&
3629+
/* does the abbreviated name on the index line agree with it? */
3630+
!prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
3631+
return 0; /* it all looks fine */
3632+
3633+
/* we may have full object name on the index line */
3634+
return get_sha1_hex(p->old_sha1_prefix, sha1);
3635+
}
3636+
36033637
/* Build an index that contains the just the files needed for a 3way merge */
36043638
static void build_fake_ancestor(struct patch *list, const char *filename)
36053639
{
@@ -3620,8 +3654,10 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
36203654
continue;
36213655

36223656
if (S_ISGITLINK(patch->old_mode)) {
3623-
if (get_sha1_hex(patch->old_sha1_prefix, sha1))
3624-
die("submoule change for %s without full index name",
3657+
if (!preimage_sha1_in_gitlink_patch(patch, sha1))
3658+
; /* ok, the textual part looks sane */
3659+
else
3660+
die("sha1 information is lacking or useless for submoule %s",
36253661
name);
36263662
} else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
36273663
; /* ok */

0 commit comments

Comments
 (0)