Skip to content

Commit d8faea9

Browse files
jnarebgitster
authored andcommitted
diff: strip extra "/" when stripping prefix
There are two ways a user might want to use "diff --relative": 1. For a file in a directory, like "subdir/file", the user can use "--relative=subdir/" to strip the directory. 2. To strip part of a filename, like "foo-10", they can use "--relative=foo-". We currently handle both of those situations. However, if the user passes "--relative=subdir" (without the trailing slash), we produce inconsistent results. For the unified diff format, we collapse the double-slash of "a//file" correctly into "a/file". But for other formats (raw, stat, name-status), we end up with "/file". We can do what the user means here and strip the extra "/" (and only a slash). We are not hurting any existing users of (2) above with this behavior change because the existing output for this case was nonsensical. Patch by Jakub, tests and commit message by Jeff King. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 497d9c3 commit d8faea9

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

diff.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,10 +2704,16 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
27042704
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
27052705
{
27062706
/* Strip the prefix but do not molest /dev/null and absolute paths */
2707-
if (*namep && **namep != '/')
2707+
if (*namep && **namep != '/') {
27082708
*namep += prefix_length;
2709-
if (*otherp && **otherp != '/')
2709+
if (**namep == '/')
2710+
++*namep;
2711+
}
2712+
if (*otherp && **otherp != '/') {
27102713
*otherp += prefix_length;
2714+
if (**otherp == '/')
2715+
++*otherp;
2716+
}
27112717
}
27122718

27132719
static void run_diff(struct diff_filepair *p, struct diff_options *o)

t/t4045-diff-relative.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/sh
2+
3+
test_description='diff --relative tests'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'setup' '
7+
git commit --allow-empty -m empty &&
8+
echo content >file1 &&
9+
mkdir subdir &&
10+
echo other content >subdir/file2 &&
11+
git add . &&
12+
git commit -m one
13+
'
14+
15+
check_diff() {
16+
expect=$1; shift
17+
cat >expected <<EOF
18+
diff --git a/$expect b/$expect
19+
new file mode 100644
20+
index 0000000..25c05ef
21+
--- /dev/null
22+
+++ b/$expect
23+
@@ -0,0 +1 @@
24+
+other content
25+
EOF
26+
test_expect_success "-p $*" "
27+
git diff -p $* HEAD^ >actual &&
28+
test_cmp expected actual
29+
"
30+
}
31+
32+
check_stat() {
33+
expect=$1; shift
34+
cat >expected <<EOF
35+
$expect | 1 +
36+
1 files changed, 1 insertions(+), 0 deletions(-)
37+
EOF
38+
test_expect_success "--stat $*" "
39+
git diff --stat $* HEAD^ >actual &&
40+
test_cmp expected actual
41+
"
42+
}
43+
44+
check_raw() {
45+
expect=$1; shift
46+
cat >expected <<EOF
47+
:000000 100644 0000000000000000000000000000000000000000 25c05ef3639d2d270e7fe765a67668f098092bc5 A $expect
48+
EOF
49+
test_expect_success "--raw $*" "
50+
git diff --no-abbrev --raw $* HEAD^ >actual &&
51+
test_cmp expected actual
52+
"
53+
}
54+
55+
for type in diff stat raw; do
56+
check_$type file2 --relative=subdir/
57+
check_$type file2 --relative=subdir
58+
check_$type dir/file2 --relative=sub
59+
done
60+
61+
test_done

0 commit comments

Comments
 (0)