/* * The merge_rr list is meant to hold outstanding conflicted paths * that rerere could handle. Abuse the list by adding other types of * entries to allow the caller to show "rerere remaining". * * - Conflicted paths that rerere does not handle are added * - Conflicted paths that have been resolved are marked as such * by storing RERERE_RESOLVED to .util field (where conflict ID * is expected to be stored). * * Do *not* write MERGE_RR file out after calling this function. * * NEEDSWORK: we may want to fix the caller that implements "rerere * remaining" to do this without abusing merge_rr. */ int rerere_remaining(struct string_list *merge_rr) { int i; if (setup_rerere(merge_rr, RERERE_READONLY)) return 0; if (read_cache() < 0) return error(_("index file corrupt")); for (i = 0; i < active_nr;) { int conflict_type; const 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_rerere_id(it); it->util = RERERE_RESOLVED; } } } return 0; }
/* * The path indicated by rr_item may still have conflict for which we * have a recorded resolution, in which case replay it and optionally * update it. Or it may have been resolved by the user and we may * only have the preimage for that conflict, in which case the result * needs to be recorded as a resolution in a postimage file. */ static void do_rerere_one_path(struct string_list_item *rr_item, struct string_list *update) { const char *path = rr_item->string; const struct rerere_id *id = rr_item->util; /* Is there a recorded resolution we could attempt to apply? */ if (has_rerere_resolution(id)) { if (merge(id, path)) return; /* failed to replay */ if (rerere_autoupdate) string_list_insert(update, path); else fprintf(stderr, "Resolved '%s' using previous resolution.\n", path); } else if (!handle_file(path, NULL, NULL)) { /* The user has resolved it. */ copy_file(rerere_path(id, "postimage"), path, 0666); fprintf(stderr, "Recorded resolution for '%s'.\n", path); } else { return; } free_rerere_id(rr_item); rr_item->util = NULL; }
static int rerere_forget_one_path(const char *path, struct string_list *rr) { const char *filename; struct rerere_id *id; unsigned char sha1[20]; 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(path, sha1, 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(sha1); filename = rerere_path(id, "postimage"); if (unlink(filename)) return (errno == ENOENT ? error("no remembered resolution for %s", path) : error("cannot unlink %s: %s", filename, strerror(errno))); /* * Update the preimage so that the user can resolve the * conflict in the working tree, run us again to record * the postimage. */ handle_cache(path, sha1, rerere_path(id, "preimage")); fprintf(stderr, "Updated preimage for '%s'\n", 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; }
/* * The path indicated by rr_item may still have conflict for which we * have a recorded resolution, in which case replay it and optionally * update it. Or it may have been resolved by the user and we may * only have the preimage for that conflict, in which case the result * needs to be recorded as a resolution in a postimage file. */ static void do_rerere_one_path(struct string_list_item *rr_item, struct string_list *update) { const char *path = rr_item->string; struct rerere_id *id = rr_item->util; struct rerere_dir *rr_dir = id->collection; int variant; variant = id->variant; /* Has the user resolved it already? */ if (variant >= 0) { if (!handle_file(path, NULL, NULL)) { copy_file(rerere_path(id, "postimage"), path, 0666); id->collection->status[variant] |= RR_HAS_POSTIMAGE; fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); free_rerere_id(rr_item); rr_item->util = NULL; return; } /* * There may be other variants that can cleanly * replay. Try them and update the variant number for * this one. */ } /* Does any existing resolution apply cleanly? */ for (variant = 0; variant < rr_dir->status_nr; variant++) { const int both = RR_HAS_PREIMAGE | RR_HAS_POSTIMAGE; struct rerere_id vid = *id; if ((rr_dir->status[variant] & both) != both) continue; vid.variant = variant; if (merge(&vid, path)) continue; /* failed to replay */ /* * If there already is a different variant that applies * cleanly, there is no point maintaining our own variant. */ if (0 <= id->variant && id->variant != variant) remove_variant(id); if (rerere_autoupdate) string_list_insert(update, path); else fprintf_ln(stderr, _("Resolved '%s' using previous resolution."), path); free_rerere_id(rr_item); rr_item->util = NULL; return; } /* None of the existing one applies; we need a new variant */ assign_variant(id); variant = id->variant; handle_file(path, NULL, rerere_path(id, "preimage")); if (id->collection->status[variant] & RR_HAS_POSTIMAGE) { const char *path = rerere_path(id, "postimage"); if (unlink(path)) die_errno(_("cannot unlink stray '%s'"), path); id->collection->status[variant] &= ~RR_HAS_POSTIMAGE; } id->collection->status[variant] |= RR_HAS_PREIMAGE; fprintf_ln(stderr, _("Recorded preimage for '%s'"), path); }
static int rerere_forget_one_path(const char *path, struct string_list *rr) { const char *filename; struct rerere_id *id; unsigned char sha1[20]; 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(path, sha1, 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(sha1); 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(path, sha1, 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(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(path, sha1, 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; }