rerere.c 8.3 KB
Newer Older
1
#include "cache.h"
2
#include "string-list.h"
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#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;

static const char *rr_path(const char *name, const char *file)
{
	return git_path("rr-cache/%s/%s", name, file);
}

static int has_resolution(const char *name)
{
	struct stat st;
	return !stat(rr_path(name, "postimage"), &st);
}

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 64 65 66 67 68 69 70 71 72 73 74 75 76 77
		length = strlen(path) + 1;
		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
		    write_in_full(out_fd, "\t", 1) != 1 ||
		    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;
}

static int handle_file(const char *path,
	 unsigned char *sha1, const char *output)
{
	SHA_CTX ctx;
	char buf[1024];
78 79 80 81
	int hunk_no = 0;
	enum {
		RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2,
	} hunk = RR_CONTEXT;
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
	struct strbuf one, two;
	FILE *f = fopen(path, "r");
	FILE *out = NULL;

	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)
		SHA1_Init(&ctx);

	strbuf_init(&one, 0);
	strbuf_init(&two,  0);
	while (fgets(buf, sizeof(buf), f)) {
		if (!prefixcmp(buf, "<<<<<<< ")) {
104
			if (hunk != RR_CONTEXT)
105
				goto bad;
106
			hunk = RR_SIDE_1;
107
		} else if (!prefixcmp(buf, "=======") && isspace(buf[7])) {
108
			if (hunk != RR_SIDE_1)
109
				goto bad;
110
			hunk = RR_SIDE_2;
111
		} else if (!prefixcmp(buf, ">>>>>>> ")) {
112
			if (hunk != RR_SIDE_2)
113 114 115 116
				goto bad;
			if (strbuf_cmp(&one, &two) > 0)
				strbuf_swap(&one, &two);
			hunk_no++;
117
			hunk = RR_CONTEXT;
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
			if (out) {
				fputs("<<<<<<<\n", out);
				fwrite(one.buf, one.len, 1, out);
				fputs("=======\n", out);
				fwrite(two.buf, two.len, 1, out);
				fputs(">>>>>>>\n", out);
			}
			if (sha1) {
				SHA1_Update(&ctx, one.buf ? one.buf : "",
					    one.len + 1);
				SHA1_Update(&ctx, two.buf ? two.buf : "",
					    two.len + 1);
			}
			strbuf_reset(&one);
			strbuf_reset(&two);
133
		} else if (hunk == RR_SIDE_1)
134
			strbuf_addstr(&one, buf);
135
		else if (hunk == RR_SIDE_2)
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
			strbuf_addstr(&two, buf);
		else if (out)
			fputs(buf, out);
		continue;
	bad:
		hunk = 99; /* force error exit */
		break;
	}
	strbuf_release(&one);
	strbuf_release(&two);

	fclose(f);
	if (out)
		fclose(out);
	if (sha1)
		SHA1_Final(sha1, &ctx);
152
	if (hunk != RR_CONTEXT) {
153 154 155 156 157 158 159
		if (output)
			unlink(output);
		return error("Could not parse conflict hunks in %s", path);
	}
	return hunk_no;
}

160
static int find_conflict(struct string_list *conflict)
161 162 163 164 165 166 167 168 169 170 171 172
{
	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)) {
173
			string_list_insert((const char *)e2->name, conflict);
174 175 176 177 178 179 180 181 182 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
			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};

	if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
		return 1;

	if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
			read_mmfile(&base, rr_path(name, "preimage")) ||
			read_mmfile(&other, rr_path(name, "postimage")))
		return 1;
	ret = xdl_merge(&base, &cur, "", &other, "",
			&xpp, XDL_MERGE_ZEALOUS, &result);
	if (!ret) {
		FILE *f = fopen(path, "w");
		if (!f)
			return error("Could not write to %s", path);
		fwrite(result.ptr, result.size, 1, f);
		fclose(f);
	}

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

	return ret;
}

static struct lock_file index_lock;

214
static int update_paths(struct string_list *update)
215 216 217 218 219 220 221 222 223
{
	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++) {
224 225
		struct string_list_item *item = &update->items[i];
		if (add_file_to_cache(item->string, ADD_CACHE_IGNORE_ERRORS))
226 227 228 229 230 231 232 233 234 235 236 237
			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;
}

238
static int do_plain_rerere(struct string_list *rr, int fd)
239
{
240 241
	struct string_list conflict = { NULL, 0, 0, 1 };
	struct string_list update = { NULL, 0, 0, 1 };
242 243 244 245 246 247 248 249 250 251 252 253
	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++) {
254 255
		const char *path = conflict.items[i].string;
		if (!string_list_has_string(rr, path)) {
256 257 258 259 260 261 262
			unsigned char sha1[20];
			char *hex;
			int ret;
			ret = handle_file(path, sha1, NULL);
			if (ret < 1)
				continue;
			hex = xstrdup(sha1_to_hex(sha1));
263
			string_list_insert(path, rr)->util = hex;
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
			if (mkdir(git_path("rr-cache/%s", hex), 0755))
				continue;;
			handle_file(path, NULL, rr_path(hex, "preimage"));
			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;
279
		const char *path = rr->items[i].string;
280 281 282 283 284
		const char *name = (const char *)rr->items[i].util;

		if (has_resolution(name)) {
			if (!merge(name, path)) {
				if (rerere_autoupdate)
285
					string_list_insert(path, &update);
286 287 288 289 290
				fprintf(stderr,
					"%s '%s' using previous resolution.\n",
					rerere_autoupdate
					? "Staged" : "Resolved",
					path);
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
				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);
		copy_file(rr_path(name, "postimage"), path, 0666);
	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)
{
	struct stat st;
	const char *rr_cache;
	int rr_cache_exists;

	if (!rerere_enabled)
		return 0;

	rr_cache = git_path("rr-cache");
	rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
	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;
}

343
int setup_rerere(struct string_list *merge_rr)
344 345 346 347 348 349 350
{
	int fd;

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

J
Junio C Hamano 已提交
351
	merge_rr_path = xstrdup(git_path("MERGE_RR"));
352 353 354 355 356 357 358
	fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
	read_rr(merge_rr);
	return fd;
}

int rerere(void)
{
359
	struct string_list merge_rr = { NULL, 0, 0, 1 };
360 361 362 363 364 365 366
	int fd;

	fd = setup_rerere(&merge_rr);
	if (fd < 0)
		return 0;
	return do_plain_rerere(&merge_rr, fd);
}