diff mbox series

[v2,19/27] gitattributes doc: document multi-line userdiff patterns

Message ID 20210215154427.32693-20-avarab@gmail.com (mailing list archive)
State Superseded
Headers show
Series userdiff: refactor + test + doc + misc improvements | expand

Commit Message

Ævar Arnfjörð Bjarmason Feb. 15, 2021, 3:44 p.m. UTC
Document the multi-line userdiff patterns and how their matching and
the negation syntax works.

These patterns have been supported since f258475a6e (Per-path
attribute based hunk header selection., 2007-07-06), and have had
their current semantics ever since 3d8dccd74a (diff: fix "multiple
regexp" semantics to find hunk header comment, 2008-09-20).

But we had no documentation for them, let's fix that, and also add
tests showing how some of the things being discussed here work.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/gitattributes.txt | 33 +++++++++++++++++++---
 t/t4018/custom.sh               | 50 +++++++++++++++++++++++++++++++++
 t/t4018/perl.sh                 | 16 +++++++++++
 3 files changed, 95 insertions(+), 4 deletions(-)

Comments

Johannes Sixt Feb. 15, 2021, 6:18 p.m. UTC | #1
Am 15.02.21 um 16:44 schrieb Ævar Arnfjörð Bjarmason:
> diff --git a/t/t4018/custom.sh b/t/t4018/custom.sh
> index 72d38dad68..30df13d8b2 100755
> --- a/t/t4018/custom.sh
> +++ b/t/t4018/custom.sh
> @@ -111,3 +111,53 @@ ChangeMe
>   
>   baz
>   EOF_TEST
> +
> +test_expect_success 'custom: setup negation syntax, ! is magic' '
> +	git config diff.custom.xfuncname "!negation
> +line"
> +'
> +
> +test_diff_funcname 'custom: negation syntax, ! is magic' \
> +	8<<\EOF_HUNK 9<<\EOF_TEST
> +line
> +EOF_HUNK
> +line
> +!negation
> +
> +ChangeMe
> +
> +baz
> +EOF_TEST
> +
> +test_expect_success 'custom: setup negation syntax, use [!] to override ! magic' '
> +	git config diff.custom.xfuncname "[!]negation
> +line"
> +'
> +
> +test_diff_funcname 'custom: negation syntax, use [!] to override ! magic' \
> +	8<<\EOF_HUNK 9<<\EOF_TEST
> +!negation
> +EOF_HUNK
> +line
> +!negation
> +
> +ChangeMe
> +
> +baz
> +EOF_TEST
> +
> +test_expect_success 'custom: setup captures in multiple patterns' '
> +	git config diff.custom.xfuncname "!^=head
> +^format ([^ ]+)
> +^sub ([^;]+)"
> +'
> +
> +test_diff_funcname 'custom: captures in multiple patterns' \
> +	8<<\EOF_HUNK 9<<\EOF_TEST
> +foo
> +EOF_HUNK
> +sub foo;
> +=head1
> +ChangeMe
> +
> +EOF_TEST

This test would not catch a regression. You must leave a line between 
the candidate-that-must-not-be, =head1, and ChangeMe, otherwise, =head1 
is never tested against the negation pattern.

Or did you change the diff invocation in an earlier patch such that it 
does not emit context lines?

> diff --git a/t/t4018/perl.sh b/t/t4018/perl.sh
> index ac8fff7417..2952483a2c 100755
> --- a/t/t4018/perl.sh
> +++ b/t/t4018/perl.sh
> @@ -76,3 +76,19 @@ sub RIGHT
>   	print "ChangeMe\n";
>   }
>   EOF_TEST
> +
> +
> +test_expect_success 'custom: setup config overrides built-in patterns' '
> +	git config diff.perl.xfuncname "!^=head
> +^[^ ]+.*"
> +'
> +
> +test_diff_funcname 'custom: config overrides built-in patterns' \
> +	8<<\EOF_HUNK 9<<\EOF_TEST
> +sub foo;
> +EOF_HUNK
> +sub foo;
> +=head1
> +ChangeMe
> +
> +EOF_TEST

Same here.

-- Hannes
Ævar Arnfjörð Bjarmason Feb. 15, 2021, 7:01 p.m. UTC | #2
On Mon, Feb 15 2021, Johannes Sixt wrote:

> Am 15.02.21 um 16:44 schrieb Ævar Arnfjörð Bjarmason:
>> diff --git a/t/t4018/custom.sh b/t/t4018/custom.sh
>> index 72d38dad68..30df13d8b2 100755
>> --- a/t/t4018/custom.sh
>> +++ b/t/t4018/custom.sh
>> @@ -111,3 +111,53 @@ ChangeMe
>>     baz
>>   EOF_TEST
>> +
>> +test_expect_success 'custom: setup negation syntax, ! is magic' '
>> +	git config diff.custom.xfuncname "!negation
>> +line"
>> +'
>> +
>> +test_diff_funcname 'custom: negation syntax, ! is magic' \
>> +	8<<\EOF_HUNK 9<<\EOF_TEST
>> +line
>> +EOF_HUNK
>> +line
>> +!negation
>> +
>> +ChangeMe
>> +
>> +baz
>> +EOF_TEST
>> +
>> +test_expect_success 'custom: setup negation syntax, use [!] to override ! magic' '
>> +	git config diff.custom.xfuncname "[!]negation
>> +line"
>> +'
>> +
>> +test_diff_funcname 'custom: negation syntax, use [!] to override ! magic' \
>> +	8<<\EOF_HUNK 9<<\EOF_TEST
>> +!negation
>> +EOF_HUNK
>> +line
>> +!negation
>> +
>> +ChangeMe
>> +
>> +baz
>> +EOF_TEST
>> +
>> +test_expect_success 'custom: setup captures in multiple patterns' '
>> +	git config diff.custom.xfuncname "!^=head
>> +^format ([^ ]+)
>> +^sub ([^;]+)"
>> +'
>> +
>> +test_diff_funcname 'custom: captures in multiple patterns' \
>> +	8<<\EOF_HUNK 9<<\EOF_TEST
>> +foo
>> +EOF_HUNK
>> +sub foo;
>> +=head1
>> +ChangeMe
>> +
>> +EOF_TEST
>
> This test would not catch a regression. You must leave a line between
> the candidate-that-must-not-be, =head1, and ChangeMe, otherwise,
> =head1 is never tested against the negation pattern.
>
> Or did you change the diff invocation in an earlier patch such that it
> does not emit context lines?
>
>> diff --git a/t/t4018/perl.sh b/t/t4018/perl.sh
>> index ac8fff7417..2952483a2c 100755
>> --- a/t/t4018/perl.sh
>> +++ b/t/t4018/perl.sh
>> @@ -76,3 +76,19 @@ sub RIGHT
>>   	print "ChangeMe\n";
>>   }
>>   EOF_TEST
>> +
>> +
>> +test_expect_success 'custom: setup config overrides built-in patterns' '
>> +	git config diff.perl.xfuncname "!^=head
>> +^[^ ]+.*"
>> +'
>> +
>> +test_diff_funcname 'custom: config overrides built-in patterns' \
>> +	8<<\EOF_HUNK 9<<\EOF_TEST
>> +sub foo;
>> +EOF_HUNK
>> +sub foo;
>> +=head1
>> +ChangeMe
>> +
>> +EOF_TEST
>
> Same here.

Well spotted. Both of these test work for their advertised
purpose. I.e. "we can override the perl built-in config" and "capture
count gets reset", but you're right that the =head1 negation rule is
redundant at this point in the series.

In 23/27 we start testing with -U0, at which point it starts
working. But of course a better fix is to just add an empty line here...
Junio C Hamano Feb. 17, 2021, 12:03 a.m. UTC | #3
Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> -There are built-in patterns shipped as part of git itself. A more
> -advanced version of the `tex` pattern discussed above is one of them.
> +Multiple patterns can be supplied by listing them one per line
> +separated by `\n`. They will be matched one at a time from left to
> +right. Do not supply a trailing "\n" for the last pattern. E.g.:

I've always thought that this was modelled after "grep --file=FILE",
where patterns are listed one per line, so "from left to right"
looked a bit funny, at least to me.

If the "do not supply" is because "it would result in giving an
empty string '' as the final pattern, which may not be what you
want", then it is a good idea to spell it out.

> +------------------------
> +[diff "perl"]
> +	xfuncname = "!^=head\n^[^ ]+.*"
> +------------------------
> +
> +Patterns in in a list of multiple that begin with "!" are negated. A

"in in"???

> +matching negated pattern will cause the matched line to be
> +skipped. Use it to skip a later pattern that would otherwise match. It
> +is an error if one or more negated patterns aren't followed by a
> +non-negated pattern.
> +
> +To match a literal "!" at the start of a line, use some other regex
> +construct that will match a literal "!" without "!" being the first
> +character on that line, such as "[!]".
> +
> +If the pattern contains a `$1` capture it will be used instead of the
> +entire matching line (`$0`) to display the hunk header. This can be
> +used e.g. to strip whitespace from the beginning of the line, or to
> +only display the function name as part of a longer function
> +definition.
> +
> +There are built-in patterns shipped as part of git itself, see the
> +full listing below.

Other than the minor nits above, the new text is written very well.
diff mbox series

Patch

diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 62c1147ba9..b51d2c86e0 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -794,12 +794,37 @@  backslashes; the pattern above picks a line that begins with a
 backslash, and zero or more occurrences of `sub` followed by
 `section` followed by open brace, to the end of line.
 
-There are built-in patterns shipped as part of git itself. A more
-advanced version of the `tex` pattern discussed above is one of them.
+Multiple patterns can be supplied by listing them one per line
+separated by `\n`. They will be matched one at a time from left to
+right. Do not supply a trailing "\n" for the last pattern. E.g.:
+
+------------------------
+[diff "perl"]
+	xfuncname = "!^=head\n^[^ ]+.*"
+------------------------
+
+Patterns in in a list of multiple that begin with "!" are negated. A
+matching negated pattern will cause the matched line to be
+skipped. Use it to skip a later pattern that would otherwise match. It
+is an error if one or more negated patterns aren't followed by a
+non-negated pattern.
+
+To match a literal "!" at the start of a line, use some other regex
+construct that will match a literal "!" without "!" being the first
+character on that line, such as "[!]".
+
+If the pattern contains a `$1` capture it will be used instead of the
+entire matching line (`$0`) to display the hunk header. This can be
+used e.g. to strip whitespace from the beginning of the line, or to
+only display the function name as part of a longer function
+definition.
+
+There are built-in patterns shipped as part of git itself, see the
+full listing below.
 
 For built-in patterns, you do not need `diff.<lang>.xfuncname` in your
-configuration file as discussed above, but if present, it will
-override a built-in pattern.
+configuration file. If present, it will override a built-in pattern,
+as shown in the `diff.perl.xfuncname` example above.
 
 Nevertheless, you need to enable built-in patterns via .gitattributes`
 for the pattern to take effect.
diff --git a/t/t4018/custom.sh b/t/t4018/custom.sh
index 72d38dad68..30df13d8b2 100755
--- a/t/t4018/custom.sh
+++ b/t/t4018/custom.sh
@@ -111,3 +111,53 @@  ChangeMe
 
 baz
 EOF_TEST
+
+test_expect_success 'custom: setup negation syntax, ! is magic' '
+	git config diff.custom.xfuncname "!negation
+line"
+'
+
+test_diff_funcname 'custom: negation syntax, ! is magic' \
+	8<<\EOF_HUNK 9<<\EOF_TEST
+line
+EOF_HUNK
+line
+!negation
+
+ChangeMe
+
+baz
+EOF_TEST
+
+test_expect_success 'custom: setup negation syntax, use [!] to override ! magic' '
+	git config diff.custom.xfuncname "[!]negation
+line"
+'
+
+test_diff_funcname 'custom: negation syntax, use [!] to override ! magic' \
+	8<<\EOF_HUNK 9<<\EOF_TEST
+!negation
+EOF_HUNK
+line
+!negation
+
+ChangeMe
+
+baz
+EOF_TEST
+
+test_expect_success 'custom: setup captures in multiple patterns' '
+	git config diff.custom.xfuncname "!^=head
+^format ([^ ]+)
+^sub ([^;]+)"
+'
+
+test_diff_funcname 'custom: captures in multiple patterns' \
+	8<<\EOF_HUNK 9<<\EOF_TEST
+foo
+EOF_HUNK
+sub foo;
+=head1
+ChangeMe
+
+EOF_TEST
diff --git a/t/t4018/perl.sh b/t/t4018/perl.sh
index ac8fff7417..2952483a2c 100755
--- a/t/t4018/perl.sh
+++ b/t/t4018/perl.sh
@@ -76,3 +76,19 @@  sub RIGHT
 	print "ChangeMe\n";
 }
 EOF_TEST
+
+
+test_expect_success 'custom: setup config overrides built-in patterns' '
+	git config diff.perl.xfuncname "!^=head
+^[^ ]+.*"
+'
+
+test_diff_funcname 'custom: config overrides built-in patterns' \
+	8<<\EOF_HUNK 9<<\EOF_TEST
+sub foo;
+EOF_HUNK
+sub foo;
+=head1
+ChangeMe
+
+EOF_TEST