static int handle_conflict(struct strbuf *out, struct rerere_io *io, int marker_size, git_hash_ctx *ctx) { enum { RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL } hunk = RR_SIDE_1; struct strbuf one = STRBUF_INIT, two = STRBUF_INIT; struct strbuf buf = STRBUF_INIT, conflict = STRBUF_INIT; int has_conflicts = -1; while (!io->getline(&buf, io)) { if (is_cmarker(buf.buf, '<', marker_size)) { if (handle_conflict(&conflict, io, marker_size, NULL) < 0) break; if (hunk == RR_SIDE_1) strbuf_addbuf(&one, &conflict); else strbuf_addbuf(&two, &conflict); strbuf_release(&conflict); } else if (is_cmarker(buf.buf, '|', marker_size)) { if (hunk != RR_SIDE_1) break; hunk = RR_ORIGINAL; } else if (is_cmarker(buf.buf, '=', marker_size)) { if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL) break; hunk = RR_SIDE_2; } else if (is_cmarker(buf.buf, '>', marker_size)) { if (hunk != RR_SIDE_2) break; if (strbuf_cmp(&one, &two) > 0) strbuf_swap(&one, &two); has_conflicts = 1; rerere_strbuf_putconflict(out, '<', marker_size); strbuf_addbuf(out, &one); rerere_strbuf_putconflict(out, '=', marker_size); strbuf_addbuf(out, &two); rerere_strbuf_putconflict(out, '>', marker_size); if (ctx) { the_hash_algo->update_fn(ctx, one.buf ? one.buf : "", one.len + 1); the_hash_algo->update_fn(ctx, two.buf ? two.buf : "", two.len + 1); } break; } else if (hunk == RR_SIDE_1) strbuf_addbuf(&one, &buf); else if (hunk == RR_ORIGINAL) ; /* discard */ else if (hunk == RR_SIDE_2) strbuf_addbuf(&two, &buf); } strbuf_release(&one); strbuf_release(&two); strbuf_release(&buf); return has_conflicts; }
/* * Read contents a file with conflicts, normalize the conflicts * by (1) discarding the common ancestor version in diff3-style, * (2) reordering our side and their side so that whichever sorts * alphabetically earlier comes before the other one, while * computing the "conflict ID", which is just an SHA-1 hash of * one side of the conflict, NUL, the other side of the conflict, * and NUL concatenated together. * * Return 1 if conflict hunks are found, 0 if there are no conflict * hunks and -1 if an error occured. */ static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size) { git_SHA_CTX ctx; struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT; int has_conflicts = 0; if (sha1) git_SHA1_Init(&ctx); while (!io->getline(&buf, io)) { if (is_cmarker(buf.buf, '<', marker_size)) { has_conflicts = handle_conflict(&out, io, marker_size, sha1 ? &ctx : NULL); if (has_conflicts < 0) break; rerere_io_putmem(out.buf, out.len, io); strbuf_reset(&out); } else rerere_io_putstr(buf.buf, io); } strbuf_release(&buf); strbuf_release(&out); if (sha1) git_SHA1_Final(sha1, &ctx); return has_conflicts; }
/* * Read contents a file with conflicts, normalize the conflicts * by (1) discarding the common ancestor version in diff3-style, * (2) reordering our side and their side so that whichever sorts * alphabetically earlier comes before the other one, while * computing the "conflict ID", which is just an SHA-1 hash of * one side of the conflict, NUL, the other side of the conflict, * and NUL concatenated together. * * Return 1 if conflict hunks are found, 0 if there are no conflict * hunks and -1 if an error occured. */ static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_size) { git_hash_ctx ctx; struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT; int has_conflicts = 0; if (hash) the_hash_algo->init_fn(&ctx); while (!io->getline(&buf, io)) { if (is_cmarker(buf.buf, '<', marker_size)) { has_conflicts = handle_conflict(&out, io, marker_size, hash ? &ctx : NULL); if (has_conflicts < 0) break; rerere_io_putmem(out.buf, out.len, io); strbuf_reset(&out); } else rerere_io_putstr(buf.buf, io); } strbuf_release(&buf); strbuf_release(&out); if (hash) the_hash_algo->final_fn(hash, &ctx); return has_conflicts; }
static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size) { git_SHA_CTX ctx; int hunk_no = 0; enum { RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL } hunk = RR_CONTEXT; struct strbuf one = STRBUF_INIT, two = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; if (sha1) git_SHA1_Init(&ctx); while (!io->getline(&buf, io)) { if (is_cmarker(buf.buf, '<', marker_size, 1)) { if (hunk != RR_CONTEXT) goto bad; hunk = RR_SIDE_1; } else if (is_cmarker(buf.buf, '|', marker_size, 0)) { if (hunk != RR_SIDE_1) goto bad; hunk = RR_ORIGINAL; } else if (is_cmarker(buf.buf, '=', marker_size, 0)) { if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL) goto bad; hunk = RR_SIDE_2; } else if (is_cmarker(buf.buf, '>', marker_size, 1)) { if (hunk != RR_SIDE_2) goto bad; if (strbuf_cmp(&one, &two) > 0) strbuf_swap(&one, &two); hunk_no++; hunk = RR_CONTEXT; rerere_io_putconflict('<', marker_size, io); rerere_io_putmem(one.buf, one.len, io); rerere_io_putconflict('=', marker_size, io); rerere_io_putmem(two.buf, two.len, io); rerere_io_putconflict('>', marker_size, io); if (sha1) { git_SHA1_Update(&ctx, one.buf ? one.buf : "", one.len + 1); git_SHA1_Update(&ctx, two.buf ? two.buf : "", two.len + 1); } strbuf_reset(&one); strbuf_reset(&two); } else if (hunk == RR_SIDE_1) strbuf_addbuf(&one, &buf); else if (hunk == RR_ORIGINAL) ; /* discard */ else if (hunk == RR_SIDE_2) strbuf_addbuf(&two, &buf); else rerere_io_putstr(buf.buf, io); continue; bad: hunk = 99; /* force error exit */ break; } strbuf_release(&one); strbuf_release(&two); strbuf_release(&buf); if (sha1) git_SHA1_Final(sha1, &ctx); if (hunk != RR_CONTEXT) return -1; return hunk_no; }