Exemplo n.º 1
0
static void rerere_io_putstr(const char *str, struct rerere_io *io)
{
	if (io->output)
		ferr_puts(str, io->output, &io->wrerror);
}
Exemplo n.º 2
0
Arquivo: rerere.c Projeto: emk/git
static int handle_file(const char *path,
	 unsigned char *sha1, const char *output)
{
	git_SHA_CTX ctx;
	char buf[1024];
	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;
	FILE *f = fopen(path, "r");
	FILE *out = NULL;
	int wrerror = 0;

	if (!f)
		return error("Could not open %s", path);

	if (output) {
		out = fopen(output, "w");
		if (!out) {
			fclose(f);
			return error("Could not write %s", output);
		}
	}

	if (sha1)
		git_SHA1_Init(&ctx);

	while (fgets(buf, sizeof(buf), f)) {
		if (!prefixcmp(buf, "<<<<<<< ")) {
			if (hunk != RR_CONTEXT)
				goto bad;
			hunk = RR_SIDE_1;
		} else if (!prefixcmp(buf, "|||||||") && isspace(buf[7])) {
			if (hunk != RR_SIDE_1)
				goto bad;
			hunk = RR_ORIGINAL;
		} else if (!prefixcmp(buf, "=======") && isspace(buf[7])) {
			if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
				goto bad;
			hunk = RR_SIDE_2;
		} else if (!prefixcmp(buf, ">>>>>>> ")) {
			if (hunk != RR_SIDE_2)
				goto bad;
			if (strbuf_cmp(&one, &two) > 0)
				strbuf_swap(&one, &two);
			hunk_no++;
			hunk = RR_CONTEXT;
			if (out) {
				ferr_puts("<<<<<<<\n", out, &wrerror);
				ferr_write(one.buf, one.len, out, &wrerror);
				ferr_puts("=======\n", out, &wrerror);
				ferr_write(two.buf, two.len, out, &wrerror);
				ferr_puts(">>>>>>>\n", out, &wrerror);
			}
			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_addstr(&one, buf);
		else if (hunk == RR_ORIGINAL)
			; /* discard */
		else if (hunk == RR_SIDE_2)
			strbuf_addstr(&two, buf);
		else if (out)
			ferr_puts(buf, out, &wrerror);
		continue;
	bad:
		hunk = 99; /* force error exit */
		break;
	}
	strbuf_release(&one);
	strbuf_release(&two);

	fclose(f);
	if (wrerror)
		error("There were errors while writing %s (%s)",
		      path, strerror(wrerror));
	if (out && fclose(out))
		wrerror = error("Failed to flush %s: %s",
				path, strerror(errno));
	if (sha1)
		git_SHA1_Final(sha1, &ctx);
	if (hunk != RR_CONTEXT) {
		if (output)
			unlink(output);
		return error("Could not parse conflict hunks in %s", path);
	}
	if (wrerror)
		return -1;
	return hunk_no;
}