diff options
Diffstat (limited to 'rerere.c')
-rw-r--r-- | rerere.c | 85 |
1 files changed, 71 insertions, 14 deletions
@@ -7,6 +7,11 @@ #include "ll-merge.h" #include "attr.h" +#define RESOLVED 0 +#define PUNTED 1 +#define THREE_STAGED 2 +void *RERERE_RESOLVED = &RERERE_RESOLVED; + /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ static int rerere_enabled = -1; @@ -325,7 +330,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu */ ll_merge(&result, path, &mmfile[0], NULL, &mmfile[1], "ours", - &mmfile[2], "theirs", 0); + &mmfile[2], "theirs", NULL); for (i = 0; i < 3; i++) free(mmfile[i].ptr); @@ -345,21 +350,74 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu return hunk_no; } -static int find_conflict(struct string_list *conflict) +static int check_one_conflict(int i, int *type) { - int i; - if (read_cache() < 0) - return error("Could not read index"); - for (i = 0; i+1 < active_nr; i++) { + struct cache_entry *e = active_cache[i]; + + if (!ce_stage(e)) { + *type = RESOLVED; + return i + 1; + } + + *type = PUNTED; + if (ce_stage(e) == 1) { + if (active_nr <= ++i) + return i + 1; + } + + /* Only handle regular files with both stages #2 and #3 */ + if (i + 1 < active_nr) { struct cache_entry *e2 = active_cache[i]; - struct cache_entry *e3 = active_cache[i+1]; + struct cache_entry *e3 = active_cache[i + 1]; if (ce_stage(e2) == 2 && ce_stage(e3) == 3 && - ce_same_name(e2, e3) && + ce_same_name(e, e3) && S_ISREG(e2->ce_mode) && - S_ISREG(e3->ce_mode)) { - string_list_insert(conflict, (const char *)e2->name); - i++; /* skip over both #2 and #3 */ + S_ISREG(e3->ce_mode)) + *type = THREE_STAGED; + } + + /* Skip the entries with the same name */ + while (i < active_nr && ce_same_name(e, active_cache[i])) + i++; + return i; +} + +static int find_conflict(struct string_list *conflict) +{ + int i; + if (read_cache() < 0) + return error("Could not read index"); + + for (i = 0; i < active_nr;) { + int conflict_type; + struct cache_entry *e = active_cache[i]; + i = check_one_conflict(i, &conflict_type); + if (conflict_type == THREE_STAGED) + string_list_insert(conflict, (const char *)e->name); + } + return 0; +} + +int rerere_remaining(struct string_list *merge_rr) +{ + int i; + if (read_cache() < 0) + return error("Could not read index"); + + for (i = 0; i < active_nr;) { + int conflict_type; + struct cache_entry *e = active_cache[i]; + i = check_one_conflict(i, &conflict_type); + if (conflict_type == PUNTED) + string_list_insert(merge_rr, (const char *)e->name); + else if (conflict_type == RESOLVED) { + struct string_list_item *it; + it = string_list_lookup(merge_rr, (const char *)e->name); + if (it != NULL) { + free(it->util); + it->util = RERERE_RESOLVED; + } } } return 0; @@ -380,7 +438,7 @@ static int merge(const char *name, const char *path) ret = 1; goto out; } - ret = ll_merge(&result, path, &base, NULL, &cur, "", &other, "", 0); + ret = ll_merge(&result, path, &base, NULL, &cur, "", &other, "", NULL); if (!ret) { FILE *f; @@ -532,8 +590,7 @@ static int is_rerere_enabled(void) if (rerere_enabled < 0) return rr_cache_exists; - if (!rr_cache_exists && - (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache))) + if (!rr_cache_exists && mkdir_in_gitdir(rr_cache)) die("Could not create directory %s", rr_cache); return 1; } |