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

[PATCH V2/RFC][GSoC] diff-no-index: transform "$directory $file" args to "$directory/$file $file"

From
YSYurii Shevtsov <ungetch@gmail.com>
Date
Mar 26, 2015, 20:54 UTC
Message-ID
<CAHLaBN+nE9tmGMdJM65V-bONKe8CE9PZ1Ottc1R9D=Pm0X7k_g@mail.gmail.com>

git diff --no-index refuses to compare if args are directory and file, instead of usual diff.

Now git diff --no-index modifies args, if they're directory and file, and diffs files, as usual diff does.

Changes are done in diff_no_index().
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Yurii Shevtsov <ungetch@gmail.com>
---
 diff-no-index.c |   31 +++++++++++++++++++++++++++++--
 1 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/diff-no-index.c b/diff-no-index.c
index 265709b..ecff15e 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -186,7 +186,7 @@ void diff_no_index(struct rev_info *revs,
            int argc, const char **argv,
            const char *prefix)
 {
-    int i, prefixlen;
+    int i, prefixlen, mode1 = 0, mode2 = 0;
     const char *paths[2];

     diff_setup(&revs->diffopt);
@@ -229,8 +229,35 @@ void diff_no_index(struct rev_info *revs,
     setup_diff_pager(&revs->diffopt);
     DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);

-    if (queue_diff(&revs->diffopt, paths[0], paths[1]))
+    if (get_mode(paths[0], &mode1) || get_mode(paths[1], &mode2))
+        exit(2);
+
+    if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) {
+        struct strbuf pathtofile;
+        const char *dir, *file;
+        char *filename;
+        int ret;
+
+        dir = S_ISDIR(mode1) ? paths[0] : paths[1];
+        file = (dir == paths[0]) ? paths[1] : paths[0];
+        strbuf_init(&pathtofile, strlen(paths[0]) + strlen(paths[1]) + 1);
+        strbuf_addstr(&pathtofile, dir);
+        if (pathtofile.len && pathtofile.buf[pathtofile.len - 1] != '/')
+               strbuf_addch(&pathtofile, '/');
+        filename = strrchr(file, '/');
+        strbuf_addstr(&pathtofile, filename ? (filename + 1) : file);
+
+        if (file == paths[0])
+            ret = queue_diff(&revs->diffopt, file, pathtofile.buf);
+        else
+            ret = queue_diff(&revs->diffopt, pathtofile.buf, file);
+        strbuf_release(&pathtofile);
+        if (ret)
+            exit(1);
+    }
+    else if (queue_diff(&revs->diffopt, paths[0], paths[1]))
         exit(1);
+
     diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/");
     diffcore_std(&revs->diffopt);
     diff_flush(&revs->diffopt);
-- 
Attached patch file because gmail always replaces tabs with spaces and
refuses to authorize 'git send-email'


From 0e160b47960dd436b32e55229184688c0a9da069 Mon Sep 17 00:00:00 2001
From: Yurii Shevtsov <ungetch@gmail.com>
Date: Thu, 25 Mar 2015 18:43:24 +0200
Subject: [PATCH]  diff-no-index: transform "$directory $file" args to "$directory/$file $file"
git diff --no-index refuses to compare if args are directory and file, instead of usual diff.

Now git diff --no-index modifies args, if they're directory and file, and
diffs files, as usual diff does.

Changes are done in diff_no_index().

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Yurii Shevtsov <ungetch@gmail.com>
---
 diff-no-index.c |   31 +++++++++++++++++++++++++++++--
 1 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/diff-no-index.c b/diff-no-index.c
index 265709b..ecff15e 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -186,7 +186,7 @@ void diff_no_index(struct rev_info *revs,
 		   int argc, const char **argv,
 		   const char *prefix)
 {
-	int i, prefixlen;
+	int i, prefixlen, mode1 = 0, mode2 = 0;
 	const char *paths[2];
 
 	diff_setup(&revs->diffopt);
@@ -229,8 +229,35 @@ void diff_no_index(struct rev_info *revs,
 	setup_diff_pager(&revs->diffopt);
 	DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
 
-	if (queue_diff(&revs->diffopt, paths[0], paths[1]))
+	if (get_mode(paths[0], &mode1) || get_mode(paths[1], &mode2))
+		exit(2);
+
+	if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) {
+		struct strbuf pathtofile;
+		const char *dir, *file;
+		char *filename;
+		int ret;
+
+		dir = S_ISDIR(mode1) ? paths[0] : paths[1];
+		file = (dir == paths[0]) ? paths[1] : paths[0];
+		strbuf_init(&pathtofile, strlen(paths[0]) + strlen(paths[1]) + 1);
+		strbuf_addstr(&pathtofile, dir);
+		if (pathtofile.len && pathtofile.buf[pathtofile.len - 1] != '/')
+			   strbuf_addch(&pathtofile, '/');
+		filename = strrchr(file, '/');
+		strbuf_addstr(&pathtofile, filename ? (filename + 1) : file);
+
+		if (file == paths[0])
+			ret = queue_diff(&revs->diffopt, file, pathtofile.buf);
+		else
+			ret = queue_diff(&revs->diffopt, pathtofile.buf, file);
+		strbuf_release(&pathtofile);
+		if (ret)
+			exit(1);
+	}
+	else if (queue_diff(&revs->diffopt, paths[0], paths[1]))
 		exit(1);
+
 	diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/");
 	diffcore_std(&revs->diffopt);
 	diff_flush(&revs->diffopt);
-- 
1.7.1
Next: Junio C Hamano
Message 1 of 2 in “[GSoC] diff-no-index: transform "$directory $file" args to "$directory/$file $file"”
  1. [GSoC] diff-no-index: transform "$directory $file" args to "$directory/$file $file"Yurii Shevtsov, Mar 26, 2015
  2. Junio C HamanoMar 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.