Skip to content

Commit ac49f5c

Browse files
Martin von Zweigbergkgitster
Martin von Zweigbergk
authored andcommitted
rerere "remaining"
After "rerere" resolves conflicts by reusing old resolution, there would be three kinds of paths with conflict in the index: * paths that have been resolved in the working tree by rerere; * paths that need further work whose resolution could be recorded; * paths that need resolving that rerere won't help. When the user wants a list of paths that need hand-resolving, output from "rerere status" does not help, as it shows only the second category, but the paths in the third category still needs work (rerere only makes sense for regular files that have both our side and their side, and does not help other kinds of conflicts, e.g. "we modified, they deleted"). The new subcommand "rerere remaining" can be used to show both. As opposed to "rerere status", this subcommand also skips printing paths that have been added to the index, since these paths are already resolved and are no longer "remaining". Initial patch provided by Junio. Refactored and modified to skip resolved paths by Martin. Commit message mostly by Junio. Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Martin von Zweigbergk <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 685e9d9 commit ac49f5c

File tree

3 files changed

+88
-12
lines changed

3 files changed

+88
-12
lines changed

builtin/rerere.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "xdiff-interface.h"
99

1010
static const char * const rerere_usage[] = {
11-
"git rerere [clear | status | diff | gc]",
11+
"git rerere [clear | status | remaining | diff | gc]",
1212
NULL,
1313
};
1414

@@ -156,7 +156,17 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
156156
else if (!strcmp(argv[0], "status"))
157157
for (i = 0; i < merge_rr.nr; i++)
158158
printf("%s\n", merge_rr.items[i].string);
159-
else if (!strcmp(argv[0], "diff"))
159+
else if (!strcmp(argv[0], "remaining")) {
160+
rerere_remaining(&merge_rr);
161+
for (i = 0; i < merge_rr.nr; i++) {
162+
if (merge_rr.items[i].util != RERERE_RESOLVED)
163+
printf("%s\n", merge_rr.items[i].string);
164+
else
165+
/* prepare for later call to
166+
* string_list_clear() */
167+
merge_rr.items[i].util = NULL;
168+
}
169+
} else if (!strcmp(argv[0], "diff"))
160170
for (i = 0; i < merge_rr.nr; i++) {
161171
const char *path = merge_rr.items[i].string;
162172
const char *name = (const char *)merge_rr.items[i].util;

rerere.c

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
#include "ll-merge.h"
88
#include "attr.h"
99

10+
#define RESOLVED 0
11+
#define PUNTED 1
12+
#define THREE_STAGED 2
13+
void *RERERE_RESOLVED = &RERERE_RESOLVED;
14+
1015
/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
1116
static int rerere_enabled = -1;
1217

@@ -345,21 +350,74 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
345350
return hunk_no;
346351
}
347352

348-
static int find_conflict(struct string_list *conflict)
353+
static int check_one_conflict(int i, int *type)
349354
{
350-
int i;
351-
if (read_cache() < 0)
352-
return error("Could not read index");
353-
for (i = 0; i+1 < active_nr; i++) {
355+
struct cache_entry *e = active_cache[i];
356+
357+
if (!ce_stage(e)) {
358+
*type = RESOLVED;
359+
return i + 1;
360+
}
361+
362+
*type = PUNTED;
363+
if (ce_stage(e) == 1) {
364+
if (active_nr <= ++i)
365+
return i + 1;
366+
}
367+
368+
/* Only handle regular files with both stages #2 and #3 */
369+
if (i + 1 < active_nr) {
354370
struct cache_entry *e2 = active_cache[i];
355-
struct cache_entry *e3 = active_cache[i+1];
371+
struct cache_entry *e3 = active_cache[i + 1];
356372
if (ce_stage(e2) == 2 &&
357373
ce_stage(e3) == 3 &&
358-
ce_same_name(e2, e3) &&
374+
ce_same_name(e, e3) &&
359375
S_ISREG(e2->ce_mode) &&
360-
S_ISREG(e3->ce_mode)) {
361-
string_list_insert(conflict, (const char *)e2->name);
362-
i++; /* skip over both #2 and #3 */
376+
S_ISREG(e3->ce_mode))
377+
*type = THREE_STAGED;
378+
}
379+
380+
/* Skip the entries with the same name */
381+
while (i < active_nr && ce_same_name(e, active_cache[i]))
382+
i++;
383+
return i;
384+
}
385+
386+
static int find_conflict(struct string_list *conflict)
387+
{
388+
int i;
389+
if (read_cache() < 0)
390+
return error("Could not read index");
391+
392+
for (i = 0; i < active_nr;) {
393+
int conflict_type;
394+
struct cache_entry *e = active_cache[i];
395+
i = check_one_conflict(i, &conflict_type);
396+
if (conflict_type == THREE_STAGED)
397+
string_list_insert(conflict, (const char *)e->name);
398+
}
399+
return 0;
400+
}
401+
402+
int rerere_remaining(struct string_list *merge_rr)
403+
{
404+
int i;
405+
if (read_cache() < 0)
406+
return error("Could not read index");
407+
408+
for (i = 0; i < active_nr;) {
409+
int conflict_type;
410+
struct cache_entry *e = active_cache[i];
411+
i = check_one_conflict(i, &conflict_type);
412+
if (conflict_type == PUNTED)
413+
string_list_insert(merge_rr, (const char *)e->name);
414+
else if (conflict_type == RESOLVED) {
415+
struct string_list_item *it;
416+
it = string_list_lookup(merge_rr, (const char *)e->name);
417+
if (it != NULL) {
418+
free(it->util);
419+
it->util = RERERE_RESOLVED;
420+
}
363421
}
364422
}
365423
return 0;

rerere.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@
66
#define RERERE_AUTOUPDATE 01
77
#define RERERE_NOAUTOUPDATE 02
88

9+
/*
10+
* Marks paths that have been hand-resolved and added to the
11+
* index. Set in the util field of such paths after calling
12+
* rerere_remaining.
13+
*/
14+
extern void *RERERE_RESOLVED;
15+
916
extern int setup_rerere(struct string_list *, int);
1017
extern int rerere(int);
1118
extern const char *rerere_path(const char *hex, const char *file);
1219
extern int has_rerere_resolution(const char *hex);
1320
extern int rerere_forget(const char **);
21+
extern int rerere_remaining(struct string_list *);
1422

1523
#define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
1624
"update the index with reused conflict resolution if possible")

0 commit comments

Comments
 (0)