git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
Cc: git@vger.kernel.org, Magnus Baeck <magnus.back@sonyericsson.com>,
	Avery Pennarun <apenwarr@gmail.com>,
	Jay Soffian <jaysoffian@gmail.com>,
	David Aguilar <davvid@gmail.com>
Subject: Re: git mergetool broken when rerere active
Date: Thu, 06 Jan 2011 11:33:27 -0800	[thread overview]
Message-ID: <7v62u1bzeg.fsf@alter.siamese.dyndns.org> (raw)
In-Reply-To: <7vbp3tc142.fsf@alter.siamese.dyndns.org> (Junio C. Hamano's message of "Thu\, 06 Jan 2011 10\:56\:29 -0800")

Junio C Hamano <gitster@pobox.com> writes:

> Probably we would need a "git rerere remaining" sobcommand that is similar
> to status but also includes the "punted" paths.

... which may look like this.

Replace use of "git rerere status" in bb0a484 (mergetool: Skip
autoresolved paths, 2010-08-17) with "git rerere remainder" and see what
happens.

 builtin/rerere.c |   12 +++++++++-
 rerere.c         |   63 +++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/builtin/rerere.c b/builtin/rerere.c
index 642bf35..081fccc 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -8,7 +8,7 @@
 #include "xdiff-interface.h"
 
 static const char * const rerere_usage[] = {
-	"git rerere [clear | status | diff | gc]",
+	"git rerere [clear | status | remaining | diff | gc]",
 	NULL,
 };
 
@@ -147,6 +147,8 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
 	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);
 		}
@@ -154,12 +156,20 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
 	} 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 d260843..eb47f97 100644
--- a/rerere.c
+++ b/rerere.c
@@ -350,21 +350,57 @@ static int find_conflict(struct string_list *conflict)
 	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;
@@ -451,6 +487,8 @@ static int do_plain_rerere(struct string_list *rr, int fd)
 
 	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;
@@ -478,6 +516,8 @@ static int do_plain_rerere(struct string_list *rr, int fd)
 		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)
@@ -552,6 +592,7 @@ int setup_rerere(struct string_list *merge_rr, int flags)
 	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;
 }
 
@@ -607,6 +648,8 @@ int rerere_forget(const char **pathspec)
 	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;

  reply	other threads:[~2011-01-06 19:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-06  3:39 git mergetool broken when rerere active Martin von Zweigbergk
2011-01-06 12:47 ` Martin von Zweigbergk
2011-01-06 18:56 ` Junio C Hamano
2011-01-06 19:33   ` Junio C Hamano [this message]
2011-01-06 19:51     ` Martin von Zweigbergk
2011-01-07  2:50     ` Martin von Zweigbergk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7v62u1bzeg.fsf@alter.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=apenwarr@gmail.com \
    --cc=davvid@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jaysoffian@gmail.com \
    --cc=magnus.back@sonyericsson.com \
    --cc=martin.von.zweigbergk@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).