checkout -m: no need to insist on having all 3 stages
The content level merge machinery ll_merge() is prepared to merge correctly in "both sides added differently" case by using an empty blob as if it were the common ancestor. "checkout -m" could do the same, but didn't bother supporting it and instead insisted on having all three stages. Reported-by: Pete Harlan Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		| @ -110,16 +110,21 @@ static int check_stage(int stage, struct cache_entry *ce, int pos) | |||||||
| 		return error(_("path '%s' does not have their version"), ce->name); | 		return error(_("path '%s' does not have their version"), ce->name); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int check_all_stages(struct cache_entry *ce, int pos) | static int check_stages(unsigned stages, struct cache_entry *ce, int pos) | ||||||
| { | { | ||||||
| 	if (ce_stage(ce) != 1 || | 	unsigned seen = 0; | ||||||
| 	    active_nr <= pos + 2 || | 	const char *name = ce->name; | ||||||
| 	    strcmp(active_cache[pos+1]->name, ce->name) || |  | ||||||
| 	    ce_stage(active_cache[pos+1]) != 2 || | 	while (pos < active_nr) { | ||||||
| 	    strcmp(active_cache[pos+2]->name, ce->name) || | 		ce = active_cache[pos]; | ||||||
| 	    ce_stage(active_cache[pos+2]) != 3) | 		if (strcmp(name, ce->name)) | ||||||
| 		return error(_("path '%s' does not have all three versions"), | 			break; | ||||||
| 			     ce->name); | 		seen |= (1 << ce_stage(ce)); | ||||||
|  | 		pos++; | ||||||
|  | 	} | ||||||
|  | 	if ((stages & seen) != stages) | ||||||
|  | 		return error(_("path '%s' does not have all necessary versions"), | ||||||
|  | 			     name); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -146,18 +151,27 @@ static int checkout_merged(int pos, struct checkout *state) | |||||||
| 	int status; | 	int status; | ||||||
| 	unsigned char sha1[20]; | 	unsigned char sha1[20]; | ||||||
| 	mmbuffer_t result_buf; | 	mmbuffer_t result_buf; | ||||||
|  | 	unsigned char threeway[3][20]; | ||||||
|  | 	unsigned mode; | ||||||
|  |  | ||||||
| 	if (ce_stage(ce) != 1 || | 	memset(threeway, 0, sizeof(threeway)); | ||||||
| 	    active_nr <= pos + 2 || | 	while (pos < active_nr) { | ||||||
| 	    strcmp(active_cache[pos+1]->name, path) || | 		int stage; | ||||||
| 	    ce_stage(active_cache[pos+1]) != 2 || | 		stage = ce_stage(ce); | ||||||
| 	    strcmp(active_cache[pos+2]->name, path) || | 		if (!stage || strcmp(path, ce->name)) | ||||||
| 	    ce_stage(active_cache[pos+2]) != 3) | 			break; | ||||||
| 		return error(_("path '%s' does not have all 3 versions"), path); | 		hashcpy(threeway[stage - 1], ce->sha1); | ||||||
|  | 		if (stage == 2) | ||||||
|  | 			mode = create_ce_mode(ce->ce_mode); | ||||||
|  | 		pos++; | ||||||
|  | 		ce = active_cache[pos]; | ||||||
|  | 	} | ||||||
|  | 	if (is_null_sha1(threeway[1]) || is_null_sha1(threeway[2])) | ||||||
|  | 		return error(_("path '%s' does not have necessary versions"), path); | ||||||
|  |  | ||||||
| 	read_mmblob(&ancestor, active_cache[pos]->sha1); | 	read_mmblob(&ancestor, threeway[0]); | ||||||
| 	read_mmblob(&ours, active_cache[pos+1]->sha1); | 	read_mmblob(&ours, threeway[1]); | ||||||
| 	read_mmblob(&theirs, active_cache[pos+2]->sha1); | 	read_mmblob(&theirs, threeway[2]); | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * NEEDSWORK: re-create conflicts from merges with | 	 * NEEDSWORK: re-create conflicts from merges with | ||||||
| @ -188,9 +202,7 @@ static int checkout_merged(int pos, struct checkout *state) | |||||||
| 	if (write_sha1_file(result_buf.ptr, result_buf.size, | 	if (write_sha1_file(result_buf.ptr, result_buf.size, | ||||||
| 			    blob_type, sha1)) | 			    blob_type, sha1)) | ||||||
| 		die(_("Unable to add merge result for '%s'"), path); | 		die(_("Unable to add merge result for '%s'"), path); | ||||||
| 	ce = make_cache_entry(create_ce_mode(active_cache[pos+1]->ce_mode), | 	ce = make_cache_entry(mode, sha1, path, 2, 0); | ||||||
| 			      sha1, |  | ||||||
| 			      path, 2, 0); |  | ||||||
| 	if (!ce) | 	if (!ce) | ||||||
| 		die(_("make_cache_entry failed for path '%s'"), path); | 		die(_("make_cache_entry failed for path '%s'"), path); | ||||||
| 	status = checkout_entry(ce, state, NULL); | 	status = checkout_entry(ce, state, NULL); | ||||||
| @ -246,7 +258,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec, | |||||||
| 			} else if (stage) { | 			} else if (stage) { | ||||||
| 				errs |= check_stage(stage, ce, pos); | 				errs |= check_stage(stage, ce, pos); | ||||||
| 			} else if (opts->merge) { | 			} else if (opts->merge) { | ||||||
| 				errs |= check_all_stages(ce, pos); | 				errs |= check_stages((1<<2) | (1<<3), ce, pos); | ||||||
| 			} else { | 			} else { | ||||||
| 				errs = 1; | 				errs = 1; | ||||||
| 				error(_("path '%s' is unmerged"), ce->name); | 				error(_("path '%s' is unmerged"), ce->name); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Junio C Hamano
					Junio C Hamano