From: Junio C Hamano Date: Thu, 14 Feb 2013 18:28:48 +0000 (-0800) Subject: Merge branch 'jc/extended-fake-ancestor-for-gitlink' X-Git-Tag: v1.8.2-rc0~24 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/d3354cde33e2674493969a1870c9771ea0921084?hp=-c 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 --- d3354cde33e2674493969a1870c9771ea0921084 diff --combined builtin/apply.c index 080ce2ea3e,445fea7af6..06f5320b18 --- a/builtin/apply.c +++ b/builtin/apply.c @@@ -1041,17 -1041,15 +1041,17 @@@ static int gitdiff_renamedst(const cha static int gitdiff_similarity(const char *line, struct patch *patch) { - if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX) - patch->score = 0; + unsigned long val = strtoul(line, NULL, 10); + if (val <= 100) + patch->score = val; return 0; } static int gitdiff_dissimilarity(const char *line, struct patch *patch) { - if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX) - patch->score = 0; + unsigned long val = strtoul(line, NULL, 10); + if (val <= 100) + patch->score = val; return 0; } @@@ -2097,7 -2095,7 +2097,7 @@@ static void update_pre_post_images(stru char *buf, size_t len, size_t postlen) { - int i, ctx; + int i, ctx, reduced; char *new, *old, *fixed; struct image fixed_preimage; @@@ -2107,10 -2105,8 +2107,10 @@@ * free "oldlines". */ prepare_image(&fixed_preimage, buf, len, 1); - assert(fixed_preimage.nr == preimage->nr); - for (i = 0; i < preimage->nr; i++) + assert(postlen + ? fixed_preimage.nr == preimage->nr + : fixed_preimage.nr <= preimage->nr); + for (i = 0; i < fixed_preimage.nr; i++) fixed_preimage.line[i].flag = preimage->line[i].flag; free(preimage->line_allocated); *preimage = fixed_preimage; @@@ -2130,8 -2126,7 +2130,8 @@@ else new = old; fixed = preimage->buf; - for (i = ctx = 0; i < postimage->nr; i++) { + + for (i = reduced = ctx = 0; i < postimage->nr; i++) { size_t len = postimage->line[i].len; if (!(postimage->line[i].flag & LINE_COMMON)) { /* an added line -- no counterparts in preimage */ @@@ -2150,15 -2145,8 +2150,15 @@@ fixed += preimage->line[ctx].len; ctx++; } - if (preimage->nr <= ctx) - die(_("oops")); + + /* + * preimage is expected to run out, if the caller + * fixed addition of trailing blank lines. + */ + if (preimage->nr <= ctx) { + reduced++; + continue; + } /* and copy it in, while fixing the line length */ len = preimage->line[ctx].len; @@@ -2171,7 -2159,6 +2171,7 @@@ /* Fix the length of the whole thing */ postimage->len = new - postimage->buf; + postimage->nr -= reduced; } static int match_fragment(struct image *img, @@@ -3600,6 -3587,40 +3600,40 @@@ static int get_current_sha1(const char 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 + * +Subproject commit + * or + * @@ -1 +0,0 @@ + * -Subproject commit + * 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 -3641,10 +3654,10 @@@ 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 */