rerere.c 13.3 KB
Newer Older
1
#include "cache.h"
2
#include "string-list.h"
3 4
#include "rerere.h"
#include "xdiff-interface.h"
5 6 7
#include "dir.h"
#include "resolve-undo.h"
#include "ll-merge.h"
8 9 10 11 12 13 14 15 16

/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
static int rerere_enabled = -1;

/* automatically update cleanly resolved paths to the index */
static int rerere_autoupdate;

static char *merge_rr_path;

17
const char *rerere_path(const char *hex, const char *file)
18
{
19
	return git_path("rr-cache/%s/%s", hex, file);
20 21
}

22
int has_rerere_resolution(const char *hex)
23 24
{
	struct stat st;
25
	return !stat(rerere_path(hex, "postimage"), &st);
26 27
}

28
static void read_rr(struct string_list *rr)
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
{
	unsigned char sha1[20];
	char buf[PATH_MAX];
	FILE *in = fopen(merge_rr_path, "r");
	if (!in)
		return;
	while (fread(buf, 40, 1, in) == 1) {
		int i;
		char *name;
		if (get_sha1_hex(buf, sha1))
			die("corrupt MERGE_RR");
		buf[40] = '\0';
		name = xstrdup(buf);
		if (fgetc(in) != '\t')
			die("corrupt MERGE_RR");
		for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
			; /* do nothing */
		if (i == sizeof(buf))
			die("filename too long");
48
		string_list_insert(buf, rr)->util = name;
49 50 51 52 53 54
	}
	fclose(in);
}

static struct lock_file write_lock;

55
static int write_rr(struct string_list *rr, int out_fd)
56 57 58 59 60 61 62
{
	int i;
	for (i = 0; i < rr->nr; i++) {
		const char *path;
		int length;
		if (!rr->items[i].util)
			continue;
63
		path = rr->items[i].string;
64 65
		length = strlen(path) + 1;
		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
66
		    write_str_in_full(out_fd, "\t") != 1 ||
67 68 69 70 71 72 73 74
		    write_in_full(out_fd, path, length) != length)
			die("unable to write rerere record");
	}
	if (commit_lock_file(&write_lock) != 0)
		die("unable to write rerere record");
	return 0;
}

75 76 77 78 79 80 81 82 83 84 85 86 87
static void ferr_write(const void *p, size_t count, FILE *fp, int *err)
{
	if (!count || *err)
		return;
	if (fwrite(p, count, 1, fp) != 1)
		*err = errno;
}

static inline void ferr_puts(const char *s, FILE *fp, int *err)
{
	ferr_write(s, strlen(s), fp, err);
}

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
struct rerere_io {
	int (*getline)(struct strbuf *, struct rerere_io *);
	FILE *output;
	int wrerror;
	/* some more stuff */
};

static void rerere_io_putstr(const char *str, struct rerere_io *io)
{
	if (io->output)
		ferr_puts(str, io->output, &io->wrerror);
}

static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)
{
	if (io->output)
		ferr_write(mem, sz, io->output, &io->wrerror);
}

struct rerere_io_file {
	struct rerere_io io;
	FILE *input;
};

static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_)
{
	struct rerere_io_file *io = (struct rerere_io_file *)io_;
	return strbuf_getwholeline(sb, io->input, '\n');
}

static int handle_path(unsigned char *sha1, struct rerere_io *io)
119
{
120
	git_SHA_CTX ctx;
121 122
	int hunk_no = 0;
	enum {
123
		RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL,
124
	} hunk = RR_CONTEXT;
125
	struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
126
	struct strbuf buf = STRBUF_INIT;
127 128

	if (sha1)
129
		git_SHA1_Init(&ctx);
130

131
	while (!io->getline(&buf, io)) {
132
		if (!prefixcmp(buf.buf, "<<<<<<< ")) {
133
			if (hunk != RR_CONTEXT)
134
				goto bad;
135
			hunk = RR_SIDE_1;
136
		} else if (!prefixcmp(buf.buf, "|||||||") && isspace(buf.buf[7])) {
137
			if (hunk != RR_SIDE_1)
138
				goto bad;
139
			hunk = RR_ORIGINAL;
140
		} else if (!prefixcmp(buf.buf, "=======") && isspace(buf.buf[7])) {
141
			if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
142
				goto bad;
143
			hunk = RR_SIDE_2;
144
		} else if (!prefixcmp(buf.buf, ">>>>>>> ")) {
145
			if (hunk != RR_SIDE_2)
146 147 148 149
				goto bad;
			if (strbuf_cmp(&one, &two) > 0)
				strbuf_swap(&one, &two);
			hunk_no++;
150
			hunk = RR_CONTEXT;
151 152 153 154 155
			rerere_io_putstr("<<<<<<<\n", io);
			rerere_io_putmem(one.buf, one.len, io);
			rerere_io_putstr("=======\n", io);
			rerere_io_putmem(two.buf, two.len, io);
			rerere_io_putstr(">>>>>>>\n", io);
156
			if (sha1) {
157
				git_SHA1_Update(&ctx, one.buf ? one.buf : "",
158
					    one.len + 1);
159
				git_SHA1_Update(&ctx, two.buf ? two.buf : "",
160 161 162 163
					    two.len + 1);
			}
			strbuf_reset(&one);
			strbuf_reset(&two);
164
		} else if (hunk == RR_SIDE_1)
165
			strbuf_addstr(&one, buf.buf);
166 167
		else if (hunk == RR_ORIGINAL)
			; /* discard */
168
		else if (hunk == RR_SIDE_2)
169
			strbuf_addstr(&two, buf.buf);
170 171
		else
			rerere_io_putstr(buf.buf, io);
172 173 174 175 176 177 178
		continue;
	bad:
		hunk = 99; /* force error exit */
		break;
	}
	strbuf_release(&one);
	strbuf_release(&two);
179
	strbuf_release(&buf);
180 181

	if (sha1)
182
		git_SHA1_Final(sha1, &ctx);
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
	if (hunk != RR_CONTEXT)
		return -1;
	return hunk_no;
}

static int handle_file(const char *path, unsigned char *sha1, const char *output)
{
	int hunk_no = 0;
	struct rerere_io_file io;

	memset(&io, 0, sizeof(io));
	io.io.getline = rerere_file_getline;
	io.input = fopen(path, "r");
	io.io.wrerror = 0;
	if (!io.input)
		return error("Could not open %s", path);

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

	hunk_no = handle_path(sha1, (struct rerere_io *)&io);

	fclose(io.input);
	if (io.io.wrerror)
		error("There were errors while writing %s (%s)",
		      path, strerror(io.io.wrerror));
	if (io.io.output && fclose(io.io.output))
		io.io.wrerror = error("Failed to flush %s: %s",
				      path, strerror(errno));

	if (hunk_no < 0) {
219
		if (output)
220
			unlink_or_warn(output);
221 222
		return error("Could not parse conflict hunks in %s", path);
	}
223
	if (io.io.wrerror)
224
		return -1;
225 226 227
	return hunk_no;
}

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
struct rerere_io_mem {
	struct rerere_io io;
	struct strbuf input;
};

static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)
{
	struct rerere_io_mem *io = (struct rerere_io_mem *)io_;
	char *ep;
	size_t len;

	strbuf_release(sb);
	if (!io->input.len)
		return -1;
	ep = strchrnul(io->input.buf, '\n');
	if (*ep == '\n')
		ep++;
	len = ep - io->input.buf;
	strbuf_add(sb, io->input.buf, len);
	strbuf_remove(&io->input, 0, len);
	return 0;
}

static int handle_cache(const char *path, unsigned char *sha1, const char *output)
{
	mmfile_t mmfile[3];
	mmbuffer_t result = {NULL, 0};
	struct cache_entry *ce;
	int pos, len, i, hunk_no;
	struct rerere_io_mem io;

	/*
	 * Reproduce the conflicted merge in-core
	 */
	len = strlen(path);
	pos = cache_name_pos(path, len);
	if (0 <= pos)
		return -1;
	pos = -pos - 1;

	for (i = 0; i < 3; i++) {
		enum object_type type;
		unsigned long size;

		mmfile[i].size = 0;
		mmfile[i].ptr = NULL;
		if (active_nr <= pos)
			break;
		ce = active_cache[pos++];
		if (ce_namelen(ce) != len || memcmp(ce->name, path, len)
		    || ce_stage(ce) != i + 1)
			break;
		mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size);
		mmfile[i].size = size;
	}
	for (i = 0; i < 3; i++) {
		if (!mmfile[i].ptr && !mmfile[i].size)
			mmfile[i].ptr = xstrdup("");
	}
	ll_merge(&result, path, &mmfile[0],
		 &mmfile[1], "ours",
		 &mmfile[2], "theirs", 0);
	for (i = 0; i < 3; i++)
		free(mmfile[i].ptr);

	memset(&io, 0, sizeof(&io));
	io.io.getline = rerere_mem_getline;
	if (output)
		io.io.output = fopen(output, "w");
	else
		io.io.output = NULL;
	strbuf_init(&io.input, 0);
	strbuf_attach(&io.input, result.ptr, result.size, result.size);

	hunk_no = handle_path(sha1, (struct rerere_io *)&io);
	strbuf_release(&io.input);
	if (io.io.output)
		fclose(io.io.output);
	return hunk_no;
}

309
static int find_conflict(struct string_list *conflict)
310 311 312 313 314 315 316 317 318 319 320 321
{
	int i;
	if (read_cache() < 0)
		return error("Could not read index");
	for (i = 0; i+1 < active_nr; i++) {
		struct cache_entry *e2 = active_cache[i];
		struct cache_entry *e3 = active_cache[i+1];
		if (ce_stage(e2) == 2 &&
		    ce_stage(e3) == 3 &&
		    ce_same_name(e2, e3) &&
		    S_ISREG(e2->ce_mode) &&
		    S_ISREG(e3->ce_mode)) {
322
			string_list_insert((const char *)e2->name, conflict);
323 324 325 326 327 328 329 330 331 332 333 334
			i++; /* skip over both #2 and #3 */
		}
	}
	return 0;
}

static int merge(const char *name, const char *path)
{
	int ret;
	mmfile_t cur, base, other;
	mmbuffer_t result = {NULL, 0};

335
	if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
336 337
		return 1;

338 339 340
	if (read_mmfile(&cur, rerere_path(name, "thisimage")) ||
			read_mmfile(&base, rerere_path(name, "preimage")) ||
			read_mmfile(&other, rerere_path(name, "postimage")))
341
		return 1;
342
	ret = ll_merge(&result, path, &base, &cur, "", &other, "", 0);
343 344 345
	if (!ret) {
		FILE *f = fopen(path, "w");
		if (!f)
346 347 348 349 350 351 352
			return error("Could not open %s: %s", path,
				     strerror(errno));
		if (fwrite(result.ptr, result.size, 1, f) != 1)
			error("Could not write %s: %s", path, strerror(errno));
		if (fclose(f))
			return error("Writing %s failed: %s", path,
				     strerror(errno));
353 354 355 356 357 358 359 360 361 362 363 364
	}

	free(cur.ptr);
	free(base.ptr);
	free(other.ptr);
	free(result.ptr);

	return ret;
}

static struct lock_file index_lock;

365
static int update_paths(struct string_list *update)
366 367 368 369 370 371 372 373 374
{
	int i;
	int fd = hold_locked_index(&index_lock, 0);
	int status = 0;

	if (fd < 0)
		return -1;

	for (i = 0; i < update->nr; i++) {
375 376
		struct string_list_item *item = &update->items[i];
		if (add_file_to_cache(item->string, ADD_CACHE_IGNORE_ERRORS))
377 378 379 380 381 382 383 384 385 386 387 388
			status = -1;
	}

	if (!status && active_cache_changed) {
		if (write_cache(fd, active_cache, active_nr) ||
		    commit_locked_index(&index_lock))
			die("Unable to write new index file");
	} else if (fd >= 0)
		rollback_lock_file(&index_lock);
	return status;
}

389
static int do_plain_rerere(struct string_list *rr, int fd)
390
{
391 392
	struct string_list conflict = { NULL, 0, 0, 1 };
	struct string_list update = { NULL, 0, 0, 1 };
393 394 395 396 397 398 399 400 401 402 403 404
	int i;

	find_conflict(&conflict);

	/*
	 * MERGE_RR records paths with conflicts immediately after merge
	 * failed.  Some of the conflicted paths might have been hand resolved
	 * in the working tree since then, but the initial run would catch all
	 * and register their preimages.
	 */

	for (i = 0; i < conflict.nr; i++) {
405 406
		const char *path = conflict.items[i].string;
		if (!string_list_has_string(rr, path)) {
407 408 409 410 411 412 413
			unsigned char sha1[20];
			char *hex;
			int ret;
			ret = handle_file(path, sha1, NULL);
			if (ret < 1)
				continue;
			hex = xstrdup(sha1_to_hex(sha1));
414
			string_list_insert(path, rr)->util = hex;
415
			if (mkdir(git_path("rr-cache/%s", hex), 0755))
J
Junio C Hamano 已提交
416
				continue;
417
			handle_file(path, NULL, rerere_path(hex, "preimage"));
418 419 420 421 422 423 424 425 426 427 428 429
			fprintf(stderr, "Recorded preimage for '%s'\n", path);
		}
	}

	/*
	 * Now some of the paths that had conflicts earlier might have been
	 * hand resolved.  Others may be similar to a conflict already that
	 * was resolved before.
	 */

	for (i = 0; i < rr->nr; i++) {
		int ret;
430
		const char *path = rr->items[i].string;
431 432
		const char *name = (const char *)rr->items[i].util;

433
		if (has_rerere_resolution(name)) {
434 435
			if (!merge(name, path)) {
				if (rerere_autoupdate)
436
					string_list_insert(path, &update);
437 438 439 440 441
				fprintf(stderr,
					"%s '%s' using previous resolution.\n",
					rerere_autoupdate
					? "Staged" : "Resolved",
					path);
442 443 444 445 446 447 448 449 450 451
				goto mark_resolved;
			}
		}

		/* Let's see if we have resolved it. */
		ret = handle_file(path, NULL, NULL);
		if (ret)
			continue;

		fprintf(stderr, "Recorded resolution for '%s'.\n", path);
452
		copy_file(rerere_path(name, "postimage"), path, 0666);
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
	mark_resolved:
		rr->items[i].util = NULL;
	}

	if (update.nr)
		update_paths(&update);

	return write_rr(rr, fd);
}

static int git_rerere_config(const char *var, const char *value, void *cb)
{
	if (!strcmp(var, "rerere.enabled"))
		rerere_enabled = git_config_bool(var, value);
	else if (!strcmp(var, "rerere.autoupdate"))
		rerere_autoupdate = git_config_bool(var, value);
	else
		return git_default_config(var, value, cb);
	return 0;
}

static int is_rerere_enabled(void)
{
	const char *rr_cache;
	int rr_cache_exists;

	if (!rerere_enabled)
		return 0;

	rr_cache = git_path("rr-cache");
483
	rr_cache_exists = is_directory(rr_cache);
484 485 486 487 488 489 490 491 492
	if (rerere_enabled < 0)
		return rr_cache_exists;

	if (!rr_cache_exists &&
	    (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
		die("Could not create directory %s", rr_cache);
	return 1;
}

493
int setup_rerere(struct string_list *merge_rr)
494 495 496 497 498 499 500
{
	int fd;

	git_config(git_rerere_config, NULL);
	if (!is_rerere_enabled())
		return -1;

501
	merge_rr_path = git_pathdup("MERGE_RR");
502 503
	fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
				       LOCK_DIE_ON_ERROR);
504 505 506 507 508 509
	read_rr(merge_rr);
	return fd;
}

int rerere(void)
{
510
	struct string_list merge_rr = { NULL, 0, 0, 1 };
511 512 513 514 515 516 517
	int fd;

	fd = setup_rerere(&merge_rr);
	if (fd < 0)
		return 0;
	return do_plain_rerere(&merge_rr, fd);
}
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566

static int rerere_forget_one_path(const char *path, struct string_list *rr)
{
	const char *filename;
	char *hex;
	unsigned char sha1[20];
	int ret;

	ret = handle_cache(path, sha1, NULL);
	if (ret < 1)
		return error("Could not parse conflict hunks in '%s'", path);
	hex = xstrdup(sha1_to_hex(sha1));
	filename = rerere_path(hex, "postimage");
	if (unlink(filename))
		return (errno == ENOENT
			? error("no remembered resolution for %s", path)
			: error("cannot unlink %s: %s", filename, strerror(errno)));

	handle_cache(path, sha1, rerere_path(hex, "preimage"));
	fprintf(stderr, "Updated preimage for '%s'\n", path);


	string_list_insert(path, rr)->util = hex;
	fprintf(stderr, "Forgot resolution for %s\n", path);
	return 0;
}

int rerere_forget(const char **pathspec)
{
	int i, fd;
	struct string_list conflict = { NULL, 0, 0, 1 };
	struct string_list merge_rr = { NULL, 0, 0, 1 };

	if (read_cache() < 0)
		return error("Could not read index");

	fd = setup_rerere(&merge_rr);

	unmerge_cache(pathspec);
	find_conflict(&conflict);
	for (i = 0; i < conflict.nr; i++) {
		struct string_list_item *it = &conflict.items[i];
		if (!match_pathspec(pathspec, it->string, strlen(it->string),
				    0, NULL))
			continue;
		rerere_forget_one_path(it->string, &merge_rr);
	}
	return write_rr(&merge_rr, fd);
}