rerere.c 9.4 KB
Newer Older
1
#include "cache.h"
2
#include "string-list.h"
3 4 5 6 7 8 9 10 11 12 13 14
#include "rerere.h"
#include "xdiff/xdiff.h"
#include "xdiff-interface.h"

/* 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;

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

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

26
static void read_rr(struct string_list *rr)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
{
	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");
46
		string_list_insert(buf, rr)->util = name;
47 48 49 50 51 52
	}
	fclose(in);
}

static struct lock_file write_lock;

53
static int write_rr(struct string_list *rr, int out_fd)
54 55 56 57 58 59 60
{
	int i;
	for (i = 0; i < rr->nr; i++) {
		const char *path;
		int length;
		if (!rr->items[i].util)
			continue;
61
		path = rr->items[i].string;
62 63
		length = strlen(path) + 1;
		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
64
		    write_str_in_full(out_fd, "\t") != 1 ||
65 66 67 68 69 70 71 72
		    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;
}

73 74 75 76 77 78 79 80 81 82 83 84 85
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);
}

86 87 88
static int handle_file(const char *path,
	 unsigned char *sha1, const char *output)
{
89
	git_SHA_CTX ctx;
90
	char buf[1024];
91 92
	int hunk_no = 0;
	enum {
93
		RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL,
94
	} hunk = RR_CONTEXT;
95
	struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
96 97
	FILE *f = fopen(path, "r");
	FILE *out = NULL;
98
	int wrerror = 0;
99 100 101 102 103 104 105 106 107 108 109 110 111

	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)
112
		git_SHA1_Init(&ctx);
113 114 115

	while (fgets(buf, sizeof(buf), f)) {
		if (!prefixcmp(buf, "<<<<<<< ")) {
116
			if (hunk != RR_CONTEXT)
117
				goto bad;
118
			hunk = RR_SIDE_1;
119
		} else if (!prefixcmp(buf, "|||||||") && isspace(buf[7])) {
120
			if (hunk != RR_SIDE_1)
121
				goto bad;
122
			hunk = RR_ORIGINAL;
123
		} else if (!prefixcmp(buf, "=======") && isspace(buf[7])) {
124
			if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
125
				goto bad;
126
			hunk = RR_SIDE_2;
127
		} else if (!prefixcmp(buf, ">>>>>>> ")) {
128
			if (hunk != RR_SIDE_2)
129 130 131 132
				goto bad;
			if (strbuf_cmp(&one, &two) > 0)
				strbuf_swap(&one, &two);
			hunk_no++;
133
			hunk = RR_CONTEXT;
134
			if (out) {
135 136 137 138 139
				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);
140 141
			}
			if (sha1) {
142
				git_SHA1_Update(&ctx, one.buf ? one.buf : "",
143
					    one.len + 1);
144
				git_SHA1_Update(&ctx, two.buf ? two.buf : "",
145 146 147 148
					    two.len + 1);
			}
			strbuf_reset(&one);
			strbuf_reset(&two);
149
		} else if (hunk == RR_SIDE_1)
150
			strbuf_addstr(&one, buf);
151 152
		else if (hunk == RR_ORIGINAL)
			; /* discard */
153
		else if (hunk == RR_SIDE_2)
154 155
			strbuf_addstr(&two, buf);
		else if (out)
156
			ferr_puts(buf, out, &wrerror);
157 158 159 160 161 162 163 164 165
		continue;
	bad:
		hunk = 99; /* force error exit */
		break;
	}
	strbuf_release(&one);
	strbuf_release(&two);

	fclose(f);
166 167 168 169 170 171
	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));
172
	if (sha1)
173
		git_SHA1_Final(sha1, &ctx);
174
	if (hunk != RR_CONTEXT) {
175
		if (output)
176
			unlink_or_warn(output);
177 178
		return error("Could not parse conflict hunks in %s", path);
	}
179 180
	if (wrerror)
		return -1;
181 182 183
	return hunk_no;
}

184
static int find_conflict(struct string_list *conflict)
185 186 187 188 189 190 191 192 193 194 195 196
{
	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)) {
197
			string_list_insert((const char *)e2->name, conflict);
198 199 200 201 202 203 204 205 206 207 208 209 210
			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};
	xpparam_t xpp = {XDF_NEED_MINIMAL};

211
	if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
212 213
		return 1;

214 215 216
	if (read_mmfile(&cur, rerere_path(name, "thisimage")) ||
			read_mmfile(&base, rerere_path(name, "preimage")) ||
			read_mmfile(&other, rerere_path(name, "postimage")))
217 218 219 220 221 222
		return 1;
	ret = xdl_merge(&base, &cur, "", &other, "",
			&xpp, XDL_MERGE_ZEALOUS, &result);
	if (!ret) {
		FILE *f = fopen(path, "w");
		if (!f)
223 224 225 226 227 228 229
			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));
230 231 232 233 234 235 236 237 238 239 240 241
	}

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

	return ret;
}

static struct lock_file index_lock;

242
static int update_paths(struct string_list *update)
243 244 245 246 247 248 249 250 251
{
	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++) {
252 253
		struct string_list_item *item = &update->items[i];
		if (add_file_to_cache(item->string, ADD_CACHE_IGNORE_ERRORS))
254 255 256 257 258 259 260 261 262 263 264 265
			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;
}

266
static int do_plain_rerere(struct string_list *rr, int fd)
267
{
268 269
	struct string_list conflict = { NULL, 0, 0, 1 };
	struct string_list update = { NULL, 0, 0, 1 };
270 271 272 273 274 275 276 277 278 279 280 281
	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++) {
282 283
		const char *path = conflict.items[i].string;
		if (!string_list_has_string(rr, path)) {
284 285 286 287 288 289 290
			unsigned char sha1[20];
			char *hex;
			int ret;
			ret = handle_file(path, sha1, NULL);
			if (ret < 1)
				continue;
			hex = xstrdup(sha1_to_hex(sha1));
291
			string_list_insert(path, rr)->util = hex;
292
			if (mkdir(git_path("rr-cache/%s", hex), 0755))
J
Junio C Hamano 已提交
293
				continue;
294
			handle_file(path, NULL, rerere_path(hex, "preimage"));
295 296 297 298 299 300 301 302 303 304 305 306
			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;
307
		const char *path = rr->items[i].string;
308 309
		const char *name = (const char *)rr->items[i].util;

310
		if (has_rerere_resolution(name)) {
311 312
			if (!merge(name, path)) {
				if (rerere_autoupdate)
313
					string_list_insert(path, &update);
314 315 316 317 318
				fprintf(stderr,
					"%s '%s' using previous resolution.\n",
					rerere_autoupdate
					? "Staged" : "Resolved",
					path);
319 320 321 322 323 324 325 326 327 328
				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);
329
		copy_file(rerere_path(name, "postimage"), path, 0666);
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
	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");
360
	rr_cache_exists = is_directory(rr_cache);
361 362 363 364 365 366 367 368 369
	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;
}

370
int setup_rerere(struct string_list *merge_rr, int flags)
371 372 373 374 375 376 377
{
	int fd;

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

378 379
	if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
		rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
380
	merge_rr_path = git_pathdup("MERGE_RR");
381 382
	fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
				       LOCK_DIE_ON_ERROR);
383 384 385 386
	read_rr(merge_rr);
	return fd;
}

387
int rerere(int flags)
388
{
389
	struct string_list merge_rr = { NULL, 0, 0, 1 };
390 391
	int fd;

392
	fd = setup_rerere(&merge_rr, flags);
393 394 395 396
	if (fd < 0)
		return 0;
	return do_plain_rerere(&merge_rr, fd);
}