diff options
| author | Junio C Hamano <gitster@pobox.com> | 2009-12-25 13:40:02 -0800 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2009-12-25 17:10:10 -0800 | 
| commit | 8aa38563b22c84b06ea1fff9638cc1f44fda726f (patch) | |
| tree | 3631ade1815f7d590ba6e4af48559ed2aab5e382 | |
| parent | 4421a8235783d0664faa9a1d45be114fd7ad8206 (diff) | |
resolve-undo: teach "update-index --unresolve" to use resolve-undo info
The update-index plumbing command had a hacky --unresolve implementation
that was written back in the days when merge was the only way for users to
end up with higher stages in the index, and assumed that stage #2 must
have come from HEAD, stage #3 from MERGE_HEAD and didn't bother to compute
the stage #1 information.
There were several issues with this approach:
 - These days, merge is not the only command, and conflicts coming from
   commands like cherry-pick, "am -3", etc. cannot be recreated by looking
   at MERGE_HEAD;
 - For a conflict that came from a merge that had renames, picking up the
   same path from MERGE_HEAD and HEAD wouldn't help recreating it, either;
 - It may have been Ok not to recreate stage #1 back when it was written,
   because "diff --ours/--theirs" were the only availble ways to review
   conflicts and they don't need stage #1 information.  "diff --cc" that
   was invented much later is a lot more useful way but it needs stage #1.
We can use resolve-undo information recorded in the index extension to
solve all of these issues.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
| -rw-r--r-- | builtin-update-index.c | 13 | ||||
| -rw-r--r-- | cache.h | 1 | ||||
| -rwxr-xr-x | t/t2030-unresolve-info.sh | 7 | 
3 files changed, 20 insertions, 1 deletions
| diff --git a/builtin-update-index.c b/builtin-update-index.c index a19e78603c..750db163b9 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -433,7 +433,18 @@ static int unresolve_one(const char *path)  	/* See if there is such entry in the index. */  	pos = cache_name_pos(path, namelen); -	if (pos < 0) { +	if (0 <= pos) { +		/* already merged */ +		pos = unmerge_cache_entry_at(pos); +		if (pos < active_nr) { +			struct cache_entry *ce = active_cache[pos]; +			if (ce_stage(ce) && +			    ce_namelen(ce) == namelen && +			    !memcmp(ce->name, path, namelen)) +				return 0; +		} +		/* no resolve-undo information; fall back */ +	} else {  		/* If there isn't, either it is unmerged, or  		 * resolved as "removed" by mistake.  We do not  		 * want to do anything in the former case. @@ -338,6 +338,7 @@ static inline void remove_name_hash(struct cache_entry *ce)  #define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))  #define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))  #define resolve_undo_clear() resolve_undo_clear_index(&the_index) +#define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)  #define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)  #endif diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index ea65f391c1..28e2eb1cec 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -108,4 +108,11 @@ test_expect_success 'add records checkout -m undoes' '  	grep "^++<<<<<<<" actual  ' +test_expect_success 'unmerge with plumbing' ' +	prime_resolve_undo && +	git update-index --unresolve file && +	git ls-files -u >actual && +	test $(wc -l <actual) = 3 +' +  test_done | 
