git
/
rerere.c
1273 строки · 32.5 Кб
1#define USE_THE_REPOSITORY_VARIABLE2
3#include "git-compat-util.h"4#include "abspath.h"5#include "config.h"6#include "copy.h"7#include "gettext.h"8#include "hex.h"9#include "lockfile.h"10#include "string-list.h"11#include "read-cache-ll.h"12#include "rerere.h"13#include "xdiff-interface.h"14#include "dir.h"15#include "resolve-undo.h"16#include "merge-ll.h"17#include "path.h"18#include "pathspec.h"19#include "object-file.h"20#include "object-store-ll.h"21#include "strmap.h"22
23#define RESOLVED 024#define PUNTED 125#define THREE_STAGED 226void *RERERE_RESOLVED = &RERERE_RESOLVED;27
28/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
29static int rerere_enabled = -1;30
31/* automatically update cleanly resolved paths to the index */
32static int rerere_autoupdate;33
34#define RR_HAS_POSTIMAGE 135#define RR_HAS_PREIMAGE 236struct rerere_dir {37int status_alloc, status_nr;38unsigned char *status;39char name[FLEX_ARRAY];40};41
42static struct strmap rerere_dirs = STRMAP_INIT;43
44static void free_rerere_dirs(void)45{
46struct hashmap_iter iter;47struct strmap_entry *ent;48
49strmap_for_each_entry(&rerere_dirs, &iter, ent) {50struct rerere_dir *rr_dir = ent->value;51free(rr_dir->status);52free(rr_dir);53}54strmap_clear(&rerere_dirs, 0);55}
56
57static void free_rerere_id(struct string_list_item *item)58{
59free(item->util);60}
61
62static const char *rerere_id_hex(const struct rerere_id *id)63{
64return id->collection->name;65}
66
67static void fit_variant(struct rerere_dir *rr_dir, int variant)68{
69variant++;70ALLOC_GROW(rr_dir->status, variant, rr_dir->status_alloc);71if (rr_dir->status_nr < variant) {72memset(rr_dir->status + rr_dir->status_nr,73'\0', variant - rr_dir->status_nr);74rr_dir->status_nr = variant;75}76}
77
78static void assign_variant(struct rerere_id *id)79{
80int variant;81struct rerere_dir *rr_dir = id->collection;82
83variant = id->variant;84if (variant < 0) {85for (variant = 0; variant < rr_dir->status_nr; variant++)86if (!rr_dir->status[variant])87break;88}89fit_variant(rr_dir, variant);90id->variant = variant;91}
92
93const char *rerere_path(const struct rerere_id *id, const char *file)94{
95if (!file)96return git_path("rr-cache/%s", rerere_id_hex(id));97
98if (id->variant <= 0)99return git_path("rr-cache/%s/%s", rerere_id_hex(id), file);100
101return git_path("rr-cache/%s/%s.%d",102rerere_id_hex(id), file, id->variant);103}
104
105static int is_rr_file(const char *name, const char *filename, int *variant)106{
107const char *suffix;108char *ep;109
110if (!strcmp(name, filename)) {111*variant = 0;112return 1;113}114if (!skip_prefix(name, filename, &suffix) || *suffix != '.')115return 0;116
117errno = 0;118*variant = strtol(suffix + 1, &ep, 10);119if (errno || *ep)120return 0;121return 1;122}
123
124static void scan_rerere_dir(struct rerere_dir *rr_dir)125{
126struct dirent *de;127DIR *dir = opendir(git_path("rr-cache/%s", rr_dir->name));128
129if (!dir)130return;131while ((de = readdir(dir)) != NULL) {132int variant;133
134if (is_rr_file(de->d_name, "postimage", &variant)) {135fit_variant(rr_dir, variant);136rr_dir->status[variant] |= RR_HAS_POSTIMAGE;137} else if (is_rr_file(de->d_name, "preimage", &variant)) {138fit_variant(rr_dir, variant);139rr_dir->status[variant] |= RR_HAS_PREIMAGE;140}141}142closedir(dir);143}
144
145static struct rerere_dir *find_rerere_dir(const char *hex)146{
147struct rerere_dir *rr_dir;148
149rr_dir = strmap_get(&rerere_dirs, hex);150if (!rr_dir) {151FLEX_ALLOC_STR(rr_dir, name, hex);152rr_dir->status = NULL;153rr_dir->status_nr = 0;154rr_dir->status_alloc = 0;155strmap_put(&rerere_dirs, hex, rr_dir);156
157scan_rerere_dir(rr_dir);158}159return rr_dir;160}
161
162static int has_rerere_resolution(const struct rerere_id *id)163{
164const int both = RR_HAS_POSTIMAGE|RR_HAS_PREIMAGE;165int variant = id->variant;166
167if (variant < 0)168return 0;169return ((id->collection->status[variant] & both) == both);170}
171
172static struct rerere_id *new_rerere_id_hex(char *hex)173{
174struct rerere_id *id = xmalloc(sizeof(*id));175id->collection = find_rerere_dir(hex);176id->variant = -1; /* not known yet */177return id;178}
179
180static struct rerere_id *new_rerere_id(unsigned char *hash)181{
182return new_rerere_id_hex(hash_to_hex(hash));183}
184
185/*
186* $GIT_DIR/MERGE_RR file is a collection of records, each of which is
187* "conflict ID", a HT and pathname, terminated with a NUL, and is
188* used to keep track of the set of paths that "rerere" may need to
189* work on (i.e. what is left by the previous invocation of "git
190* rerere" during the current conflict resolution session).
191*/
192static void read_rr(struct repository *r, struct string_list *rr)193{
194struct strbuf buf = STRBUF_INIT;195FILE *in = fopen_or_warn(git_path_merge_rr(r), "r");196
197if (!in)198return;199while (!strbuf_getwholeline(&buf, in, '\0')) {200char *path;201unsigned char hash[GIT_MAX_RAWSZ];202struct rerere_id *id;203int variant;204const unsigned hexsz = the_hash_algo->hexsz;205
206/* There has to be the hash, tab, path and then NUL */207if (buf.len < hexsz + 2 || get_hash_hex(buf.buf, hash))208die(_("corrupt MERGE_RR"));209
210if (buf.buf[hexsz] != '.') {211variant = 0;212path = buf.buf + hexsz;213} else {214errno = 0;215variant = strtol(buf.buf + hexsz + 1, &path, 10);216if (errno)217die(_("corrupt MERGE_RR"));218}219if (*(path++) != '\t')220die(_("corrupt MERGE_RR"));221buf.buf[hexsz] = '\0';222id = new_rerere_id_hex(buf.buf);223id->variant = variant;224/*225* make sure id->collection->status has enough space
226* for the variant we are interested in
227*/
228fit_variant(id->collection, variant);229string_list_insert(rr, path)->util = id;230}231strbuf_release(&buf);232fclose(in);233}
234
235static struct lock_file write_lock;236
237static int write_rr(struct string_list *rr, int out_fd)238{
239int i;240for (i = 0; i < rr->nr; i++) {241struct strbuf buf = STRBUF_INIT;242struct rerere_id *id;243
244assert(rr->items[i].util != RERERE_RESOLVED);245
246id = rr->items[i].util;247if (!id)248continue;249assert(id->variant >= 0);250if (0 < id->variant)251strbuf_addf(&buf, "%s.%d\t%s%c",252rerere_id_hex(id), id->variant,253rr->items[i].string, 0);254else255strbuf_addf(&buf, "%s\t%s%c",256rerere_id_hex(id),257rr->items[i].string, 0);258
259if (write_in_full(out_fd, buf.buf, buf.len) < 0)260die(_("unable to write rerere record"));261
262strbuf_release(&buf);263}264if (commit_lock_file(&write_lock) != 0)265die(_("unable to write rerere record"));266return 0;267}
268
269/*
270* "rerere" interacts with conflicted file contents using this I/O
271* abstraction. It reads a conflicted contents from one place via
272* "getline()" method, and optionally can write it out after
273* normalizing the conflicted hunks to the "output". Subclasses of
274* rerere_io embed this structure at the beginning of their own
275* rerere_io object.
276*/
277struct rerere_io {278int (*getline)(struct strbuf *, struct rerere_io *);279FILE *output;280int wrerror;281/* some more stuff */282};283
284static void ferr_write(const void *p, size_t count, FILE *fp, int *err)285{
286if (!count || *err)287return;288if (fwrite(p, count, 1, fp) != 1)289*err = errno;290}
291
292static inline void ferr_puts(const char *s, FILE *fp, int *err)293{
294ferr_write(s, strlen(s), fp, err);295}
296
297static void rerere_io_putstr(const char *str, struct rerere_io *io)298{
299if (io->output)300ferr_puts(str, io->output, &io->wrerror);301}
302
303static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)304{
305if (io->output)306ferr_write(mem, sz, io->output, &io->wrerror);307}
308
309/*
310* Subclass of rerere_io that reads from an on-disk file
311*/
312struct rerere_io_file {313struct rerere_io io;314FILE *input;315};316
317/*
318* ... and its getline() method implementation
319*/
320static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_)321{
322struct rerere_io_file *io = (struct rerere_io_file *)io_;323return strbuf_getwholeline(sb, io->input, '\n');324}
325
326/*
327* Require the exact number of conflict marker letters, no more, no
328* less, followed by SP or any whitespace
329* (including LF).
330*/
331static int is_cmarker(char *buf, int marker_char, int marker_size)332{
333int want_sp;334
335/*336* The beginning of our version and the end of their version
337* always are labeled like "<<<<< ours" or ">>>>> theirs",
338* hence we set want_sp for them. Note that the version from
339* the common ancestor in diff3-style output is not always
340* labelled (e.g. "||||| common" is often seen but "|||||"
341* alone is also valid), so we do not set want_sp.
342*/
343want_sp = (marker_char == '<') || (marker_char == '>');344
345while (marker_size--)346if (*buf++ != marker_char)347return 0;348if (want_sp && *buf != ' ')349return 0;350return isspace(*buf);351}
352
353static void rerere_strbuf_putconflict(struct strbuf *buf, int ch, size_t size)354{
355strbuf_addchars(buf, ch, size);356strbuf_addch(buf, '\n');357}
358
359static int handle_conflict(struct strbuf *out, struct rerere_io *io,360int marker_size, git_hash_ctx *ctx)361{
362enum {363RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL364} hunk = RR_SIDE_1;365struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;366struct strbuf buf = STRBUF_INIT, conflict = STRBUF_INIT;367int has_conflicts = -1;368
369while (!io->getline(&buf, io)) {370if (is_cmarker(buf.buf, '<', marker_size)) {371if (handle_conflict(&conflict, io, marker_size, NULL) < 0)372break;373if (hunk == RR_SIDE_1)374strbuf_addbuf(&one, &conflict);375else376strbuf_addbuf(&two, &conflict);377strbuf_release(&conflict);378} else if (is_cmarker(buf.buf, '|', marker_size)) {379if (hunk != RR_SIDE_1)380break;381hunk = RR_ORIGINAL;382} else if (is_cmarker(buf.buf, '=', marker_size)) {383if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)384break;385hunk = RR_SIDE_2;386} else if (is_cmarker(buf.buf, '>', marker_size)) {387if (hunk != RR_SIDE_2)388break;389if (strbuf_cmp(&one, &two) > 0)390strbuf_swap(&one, &two);391has_conflicts = 1;392rerere_strbuf_putconflict(out, '<', marker_size);393strbuf_addbuf(out, &one);394rerere_strbuf_putconflict(out, '=', marker_size);395strbuf_addbuf(out, &two);396rerere_strbuf_putconflict(out, '>', marker_size);397if (ctx) {398the_hash_algo->update_fn(ctx, one.buf ?399one.buf : "",400one.len + 1);401the_hash_algo->update_fn(ctx, two.buf ?402two.buf : "",403two.len + 1);404}405break;406} else if (hunk == RR_SIDE_1)407strbuf_addbuf(&one, &buf);408else if (hunk == RR_ORIGINAL)409; /* discard */410else if (hunk == RR_SIDE_2)411strbuf_addbuf(&two, &buf);412}413strbuf_release(&one);414strbuf_release(&two);415strbuf_release(&buf);416
417return has_conflicts;418}
419
420/*
421* Read contents a file with conflicts, normalize the conflicts
422* by (1) discarding the common ancestor version in diff3-style,
423* (2) reordering our side and their side so that whichever sorts
424* alphabetically earlier comes before the other one, while
425* computing the "conflict ID", which is just an SHA-1 hash of
426* one side of the conflict, NUL, the other side of the conflict,
427* and NUL concatenated together.
428*
429* Return 1 if conflict hunks are found, 0 if there are no conflict
430* hunks and -1 if an error occurred.
431*/
432static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_size)433{
434git_hash_ctx ctx;435struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT;436int has_conflicts = 0;437if (hash)438the_hash_algo->init_fn(&ctx);439
440while (!io->getline(&buf, io)) {441if (is_cmarker(buf.buf, '<', marker_size)) {442has_conflicts = handle_conflict(&out, io, marker_size,443hash ? &ctx : NULL);444if (has_conflicts < 0)445break;446rerere_io_putmem(out.buf, out.len, io);447strbuf_reset(&out);448} else449rerere_io_putstr(buf.buf, io);450}451strbuf_release(&buf);452strbuf_release(&out);453
454if (hash)455the_hash_algo->final_fn(hash, &ctx);456
457return has_conflicts;458}
459
460/*
461* Scan the path for conflicts, do the "handle_path()" thing above, and
462* return the number of conflict hunks found.
463*/
464static int handle_file(struct index_state *istate,465const char *path, unsigned char *hash, const char *output)466{
467int has_conflicts = 0;468struct rerere_io_file io;469int marker_size = ll_merge_marker_size(istate, path);470
471memset(&io, 0, sizeof(io));472io.io.getline = rerere_file_getline;473io.input = fopen(path, "r");474io.io.wrerror = 0;475if (!io.input)476return error_errno(_("could not open '%s'"), path);477
478if (output) {479io.io.output = fopen(output, "w");480if (!io.io.output) {481error_errno(_("could not write '%s'"), output);482fclose(io.input);483return -1;484}485}486
487has_conflicts = handle_path(hash, (struct rerere_io *)&io, marker_size);488
489fclose(io.input);490if (io.io.wrerror)491error(_("there were errors while writing '%s' (%s)"),492path, strerror(io.io.wrerror));493if (io.io.output && fclose(io.io.output))494io.io.wrerror = error_errno(_("failed to flush '%s'"), path);495
496if (has_conflicts < 0) {497if (output)498unlink_or_warn(output);499return error(_("could not parse conflict hunks in '%s'"), path);500}501if (io.io.wrerror)502return -1;503return has_conflicts;504}
505
506/*
507* Look at a cache entry at "i" and see if it is not conflicting,
508* conflicting and we are willing to handle, or conflicting and
509* we are unable to handle, and return the determination in *type.
510* Return the cache index to be looked at next, by skipping the
511* stages we have already looked at in this invocation of this
512* function.
513*/
514static int check_one_conflict(struct index_state *istate, int i, int *type)515{
516const struct cache_entry *e = istate->cache[i];517
518if (!ce_stage(e)) {519*type = RESOLVED;520return i + 1;521}522
523*type = PUNTED;524while (i < istate->cache_nr && ce_stage(istate->cache[i]) == 1)525i++;526
527/* Only handle regular files with both stages #2 and #3 */528if (i + 1 < istate->cache_nr) {529const struct cache_entry *e2 = istate->cache[i];530const struct cache_entry *e3 = istate->cache[i + 1];531if (ce_stage(e2) == 2 &&532ce_stage(e3) == 3 &&533ce_same_name(e, e3) &&534S_ISREG(e2->ce_mode) &&535S_ISREG(e3->ce_mode))536*type = THREE_STAGED;537}538
539/* Skip the entries with the same name */540while (i < istate->cache_nr && ce_same_name(e, istate->cache[i]))541i++;542return i;543}
544
545/*
546* Scan the index and find paths that have conflicts that rerere can
547* handle, i.e. the ones that has both stages #2 and #3.
548*
549* NEEDSWORK: we do not record or replay a previous "resolve by
550* deletion" for a delete-modify conflict, as that is inherently risky
551* without knowing what modification is being discarded. The only
552* safe case, i.e. both side doing the deletion and modification that
553* are identical to the previous round, might want to be handled,
554* though.
555*/
556static int find_conflict(struct repository *r, struct string_list *conflict)557{
558int i;559
560if (repo_read_index(r) < 0)561return error(_("index file corrupt"));562
563for (i = 0; i < r->index->cache_nr;) {564int conflict_type;565const struct cache_entry *e = r->index->cache[i];566i = check_one_conflict(r->index, i, &conflict_type);567if (conflict_type == THREE_STAGED)568string_list_insert(conflict, (const char *)e->name);569}570return 0;571}
572
573/*
574* The merge_rr list is meant to hold outstanding conflicted paths
575* that rerere could handle. Abuse the list by adding other types of
576* entries to allow the caller to show "rerere remaining".
577*
578* - Conflicted paths that rerere does not handle are added
579* - Conflicted paths that have been resolved are marked as such
580* by storing RERERE_RESOLVED to .util field (where conflict ID
581* is expected to be stored).
582*
583* Do *not* write MERGE_RR file out after calling this function.
584*
585* NEEDSWORK: we may want to fix the caller that implements "rerere
586* remaining" to do this without abusing merge_rr.
587*/
588int rerere_remaining(struct repository *r, struct string_list *merge_rr)589{
590int i;591
592if (setup_rerere(r, merge_rr, RERERE_READONLY))593return 0;594if (repo_read_index(r) < 0)595return error(_("index file corrupt"));596
597for (i = 0; i < r->index->cache_nr;) {598int conflict_type;599const struct cache_entry *e = r->index->cache[i];600i = check_one_conflict(r->index, i, &conflict_type);601if (conflict_type == PUNTED)602string_list_insert(merge_rr, (const char *)e->name);603else if (conflict_type == RESOLVED) {604struct string_list_item *it;605it = string_list_lookup(merge_rr, (const char *)e->name);606if (it) {607free_rerere_id(it);608it->util = RERERE_RESOLVED;609}610}611}612return 0;613}
614
615/*
616* Try using the given conflict resolution "ID" to see
617* if that recorded conflict resolves cleanly what we
618* got in the "cur".
619*/
620static int try_merge(struct index_state *istate,621const struct rerere_id *id, const char *path,622mmfile_t *cur, mmbuffer_t *result)623{
624enum ll_merge_result ret;625mmfile_t base = {NULL, 0}, other = {NULL, 0};626
627if (read_mmfile(&base, rerere_path(id, "preimage")) ||628read_mmfile(&other, rerere_path(id, "postimage"))) {629ret = LL_MERGE_CONFLICT;630} else {631/*632* A three-way merge. Note that this honors user-customizable
633* low-level merge driver settings.
634*/
635ret = ll_merge(result, path, &base, NULL, cur, "", &other, "",636istate, NULL);637}638
639free(base.ptr);640free(other.ptr);641
642return ret;643}
644
645/*
646* Find the conflict identified by "id"; the change between its
647* "preimage" (i.e. a previous contents with conflict markers) and its
648* "postimage" (i.e. the corresponding contents with conflicts
649* resolved) may apply cleanly to the contents stored in "path", i.e.
650* the conflict this time around.
651*
652* Returns 0 for successful replay of recorded resolution, or non-zero
653* for failure.
654*/
655static int merge(struct index_state *istate, const struct rerere_id *id, const char *path)656{
657FILE *f;658int ret;659mmfile_t cur = {NULL, 0};660mmbuffer_t result = {NULL, 0};661
662/*663* Normalize the conflicts in path and write it out to
664* "thisimage" temporary file.
665*/
666if ((handle_file(istate, path, NULL, rerere_path(id, "thisimage")) < 0) ||667read_mmfile(&cur, rerere_path(id, "thisimage"))) {668ret = 1;669goto out;670}671
672ret = try_merge(istate, id, path, &cur, &result);673if (ret)674goto out;675
676/*677* A successful replay of recorded resolution.
678* Mark that "postimage" was used to help gc.
679*/
680if (utime(rerere_path(id, "postimage"), NULL) < 0)681warning_errno(_("failed utime() on '%s'"),682rerere_path(id, "postimage"));683
684/* Update "path" with the resolution */685f = fopen(path, "w");686if (!f)687return error_errno(_("could not open '%s'"), path);688if (fwrite(result.ptr, result.size, 1, f) != 1)689error_errno(_("could not write '%s'"), path);690if (fclose(f))691return error_errno(_("writing '%s' failed"), path);692
693out:694free(cur.ptr);695free(result.ptr);696
697return ret;698}
699
700static void update_paths(struct repository *r, struct string_list *update)701{
702struct lock_file index_lock = LOCK_INIT;703int i;704
705repo_hold_locked_index(r, &index_lock, LOCK_DIE_ON_ERROR);706
707for (i = 0; i < update->nr; i++) {708struct string_list_item *item = &update->items[i];709if (add_file_to_index(r->index, item->string, 0))710exit(128);711fprintf_ln(stderr, _("Staged '%s' using previous resolution."),712item->string);713}714
715if (write_locked_index(r->index, &index_lock,716COMMIT_LOCK | SKIP_IF_UNCHANGED))717die(_("unable to write new index file"));718}
719
720static void remove_variant(struct rerere_id *id)721{
722unlink_or_warn(rerere_path(id, "postimage"));723unlink_or_warn(rerere_path(id, "preimage"));724id->collection->status[id->variant] = 0;725}
726
727/*
728* The path indicated by rr_item may still have conflict for which we
729* have a recorded resolution, in which case replay it and optionally
730* update it. Or it may have been resolved by the user and we may
731* only have the preimage for that conflict, in which case the result
732* needs to be recorded as a resolution in a postimage file.
733*/
734static void do_rerere_one_path(struct index_state *istate,735struct string_list_item *rr_item,736struct string_list *update)737{
738const char *path = rr_item->string;739struct rerere_id *id = rr_item->util;740struct rerere_dir *rr_dir = id->collection;741int variant;742
743variant = id->variant;744
745/* Has the user resolved it already? */746if (variant >= 0) {747if (!handle_file(istate, path, NULL, NULL)) {748copy_file(rerere_path(id, "postimage"), path, 0666);749id->collection->status[variant] |= RR_HAS_POSTIMAGE;750fprintf_ln(stderr, _("Recorded resolution for '%s'."), path);751free_rerere_id(rr_item);752rr_item->util = NULL;753return;754}755/*756* There may be other variants that can cleanly
757* replay. Try them and update the variant number for
758* this one.
759*/
760}761
762/* Does any existing resolution apply cleanly? */763for (variant = 0; variant < rr_dir->status_nr; variant++) {764const int both = RR_HAS_PREIMAGE | RR_HAS_POSTIMAGE;765struct rerere_id vid = *id;766
767if ((rr_dir->status[variant] & both) != both)768continue;769
770vid.variant = variant;771if (merge(istate, &vid, path))772continue; /* failed to replay */773
774/*775* If there already is a different variant that applies
776* cleanly, there is no point maintaining our own variant.
777*/
778if (0 <= id->variant && id->variant != variant)779remove_variant(id);780
781if (rerere_autoupdate)782string_list_insert(update, path);783else784fprintf_ln(stderr,785_("Resolved '%s' using previous resolution."),786path);787free_rerere_id(rr_item);788rr_item->util = NULL;789return;790}791
792/* None of the existing one applies; we need a new variant */793assign_variant(id);794
795variant = id->variant;796handle_file(istate, path, NULL, rerere_path(id, "preimage"));797if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {798const char *path = rerere_path(id, "postimage");799if (unlink(path))800die_errno(_("cannot unlink stray '%s'"), path);801id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;802}803id->collection->status[variant] |= RR_HAS_PREIMAGE;804fprintf_ln(stderr, _("Recorded preimage for '%s'"), path);805}
806
807static int do_plain_rerere(struct repository *r,808struct string_list *rr, int fd)809{
810struct string_list conflict = STRING_LIST_INIT_DUP;811struct string_list update = STRING_LIST_INIT_DUP;812int i;813
814find_conflict(r, &conflict);815
816/*817* MERGE_RR records paths with conflicts immediately after
818* merge failed. Some of the conflicted paths might have been
819* hand resolved in the working tree since then, but the
820* initial run would catch all and register their preimages.
821*/
822for (i = 0; i < conflict.nr; i++) {823struct rerere_id *id;824unsigned char hash[GIT_MAX_RAWSZ];825const char *path = conflict.items[i].string;826int ret;827
828/*829* Ask handle_file() to scan and assign a
830* conflict ID. No need to write anything out
831* yet.
832*/
833ret = handle_file(r->index, path, hash, NULL);834if (ret != 0 && string_list_has_string(rr, path)) {835remove_variant(string_list_lookup(rr, path)->util);836string_list_remove(rr, path, 1);837}838if (ret < 1)839continue;840
841id = new_rerere_id(hash);842string_list_insert(rr, path)->util = id;843
844/* Ensure that the directory exists. */845mkdir_in_gitdir(rerere_path(id, NULL));846}847
848for (i = 0; i < rr->nr; i++)849do_rerere_one_path(r->index, &rr->items[i], &update);850
851if (update.nr)852update_paths(r, &update);853
854string_list_clear(&conflict, 0);855string_list_clear(&update, 0);856return write_rr(rr, fd);857}
858
859static void git_rerere_config(void)860{
861git_config_get_bool("rerere.enabled", &rerere_enabled);862git_config_get_bool("rerere.autoupdate", &rerere_autoupdate);863git_config(git_default_config, NULL);864}
865
866static GIT_PATH_FUNC(git_path_rr_cache, "rr-cache")867
868static int is_rerere_enabled(void)869{
870int rr_cache_exists;871
872if (!rerere_enabled)873return 0;874
875rr_cache_exists = is_directory(git_path_rr_cache());876if (rerere_enabled < 0)877return rr_cache_exists;878
879if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache()))880die(_("could not create directory '%s'"), git_path_rr_cache());881return 1;882}
883
884int setup_rerere(struct repository *r, struct string_list *merge_rr, int flags)885{
886int fd;887
888git_rerere_config();889if (!is_rerere_enabled())890return -1;891
892if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))893rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);894if (flags & RERERE_READONLY)895fd = 0;896else897fd = hold_lock_file_for_update(&write_lock,898git_path_merge_rr(r),899LOCK_DIE_ON_ERROR);900read_rr(r, merge_rr);901return fd;902}
903
904/*
905* The main entry point that is called internally from codepaths that
906* perform mergy operations, possibly leaving conflicted index entries
907* and working tree files.
908*/
909int repo_rerere(struct repository *r, int flags)910{
911struct string_list merge_rr = STRING_LIST_INIT_DUP;912int fd, status;913
914fd = setup_rerere(r, &merge_rr, flags);915if (fd < 0)916return 0;917status = do_plain_rerere(r, &merge_rr, fd);918free_rerere_dirs();919string_list_clear(&merge_rr, 1);920return status;921}
922
923/*
924* Subclass of rerere_io that reads from an in-core buffer that is a
925* strbuf
926*/
927struct rerere_io_mem {928struct rerere_io io;929struct strbuf input;930};931
932/*
933* ... and its getline() method implementation
934*/
935static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)936{
937struct rerere_io_mem *io = (struct rerere_io_mem *)io_;938char *ep;939size_t len;940
941strbuf_release(sb);942if (!io->input.len)943return -1;944ep = memchr(io->input.buf, '\n', io->input.len);945if (!ep)946ep = io->input.buf + io->input.len;947else if (*ep == '\n')948ep++;949len = ep - io->input.buf;950strbuf_add(sb, io->input.buf, len);951strbuf_remove(&io->input, 0, len);952return 0;953}
954
955static int handle_cache(struct index_state *istate,956const char *path, unsigned char *hash, const char *output)957{
958mmfile_t mmfile[3] = {{NULL}};959mmbuffer_t result = {NULL, 0};960const struct cache_entry *ce;961int pos, len, i, has_conflicts;962struct rerere_io_mem io;963int marker_size = ll_merge_marker_size(istate, path);964
965/*966* Reproduce the conflicted merge in-core
967*/
968len = strlen(path);969pos = index_name_pos(istate, path, len);970if (0 <= pos)971return -1;972pos = -pos - 1;973
974while (pos < istate->cache_nr) {975enum object_type type;976unsigned long size;977
978ce = istate->cache[pos++];979if (ce_namelen(ce) != len || memcmp(ce->name, path, len))980break;981i = ce_stage(ce) - 1;982if (!mmfile[i].ptr) {983mmfile[i].ptr = repo_read_object_file(the_repository,984&ce->oid, &type,985&size);986if (!mmfile[i].ptr)987die(_("unable to read %s"),988oid_to_hex(&ce->oid));989mmfile[i].size = size;990}991}992for (i = 0; i < 3; i++)993if (!mmfile[i].ptr && !mmfile[i].size)994mmfile[i].ptr = xstrdup("");995
996/*997* NEEDSWORK: handle conflicts from merges with
998* merge.renormalize set, too?
999*/
1000ll_merge(&result, path, &mmfile[0], NULL,1001&mmfile[1], "ours",1002&mmfile[2], "theirs",1003istate, NULL);1004for (i = 0; i < 3; i++)1005free(mmfile[i].ptr);1006
1007memset(&io, 0, sizeof(io));1008io.io.getline = rerere_mem_getline;1009if (output)1010io.io.output = fopen(output, "w");1011else1012io.io.output = NULL;1013strbuf_init(&io.input, 0);1014strbuf_attach(&io.input, result.ptr, result.size, result.size);1015
1016/*1017* Grab the conflict ID and optionally write the original
1018* contents with conflict markers out.
1019*/
1020has_conflicts = handle_path(hash, (struct rerere_io *)&io, marker_size);1021strbuf_release(&io.input);1022if (io.io.output)1023fclose(io.io.output);1024return has_conflicts;1025}
1026
1027static int rerere_forget_one_path(struct index_state *istate,1028const char *path,1029struct string_list *rr)1030{
1031const char *filename;1032struct rerere_id *id;1033unsigned char hash[GIT_MAX_RAWSZ];1034int ret;1035struct string_list_item *item;1036
1037/*1038* Recreate the original conflict from the stages in the
1039* index and compute the conflict ID
1040*/
1041ret = handle_cache(istate, path, hash, NULL);1042if (ret < 1)1043return error(_("could not parse conflict hunks in '%s'"), path);1044
1045/* Nuke the recorded resolution for the conflict */1046id = new_rerere_id(hash);1047
1048for (id->variant = 0;1049id->variant < id->collection->status_nr;1050id->variant++) {1051mmfile_t cur = { NULL, 0 };1052mmbuffer_t result = {NULL, 0};1053int cleanly_resolved;1054
1055if (!has_rerere_resolution(id))1056continue;1057
1058handle_cache(istate, path, hash, rerere_path(id, "thisimage"));1059if (read_mmfile(&cur, rerere_path(id, "thisimage"))) {1060free(cur.ptr);1061error(_("failed to update conflicted state in '%s'"), path);1062goto fail_exit;1063}1064cleanly_resolved = !try_merge(istate, id, path, &cur, &result);1065free(result.ptr);1066free(cur.ptr);1067if (cleanly_resolved)1068break;1069}1070
1071if (id->collection->status_nr <= id->variant) {1072error(_("no remembered resolution for '%s'"), path);1073goto fail_exit;1074}1075
1076filename = rerere_path(id, "postimage");1077if (unlink(filename)) {1078if (errno == ENOENT)1079error(_("no remembered resolution for '%s'"), path);1080else1081error_errno(_("cannot unlink '%s'"), filename);1082goto fail_exit;1083}1084
1085/*1086* Update the preimage so that the user can resolve the
1087* conflict in the working tree, run us again to record
1088* the postimage.
1089*/
1090handle_cache(istate, path, hash, rerere_path(id, "preimage"));1091fprintf_ln(stderr, _("Updated preimage for '%s'"), path);1092
1093/*1094* And remember that we can record resolution for this
1095* conflict when the user is done.
1096*/
1097item = string_list_insert(rr, path);1098free_rerere_id(item);1099item->util = id;1100fprintf(stderr, _("Forgot resolution for '%s'\n"), path);1101return 0;1102
1103fail_exit:1104free(id);1105return -1;1106}
1107
1108int rerere_forget(struct repository *r, struct pathspec *pathspec)1109{
1110int i, fd, ret;1111struct string_list conflict = STRING_LIST_INIT_DUP;1112struct string_list merge_rr = STRING_LIST_INIT_DUP;1113
1114if (repo_read_index(r) < 0)1115return error(_("index file corrupt"));1116
1117fd = setup_rerere(r, &merge_rr, RERERE_NOAUTOUPDATE);1118if (fd < 0)1119return 0;1120
1121/*1122* The paths may have been resolved (incorrectly);
1123* recover the original conflicted state and then
1124* find the conflicted paths.
1125*/
1126unmerge_index(r->index, pathspec, 0);1127find_conflict(r, &conflict);1128for (i = 0; i < conflict.nr; i++) {1129struct string_list_item *it = &conflict.items[i];1130if (!match_pathspec(r->index, pathspec, it->string,1131strlen(it->string), 0, NULL, 0))1132continue;1133rerere_forget_one_path(r->index, it->string, &merge_rr);1134}1135
1136ret = write_rr(&merge_rr, fd);1137
1138string_list_clear(&conflict, 0);1139string_list_clear(&merge_rr, 1);1140return ret;1141}
1142
1143/*
1144* Garbage collection support
1145*/
1146
1147static timestamp_t rerere_created_at(struct rerere_id *id)1148{
1149struct stat st;1150
1151return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime;1152}
1153
1154static timestamp_t rerere_last_used_at(struct rerere_id *id)1155{
1156struct stat st;1157
1158return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime;1159}
1160
1161/*
1162* Remove the recorded resolution for a given conflict ID
1163*/
1164static void unlink_rr_item(struct rerere_id *id)1165{
1166unlink_or_warn(rerere_path(id, "thisimage"));1167remove_variant(id);1168id->collection->status[id->variant] = 0;1169}
1170
1171static void prune_one(struct rerere_id *id,1172timestamp_t cutoff_resolve, timestamp_t cutoff_noresolve)1173{
1174timestamp_t then;1175timestamp_t cutoff;1176
1177then = rerere_last_used_at(id);1178if (then)1179cutoff = cutoff_resolve;1180else {1181then = rerere_created_at(id);1182if (!then)1183return;1184cutoff = cutoff_noresolve;1185}1186if (then < cutoff)1187unlink_rr_item(id);1188}
1189
1190/* Does the basename in "path" look plausibly like an rr-cache entry? */
1191static int is_rr_cache_dirname(const char *path)1192{
1193struct object_id oid;1194const char *end;1195return !parse_oid_hex(path, &oid, &end) && !*end;1196}
1197
1198void rerere_gc(struct repository *r, struct string_list *rr)1199{
1200struct string_list to_remove = STRING_LIST_INIT_DUP;1201DIR *dir;1202struct dirent *e;1203int i;1204timestamp_t now = time(NULL);1205timestamp_t cutoff_noresolve = now - 15 * 86400;1206timestamp_t cutoff_resolve = now - 60 * 86400;1207
1208if (setup_rerere(r, rr, 0) < 0)1209return;1210
1211repo_config_get_expiry_in_days(the_repository, "gc.rerereresolved",1212&cutoff_resolve, now);1213repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved",1214&cutoff_noresolve, now);1215git_config(git_default_config, NULL);1216dir = opendir(git_path("rr-cache"));1217if (!dir)1218die_errno(_("unable to open rr-cache directory"));1219/* Collect stale conflict IDs ... */1220while ((e = readdir_skip_dot_and_dotdot(dir))) {1221struct rerere_dir *rr_dir;1222struct rerere_id id;1223int now_empty;1224
1225if (!is_rr_cache_dirname(e->d_name))1226continue; /* or should we remove e->d_name? */1227
1228rr_dir = find_rerere_dir(e->d_name);1229
1230now_empty = 1;1231for (id.variant = 0, id.collection = rr_dir;1232id.variant < id.collection->status_nr;1233id.variant++) {1234prune_one(&id, cutoff_resolve, cutoff_noresolve);1235if (id.collection->status[id.variant])1236now_empty = 0;1237}1238if (now_empty)1239string_list_append(&to_remove, e->d_name);1240}1241closedir(dir);1242
1243/* ... and then remove the empty directories */1244for (i = 0; i < to_remove.nr; i++)1245rmdir(git_path("rr-cache/%s", to_remove.items[i].string));1246string_list_clear(&to_remove, 0);1247rollback_lock_file(&write_lock);1248}
1249
1250/*
1251* During a conflict resolution, after "rerere" recorded the
1252* preimages, abandon them if the user did not resolve them or
1253* record their resolutions. And drop $GIT_DIR/MERGE_RR.
1254*
1255* NEEDSWORK: shouldn't we be calling this from "reset --hard"?
1256*/
1257void rerere_clear(struct repository *r, struct string_list *merge_rr)1258{
1259int i;1260
1261if (setup_rerere(r, merge_rr, 0) < 0)1262return;1263
1264for (i = 0; i < merge_rr->nr; i++) {1265struct rerere_id *id = merge_rr->items[i].util;1266if (!has_rerere_resolution(id)) {1267unlink_rr_item(id);1268rmdir(rerere_path(id, NULL));1269}1270}1271unlink_or_warn(git_path_merge_rr(r));1272rollback_lock_file(&write_lock);1273}
1274