git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH] align D/F handling of "diff --no-index" with that of normal Git

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 22, 2015, 05:11 UTC
Message-ID
<xmqqiodtd3b4.fsf@gitster.dls.corp.google.com>

When a commit changes a path P that used to be a file to a directory and create a new path P/X in it, "git show" would say that file P was removed and file P/X was created for such a commit.

However, if we compare two directories, D1 and D2, where D1 has a file D1/P in it and D2 has a directory D2/P under which there is a file D2/P/X, and ask "git diff --no-index D1 D2" to show their differences, we simply get a refusal "file/directory conflict".

The "diff --no-index" implementation has an underlying machinery that can make it more in line with the normal Git if it wanted to, but somehow it is not being exercised. The only thing we need to do, when we see a file P and a directory P/ (or the other way around) is to show the removal of a file P and then pretend as if we are comparing nothing with a whole directory P/, as the code is fully prepared to express a creation of everything in a directory (and if the comparison is between a directory P/ and a file P, then show the creation of the file and then let the existing code remove everything in P/).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diff-no-index.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/diff-no-index.c b/diff-no-index.c
index 265709b..52e9546 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -97,8 +97,27 @@ static int queue_diff(struct diff_options *o,
 	if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
 		return -1;
 
-	if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
-		return error("file/directory conflict: %s, %s", name1, name2);
+	if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) {
+		struct diff_filespec *d1, *d2;
+
+		if (S_ISDIR(mode1)) {
+			/* 2 is file that is created */
+			d1 = noindex_filespec(NULL, 0);
+			d2 = noindex_filespec(name2, mode2);
+			name2 = NULL;
+			mode2 = 0;
+		} else {
+			/* 1 is file that is deleted */
+			d1 = noindex_filespec(name1, mode2);
+			d2 = noindex_filespec(NULL, 0);
+			name1 = NULL;
+			mode1 = 0;
+		}
+		/* emit that file */
+		diff_queue(&diff_queued_diff, d1, d2);
+
+		/* and then let the entire directory created or deleted */
+	}
 
 	if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
 		struct strbuf buffer1 = STRBUF_INIT;
Next: Eric Sunshine
Message 1 of 7 in “align D/F handling of "diff --no-index" with that of normal Git”
  1. align D/F handling of "diff --no-index" with that of normal GitJunio C Hamano, Mar 22, 2015
  2. Eric SunshineMar 22, 2015
  3. Ramsay JonesMar 22, 2015
  4. Junio C HamanoMar 22, 2015
  5. 0/2 "diff --no-index" updatesJunio C Hamano, Mar 26, 2015
  6. 1/2 diff-no-index: DWIM "diff D F" into "diff D/F F"Junio C Hamano, Mar 26, 2015
  7. 2/2 diff: align D/F handling of "diff --no-index" with that of normal GitJunio C Hamano, Mar 26, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.