|
17 | 17 | #include "cache.h"
|
18 | 18 | #include "merge-ort.h"
|
19 | 19 |
|
| 20 | +#include "cache-tree.h" |
20 | 21 | #include "diff.h"
|
21 | 22 | #include "diffcore.h"
|
22 | 23 | #include "dir.h"
|
@@ -1026,10 +1027,95 @@ static int record_conflicted_index_entries(struct merge_options *opt,
|
1026 | 1027 | struct strmap *paths,
|
1027 | 1028 | struct strmap *conflicted)
|
1028 | 1029 | {
|
| 1030 | + struct hashmap_iter iter; |
| 1031 | + struct strmap_entry *e; |
| 1032 | + int errs = 0; |
| 1033 | + int original_cache_nr; |
| 1034 | + |
1029 | 1035 | if (strmap_empty(conflicted))
|
1030 | 1036 | return 0;
|
1031 | 1037 |
|
1032 |
| - die("Not yet implemented."); |
| 1038 | + original_cache_nr = index->cache_nr; |
| 1039 | + |
| 1040 | + /* Put every entry from paths into plist, then sort */ |
| 1041 | + strmap_for_each_entry(conflicted, &iter, e) { |
| 1042 | + const char *path = e->key; |
| 1043 | + struct conflict_info *ci = e->value; |
| 1044 | + int pos; |
| 1045 | + struct cache_entry *ce; |
| 1046 | + int i; |
| 1047 | + |
| 1048 | + VERIFY_CI(ci); |
| 1049 | + |
| 1050 | + /* |
| 1051 | + * The index will already have a stage=0 entry for this path, |
| 1052 | + * because we created an as-merged-as-possible version of the |
| 1053 | + * file and checkout() moved the working copy and index over |
| 1054 | + * to that version. |
| 1055 | + * |
| 1056 | + * However, previous iterations through this loop will have |
| 1057 | + * added unstaged entries to the end of the cache which |
| 1058 | + * ignore the standard alphabetical ordering of cache |
| 1059 | + * entries and break invariants needed for index_name_pos() |
| 1060 | + * to work. However, we know the entry we want is before |
| 1061 | + * those appended cache entries, so do a temporary swap on |
| 1062 | + * cache_nr to only look through entries of interest. |
| 1063 | + */ |
| 1064 | + SWAP(index->cache_nr, original_cache_nr); |
| 1065 | + pos = index_name_pos(index, path, strlen(path)); |
| 1066 | + SWAP(index->cache_nr, original_cache_nr); |
| 1067 | + if (pos < 0) { |
| 1068 | + if (ci->filemask != 1) |
| 1069 | + BUG("Conflicted %s but nothing in basic working tree or index; this shouldn't happen", path); |
| 1070 | + cache_tree_invalidate_path(index, path); |
| 1071 | + } else { |
| 1072 | + ce = index->cache[pos]; |
| 1073 | + |
| 1074 | + /* |
| 1075 | + * Clean paths with CE_SKIP_WORKTREE set will not be |
| 1076 | + * written to the working tree by the unpack_trees() |
| 1077 | + * call in checkout(). Our conflicted entries would |
| 1078 | + * have appeared clean to that code since we ignored |
| 1079 | + * the higher order stages. Thus, we need override |
| 1080 | + * the CE_SKIP_WORKTREE bit and manually write those |
| 1081 | + * files to the working disk here. |
| 1082 | + * |
| 1083 | + * TODO: Implement this CE_SKIP_WORKTREE fixup. |
| 1084 | + */ |
| 1085 | + |
| 1086 | + /* |
| 1087 | + * Mark this cache entry for removal and instead add |
| 1088 | + * new stage>0 entries corresponding to the |
| 1089 | + * conflicts. If there are many conflicted entries, we |
| 1090 | + * want to avoid memmove'ing O(NM) entries by |
| 1091 | + * inserting the new entries one at a time. So, |
| 1092 | + * instead, we just add the new cache entries to the |
| 1093 | + * end (ignoring normal index requirements on sort |
| 1094 | + * order) and sort the index once we're all done. |
| 1095 | + */ |
| 1096 | + ce->ce_flags |= CE_REMOVE; |
| 1097 | + } |
| 1098 | + |
| 1099 | + for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) { |
| 1100 | + struct version_info *vi; |
| 1101 | + if (!(ci->filemask & (1ul << i))) |
| 1102 | + continue; |
| 1103 | + vi = &ci->stages[i]; |
| 1104 | + ce = make_cache_entry(index, vi->mode, &vi->oid, |
| 1105 | + path, i+1, 0); |
| 1106 | + add_index_entry(index, ce, ADD_CACHE_JUST_APPEND); |
| 1107 | + } |
| 1108 | + } |
| 1109 | + |
| 1110 | + /* |
| 1111 | + * Remove the unused cache entries (and invalidate the relevant |
| 1112 | + * cache-trees), then sort the index entries to get the conflicted |
| 1113 | + * entries we added to the end into their right locations. |
| 1114 | + */ |
| 1115 | + remove_marked_cache_entries(index, 1); |
| 1116 | + QSORT(index->cache, index->cache_nr, cmp_cache_name_compare); |
| 1117 | + |
| 1118 | + return errs; |
1033 | 1119 | }
|
1034 | 1120 |
|
1035 | 1121 | void merge_switch_to_result(struct merge_options *opt,
|
|
0 commit comments