Skip to content

Commit c0f16f8

Browse files
tgummerergitster
authored andcommitted
rerere: factor out handle_conflict function
Factor out the handle_conflict function, which handles a single conflict in a path. This is in preparation for a subsequent commit, where this function will be re-used. Note that this does change the behaviour of 'git rerere' slightly. Where previously we'd consider all files where an unmatched conflict marker is found as invalid, we now only consider files invalid when the "ours" conflict marker ("<<<<<<< <text>") is unmatched, not when other conflict markers (e.g. "=======") is unmatched. Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 221444f commit c0f16f8

File tree

1 file changed

+47
-40
lines changed

1 file changed

+47
-40
lines changed

rerere.c

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -384,85 +384,92 @@ static int is_cmarker(char *buf, int marker_char, int marker_size)
384384
return isspace(*buf);
385385
}
386386

387-
/*
388-
* Read contents a file with conflicts, normalize the conflicts
389-
* by (1) discarding the common ancestor version in diff3-style,
390-
* (2) reordering our side and their side so that whichever sorts
391-
* alphabetically earlier comes before the other one, while
392-
* computing the "conflict ID", which is just an SHA-1 hash of
393-
* one side of the conflict, NUL, the other side of the conflict,
394-
* and NUL concatenated together.
395-
*
396-
* Return 1 if conflict hunks are found, 0 if there are no conflict
397-
* hunks and -1 if an error occured.
398-
*/
399-
static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
387+
static int handle_conflict(struct rerere_io *io, int marker_size, git_SHA_CTX *ctx)
400388
{
401-
git_SHA_CTX ctx;
402-
int has_conflicts = 0;
403389
enum {
404-
RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL
405-
} hunk = RR_CONTEXT;
390+
RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL
391+
} hunk = RR_SIDE_1;
406392
struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
407393
struct strbuf buf = STRBUF_INIT;
408-
409-
if (sha1)
410-
git_SHA1_Init(&ctx);
394+
int has_conflicts = -1;
411395

412396
while (!io->getline(&buf, io)) {
413397
if (is_cmarker(buf.buf, '<', marker_size)) {
414-
if (hunk != RR_CONTEXT)
415-
goto bad;
416-
hunk = RR_SIDE_1;
398+
break;
417399
} else if (is_cmarker(buf.buf, '|', marker_size)) {
418400
if (hunk != RR_SIDE_1)
419-
goto bad;
401+
break;
420402
hunk = RR_ORIGINAL;
421403
} else if (is_cmarker(buf.buf, '=', marker_size)) {
422404
if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
423-
goto bad;
405+
break;
424406
hunk = RR_SIDE_2;
425407
} else if (is_cmarker(buf.buf, '>', marker_size)) {
426408
if (hunk != RR_SIDE_2)
427-
goto bad;
409+
break;
428410
if (strbuf_cmp(&one, &two) > 0)
429411
strbuf_swap(&one, &two);
430412
has_conflicts = 1;
431-
hunk = RR_CONTEXT;
432413
rerere_io_putconflict('<', marker_size, io);
433414
rerere_io_putmem(one.buf, one.len, io);
434415
rerere_io_putconflict('=', marker_size, io);
435416
rerere_io_putmem(two.buf, two.len, io);
436417
rerere_io_putconflict('>', marker_size, io);
437-
if (sha1) {
438-
git_SHA1_Update(&ctx, one.buf ? one.buf : "",
418+
if (ctx) {
419+
git_SHA1_Update(ctx, one.buf ? one.buf : "",
439420
one.len + 1);
440-
git_SHA1_Update(&ctx, two.buf ? two.buf : "",
421+
git_SHA1_Update(ctx, two.buf ? two.buf : "",
441422
two.len + 1);
442423
}
443-
strbuf_reset(&one);
444-
strbuf_reset(&two);
424+
break;
445425
} else if (hunk == RR_SIDE_1)
446426
strbuf_addbuf(&one, &buf);
447427
else if (hunk == RR_ORIGINAL)
448428
; /* discard */
449429
else if (hunk == RR_SIDE_2)
450430
strbuf_addbuf(&two, &buf);
451-
else
452-
rerere_io_putstr(buf.buf, io);
453-
continue;
454-
bad:
455-
hunk = 99; /* force error exit */
456-
break;
457431
}
458432
strbuf_release(&one);
459433
strbuf_release(&two);
460434
strbuf_release(&buf);
461435

436+
return has_conflicts;
437+
}
438+
439+
/*
440+
* Read contents a file with conflicts, normalize the conflicts
441+
* by (1) discarding the common ancestor version in diff3-style,
442+
* (2) reordering our side and their side so that whichever sorts
443+
* alphabetically earlier comes before the other one, while
444+
* computing the "conflict ID", which is just an SHA-1 hash of
445+
* one side of the conflict, NUL, the other side of the conflict,
446+
* and NUL concatenated together.
447+
*
448+
* Return 1 if conflict hunks are found, 0 if there are no conflict
449+
* hunks and -1 if an error occured.
450+
*/
451+
static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
452+
{
453+
git_SHA_CTX ctx;
454+
struct strbuf buf = STRBUF_INIT;
455+
int has_conflicts = 0;
456+
if (sha1)
457+
git_SHA1_Init(&ctx);
458+
459+
while (!io->getline(&buf, io)) {
460+
if (is_cmarker(buf.buf, '<', marker_size)) {
461+
has_conflicts = handle_conflict(io, marker_size,
462+
sha1 ? &ctx : NULL);
463+
if (has_conflicts < 0)
464+
break;
465+
} else
466+
rerere_io_putstr(buf.buf, io);
467+
}
468+
strbuf_release(&buf);
469+
462470
if (sha1)
463471
git_SHA1_Final(sha1, &ctx);
464-
if (hunk != RR_CONTEXT)
465-
return -1;
472+
466473
return has_conflicts;
467474
}
468475

0 commit comments

Comments
 (0)