/* * Remove the recorded resolution for a given conflict ID */ static void unlink_rr_item(struct rerere_id *id) { unlink_or_warn(rerere_path(id, "thisimage")); remove_variant(id); id->collection->status[id->variant] = 0; }
static void remove_variant(struct rerere_id *id) { unlink_or_warn(rerere_path(id, "postimage")); unlink_or_warn(rerere_path(id, "preimage")); id->collection->status[id->variant] = 0; }
static timestamp_t rerere_last_used_at(struct rerere_id *id) { struct stat st; return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; }
static int rerere_forget_one_path(struct index_state *istate, const char *path, struct string_list *rr) { const char *filename; struct rerere_id *id; unsigned char hash[GIT_MAX_RAWSZ]; int ret; struct string_list_item *item; /* * Recreate the original conflict from the stages in the * index and compute the conflict ID */ ret = handle_cache(istate, path, hash, NULL); if (ret < 1) return error(_("could not parse conflict hunks in '%s'"), path); /* Nuke the recorded resolution for the conflict */ id = new_rerere_id(hash); for (id->variant = 0; id->variant < id->collection->status_nr; id->variant++) { mmfile_t cur = { NULL, 0 }; mmbuffer_t result = {NULL, 0}; int cleanly_resolved; if (!has_rerere_resolution(id)) continue; handle_cache(istate, path, hash, rerere_path(id, "thisimage")); if (read_mmfile(&cur, rerere_path(id, "thisimage"))) { free(cur.ptr); error(_("failed to update conflicted state in '%s'"), path); goto fail_exit; } cleanly_resolved = !try_merge(istate, id, path, &cur, &result); free(result.ptr); free(cur.ptr); if (cleanly_resolved) break; } if (id->collection->status_nr <= id->variant) { error(_("no remembered resolution for '%s'"), path); goto fail_exit; } filename = rerere_path(id, "postimage"); if (unlink(filename)) { if (errno == ENOENT) error(_("no remembered resolution for '%s'"), path); else error_errno(_("cannot unlink '%s'"), filename); goto fail_exit; } /* * Update the preimage so that the user can resolve the * conflict in the working tree, run us again to record * the postimage. */ handle_cache(istate, path, hash, rerere_path(id, "preimage")); fprintf_ln(stderr, _("Updated preimage for '%s'"), path); /* * And remember that we can record resolution for this * conflict when the user is done. */ item = string_list_insert(rr, path); free_rerere_id(item); item->util = id; fprintf(stderr, _("Forgot resolution for '%s'\n"), path); return 0; fail_exit: free(id); return -1; }
static int do_plain_rerere(struct string_list *rr, int fd) { struct string_list conflict = STRING_LIST_INIT_DUP; struct string_list update = STRING_LIST_INIT_DUP; 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++) { const char *path = conflict.items[i].string; if (!string_list_has_string(rr, path)) { unsigned char sha1[20]; char *hex; int ret; ret = handle_file(path, sha1, NULL); if (ret < 1) continue; hex = xstrdup(sha1_to_hex(sha1)); string_list_insert(rr, path)->util = hex; if (mkdir(git_path("rr-cache/%s", hex), 0755)) continue; handle_file(path, NULL, rerere_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; const char *path = rr->items[i].string; const char *name = (const char *)rr->items[i].util; if (has_rerere_resolution(name)) { if (!merge(name, path)) { if (rerere_autoupdate) string_list_insert(&update, path); fprintf(stderr, "%s '%s' using previous resolution.\n", rerere_autoupdate ? "Staged" : "Resolved", path); 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(rerere_path(name, "postimage"), path, 0666); mark_resolved: rr->items[i].util = NULL; } if (update.nr) update_paths(&update); return write_rr(rr, fd); }
int has_rerere_resolution(const char *hex) { struct stat st; return !stat(rerere_path(hex, "postimage"), &st); }
static time_t rerere_last_used_at(const char *name) { struct stat st; return stat(rerere_path(name, "postimage"), &st) ? (time_t) 0 : st.st_mtime; }