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

[PATCH v4 2/3] diff: Let "git diff -O" read orderfile from any file, fail properly

From
Samuel Bronson <naesten@gmail.com>
Date
Dec 16, 2013, 20:09 UTC
Message-ID
<1387224586-10169-3-git-send-email-naesten@gmail.com>
In-Reply-To
<1387224586-10169-1-git-send-email-naesten@gmail.com>

The -O flag really shouldn't silently fail to do anything when given a path that it can't read from.

However, it should be able to read from un-mmappable files, such as:
 * pipes/fifos
 * /dev/null:  It's a character device (at least on Linux)
 * ANY empty file:
   Quoting Linux mmap(2), "SUSv3 specifies that mmap() should fail if
   length is 0.  However, in kernels before 2.6.12, mmap() succeeded in
   this case: no mapping was created and the call returned addr.  Since
   kernel 2.6.12, mmap() fails with the error EINVAL for this case."

We especially want "-O/dev/null" to work, since we will be documenting it as the way to cancel "diff.orderfile" when we add that.

(Note: "-O/dev/null" did have the right effect, since the existing error handling essentially worked out to "silently ignore the orderfile". But this was probably more coincidence than anything else.)

So, lets toss all of that logic to get the file mmapped and just use strbuf_read_file() instead, which gives us decent error handling practically for free.

Signed-off-by: Samuel Bronson <naesten@gmail.com>
---
 diffcore-order.c      | 23 ++++++++---------------
 t/t4056-diff-order.sh | 23 +++++++++++++++++++++++
 2 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/diffcore-order.c b/diffcore-order.c
index 23e9385..a63f332 100644
--- a/diffcore-order.c
+++ b/diffcore-order.c
@@ -10,28 +10,21 @@ static int order_cnt;
 
 static void prepare_order(const char *orderfile)
 {
-	int fd, cnt, pass;
+	int cnt, pass;
+	struct strbuf sb = STRBUF_INIT;
 	void *map;
 	char *cp, *endp;
-	struct stat st;
-	size_t sz;
+	ssize_t sz;
 
 	if (order)
 		return;
 
-	fd = open(orderfile, O_RDONLY);
-	if (fd < 0)
-		return;
-	if (fstat(fd, &st)) {
-		close(fd);
-		return;
-	}
-	sz = xsize_t(st.st_size);
-	map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
-	close(fd);
-	if (map == MAP_FAILED)
-		return;
+	sz = strbuf_read_file(&sb, orderfile, 0);
+	if (sz < 0)
+		die_errno(_("failed to read orderfile '%s'"), orderfile);
+	map = strbuf_detach(&sb, NULL);
 	endp = (char *) map + sz;
+
 	for (pass = 0; pass < 2; pass++) {
 		cnt = 0;
 		cp = map;
diff --git a/t/t4056-diff-order.sh b/t/t4056-diff-order.sh
index 398b3f6..eb471e7 100755
--- a/t/t4056-diff-order.sh
+++ b/t/t4056-diff-order.sh
@@ -61,12 +61,35 @@ test_expect_success "no order (=tree object order)" '
 	test_cmp expect_none actual
 '
 
+test_expect_success 'missing orderfile' '
+	rm -f bogus_file &&
+	test_must_fail git diff -Obogus_file --name-only HEAD^..HEAD
+'
+
+test_expect_success 'unreadable orderfile' '
+	touch unreadable_file &&
+	chmod -r unreadable_file &&
+	test_must_fail git diff -Ounreadable_file --name-only HEAD^..HEAD
+'
+
+test_expect_success 'orderfile is a directory' '
+	test_must_fail git diff -O/ --name-only HEAD^..HEAD
+'
+
 for i in 1 2
 do
 	test_expect_success "orderfile using option ($i)" '
 	git diff -Oorder_file_$i --name-only HEAD^..HEAD >actual &&
 	test_cmp expect_$i actual
 '
+
+	test_expect_success PIPE "orderfile is fifo ($i)" '
+	rm -f order_fifo &&
+	mkfifo order_fifo &&
+	cat order_file_$i >order_fifo &
+	git diff -O order_fifo --name-only HEAD^..HEAD >actual &&
+	test_cmp expect_$i actual
+'
 done
 
 test_done
-- 
1.8.4.3
Previous: Samuel BronsonNext: Junio C Hamano
Message 17 of 35 in “diff: Add diff.orderfile configuration variable”
  1. diff: Add diff.orderfile configuration variableAnders Waldenborg, Oct 21, 2013
  2. Jonathan NiederOct 21, 2013
  3. Anders WaldenborgOct 25, 2013
  4. diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 6, 2013
  5. Junio C HamanoDec 6, 2013
  6. Samuel BronsonDec 7, 2013
  7. Junio C HamanoDec 9, 2013
  8. 0/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 14, 2013
  9. 1/3 diff: Tests for "git diff -O"Samuel Bronson, Dec 14, 2013
  10. 2/3 diff: Let "git diff -O" read orderfile from any file, failing when appropriateSamuel Bronson, Dec 14, 2013
  11. Junio C HamanoDec 16, 2013
  12. 3/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 14, 2013
  13. Junio C HamanoDec 16, 2013
  14. Samuel BronsonDec 16, 2013
  15. 0/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 16, 2013
  16. 1/3 diff: Tests for "git diff -O"Samuel Bronson, Dec 16, 2013
  17. 2/3 diff: Let "git diff -O" read orderfile from any file, fail properlySamuel Bronson, Dec 16, 2013
  18. Junio C HamanoDec 16, 2013
  19. Samuel BronsonDec 17, 2013
  20. Junio C HamanoDec 16, 2013
  21. Samuel BronsonDec 17, 2013
  22. Junio C HamanoDec 17, 2013
  23. Antoine PelisseDec 17, 2013
  24. Junio C HamanoDec 17, 2013
  25. Samuel BronsonDec 18, 2013
  26. Junio C HamanoDec 18, 2013
  27. Junio C HamanoDec 17, 2013
  28. 3/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 16, 2013
  29. 0/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 19, 2013
  30. 1/3 diff: Tests for "git diff -O"Samuel Bronson, Dec 19, 2013
  31. 2/3 diff: Let "git diff -O" read orderfile from any file, fail properlySamuel Bronson, Dec 19, 2013
  32. diff test: reading a directory as a file need not error outJonathan Nieder, Jan 10, 2014
  33. Junio C HamanoJan 10, 2014
  34. 3/3 diff: Add diff.orderfile configuration variableSamuel Bronson, Dec 19, 2013
  35. Junio C HamanoDec 19, 2013

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.