summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 685e9d9)
raw | patch | inline | side by side (parent: 685e9d9)
author | Junio C Hamano <gitster@pobox.com> | |
Thu, 6 Jan 2011 19:33:27 +0000 (11:33 -0800) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Fri, 7 Jan 2011 00:51:43 +0000 (16:51 -0800) |
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.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
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.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/rerere.c | patch | blob | history | |
rerere.c | patch | blob | history |
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 642bf35587ed994948d3eeac0a189ae29e39bf11..081fccc7d7638f83a863a16193c91b17658f4d34 100644 (file)
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
#include "xdiff-interface.h"
static const char * const rerere_usage[] = {
- "git rerere [clear | status | diff | gc]",
+ "git rerere [clear | status | remaining | diff | gc]",
NULL,
};
if (!strcmp(argv[0], "clear")) {
for (i = 0; i < merge_rr.nr; i++) {
const char *name = (const char *)merge_rr.items[i].util;
+ if (!name)
+ continue;
if (!has_rerere_resolution(name))
unlink_rr_item(name);
}
} else if (!strcmp(argv[0], "gc"))
garbage_collect(&merge_rr);
else if (!strcmp(argv[0], "status"))
+ for (i = 0; i < merge_rr.nr; i++) {
+ if (!merge_rr.items[i].util)
+ continue;
+ printf("%s\n", merge_rr.items[i].string);
+ }
+ else if (!strcmp(argv[0], "remaining"))
for (i = 0; i < merge_rr.nr; i++)
printf("%s\n", merge_rr.items[i].string);
else if (!strcmp(argv[0], "diff"))
for (i = 0; i < merge_rr.nr; i++) {
const char *path = merge_rr.items[i].string;
const char *name = (const char *)merge_rr.items[i].util;
+ if (!name)
+ continue;
diff_two(rerere_path(name, "preimage"), path, path, path);
}
else
diff --git a/rerere.c b/rerere.c
index d2608434750c336c3f3881efda8373b7c67d4b11..eb47f975c6154cb56e05a16da0223a492d63be59 100644 (file)
--- a/rerere.c
+++ b/rerere.c
int i;
if (read_cache() < 0)
return error("Could not read index");
- for (i = 0; i+1 < active_nr; i++) {
- struct cache_entry *e2 = active_cache[i];
- struct cache_entry *e3 = active_cache[i+1];
- if (ce_stage(e2) == 2 &&
- ce_stage(e3) == 3 &&
- ce_same_name(e2, e3) &&
- S_ISREG(e2->ce_mode) &&
- S_ISREG(e3->ce_mode)) {
- string_list_insert(conflict, (const char *)e2->name);
- i++; /* skip over both #2 and #3 */
+
+ /*
+ * Collect paths with conflict, mark them with NULL (punted) or
+ * !NULL (eligible) in their ->util field.
+ */
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *e = active_cache[i];
+ struct string_list_item *it;
+
+ if (!ce_stage(e))
+ continue;
+ it = string_list_insert(conflict, (const char *)e->name);
+ it->util = NULL;
+ if (ce_stage(e) == 1) {
+ if (active_nr <= ++i)
+ break;
}
+
+ /* Only handle regular files with both stages #2 and #3 */
+ if (i + 1 < active_nr) {
+ struct cache_entry *e2 = active_cache[i];
+ struct cache_entry *e3 = active_cache[i + 1];
+ if (ce_stage(e2) == 2 &&
+ ce_stage(e3) == 3 &&
+ ce_same_name(e, e3) &&
+ S_ISREG(e2->ce_mode) &&
+ S_ISREG(e3->ce_mode))
+ it->util = (void *) 1;
+ }
+
+ /* Skip the entries with the same name */
+ while (i < active_nr && ce_same_name(e, active_cache[i]))
+ i++;
+ i--; /* compensate for the outer loop */
}
return 0;
}
+static void add_punted(struct string_list *merge_rr)
+{
+ int i;
+ struct string_list conflict = STRING_LIST_INIT_DUP;
+
+ find_conflict(&conflict);
+ for (i = 0; i < conflict.nr; i++) {
+ if (conflict.items[i].util)
+ continue;
+ string_list_insert(merge_rr, conflict.items[i].string);
+ }
+}
+
static int merge(const char *name, const char *path)
{
int ret;
for (i = 0; i < conflict.nr; i++) {
const char *path = conflict.items[i].string;
+ if (!conflict.items[i].util)
+ continue; /* punted */
if (!string_list_has_string(rr, path)) {
unsigned char sha1[20];
char *hex;
const char *path = rr->items[i].string;
const char *name = (const char *)rr->items[i].util;
+ if (!name)
+ continue;
if (has_rerere_resolution(name)) {
if (!merge(name, path)) {
if (rerere_autoupdate)
fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
LOCK_DIE_ON_ERROR);
read_rr(merge_rr);
+ add_punted(merge_rr);
return fd;
}
find_conflict(&conflict);
for (i = 0; i < conflict.nr; i++) {
struct string_list_item *it = &conflict.items[i];
+ if (!conflict.items[i].util)
+ continue; /* punted */
if (!match_pathspec(pathspec, it->string, strlen(it->string),
0, NULL))
continue;