Skip to content

Commit a21bae3

Browse files
SamBgitster
authored andcommitted
diff: let "git diff -O" read orderfile from any file and fail properly
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b527773 commit a21bae3

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

diffcore-order.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,21 @@ static int order_cnt;
1010

1111
static void prepare_order(const char *orderfile)
1212
{
13-
int fd, cnt, pass;
13+
int cnt, pass;
14+
struct strbuf sb = STRBUF_INIT;
1415
void *map;
1516
char *cp, *endp;
16-
struct stat st;
17-
size_t sz;
17+
ssize_t sz;
1818

1919
if (order)
2020
return;
2121

22-
fd = open(orderfile, O_RDONLY);
23-
if (fd < 0)
24-
return;
25-
if (fstat(fd, &st)) {
26-
close(fd);
27-
return;
28-
}
29-
sz = xsize_t(st.st_size);
30-
map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
31-
close(fd);
32-
if (map == MAP_FAILED)
33-
return;
22+
sz = strbuf_read_file(&sb, orderfile, 0);
23+
if (sz < 0)
24+
die_errno(_("failed to read orderfile '%s'"), orderfile);
25+
map = strbuf_detach(&sb, NULL);
3426
endp = (char *) map + sz;
27+
3528
for (pass = 0; pass < 2; pass++) {
3629
cnt = 0;
3730
cp = map;

t/t4056-diff-order.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,38 @@ test_expect_success "no order (=tree object order)" '
5757
test_cmp expect_none actual
5858
'
5959

60+
test_expect_success 'missing orderfile' '
61+
rm -f bogus_file &&
62+
test_must_fail git diff -Obogus_file --name-only HEAD^..HEAD
63+
'
64+
65+
test_expect_success POSIXPERM,SANITY 'unreadable orderfile' '
66+
>unreadable_file &&
67+
chmod -r unreadable_file &&
68+
test_must_fail git diff -Ounreadable_file --name-only HEAD^..HEAD
69+
'
70+
71+
test_expect_success 'orderfile is a directory' '
72+
test_must_fail git diff -O/ --name-only HEAD^..HEAD
73+
'
74+
6075
for i in 1 2
6176
do
6277
test_expect_success "orderfile using option ($i)" '
6378
git diff -Oorder_file_$i --name-only HEAD^..HEAD >actual &&
6479
test_cmp expect_$i actual
6580
'
81+
82+
test_expect_success PIPE "orderfile is fifo ($i)" '
83+
rm -f order_fifo &&
84+
mkfifo order_fifo &&
85+
{
86+
cat order_file_$i >order_fifo &
87+
} &&
88+
git diff -O order_fifo --name-only HEAD^..HEAD >actual &&
89+
wait &&
90+
test_cmp expect_$i actual
91+
'
6692
done
6793

6894
test_done

0 commit comments

Comments
 (0)