Coverage Report

Created: 2026-11-12 06:03

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