Fix trailers atom bug and improved tests
PATCH 1/2 t6300: unify %(trailers) and %(contents:trailers) tests
In reply to Hariom Verma via GitGitGadgetFrom: Hariom Verma <[email protected]>
Currently, there are different tests for testing %(trailers) and %(contents:trailers) causing redundant copy.
Its time to get rid of duplicate code.
--- t/t6300-for-each-ref.sh | 50 +++++++++-------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-)
t/t6300-for-each-ref.sh +11 -39
@@ -776,60 +776,39 @@ test_expect_success 'set up trailers for next test' ' ' test_expect_success '%(trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && { unfold <trailers echo } >expect && + git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && { grep -v patch.description <trailers && echo } >expect && + git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) and %(trailers:unfold) work together' ' - git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && { grep -v patch.description <trailers | unfold && echo } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && - { - unfold <trailers - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && - { - grep -v patch.description <trailers && - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' ' + git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && + git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && + test_cmp actual reverse && + test_cmp expect actual && git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual && git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse && test_cmp actual reverse && - { - grep -v patch.description <trailers | unfold && - echo - } >expect && test_cmp expect actual '
@@ -839,14 +818,7 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' fatal: unknown %(trailers) argument: unsupported EOF test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual && - test_i18ncmp expect actual -' - -test_expect_success '%(contents:trailers) rejects unknown trailers arguments' ' - # error message cannot be checked under i18n - cat >expect <<-EOF && - fatal: unknown %(trailers) argument: unsupported - EOF + test_i18ncmp expect actual && test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual && test_i18ncmp expect actual '
Signature · 1 line
gitgitgadget
cover Fix trailers atom bug and improved tests
Currently, there exists a bug in 'contents' atom. It does not show any error if used with modifier 'trailers' and semicolon is missing before trailers arguments. This small patch series is focused on fixing that bug and also unified 'trailers' and 'contents:trailers' tests. Thus, removed duplicate code from t6300 and made tests more compact.
Hariom Verma (2):
t6300: unify %(trailers) and %(contents:trailers) tests
ref-filter: 'contents:trailers' show error if : is missing
ref-filter.c | 21 +++++++++++++++--- t/t6300-for-each-ref.sh | 49 +++++++++++++---------------------------- 2 files changed, 33 insertions(+), 37 deletions(-)
base-commit: 2befe97201e1f3175cce557866c5822793624b5a
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-707%2Fharry-hov%2Ffix-trailers-atom-bug-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-707/harry-hov/fix-trailers-atom-bug-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/707
Signature · 1 line
gitgitgadget
PATCH 2/2 ref-filter: 'contents:trailers' show error if `:` is missing
From: Hariom Verma <[email protected]>
The 'contents' atom does not show any error if used with 'trailers' atom and semicolon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
It is definitely not an expected behavior.
Let's fix this bug.
--- ref-filter.c | 21 ++++++++++++++++++--- t/t6300-for-each-ref.sh | 9 +++++++++ 2 files changed, 27 insertions(+), 3 deletions(-)
ref-filter.c +18 -3
@@ -332,6 +332,22 @@ static int trailers_atom_parser(const struct ref_format *format, struct used_atoreturn 0 ; } +static int check_format_field (const char *arg,const char *field,const char **option) +{ +const char *opt; +if (skip_prefix (arg, field, &opt)) { +if (*opt =='\0' ) { + *option =NULL ; +return 1 ; + } +else if (*opt ==':' ) { + *option = ++opt; +return 1 ; + } + } +return 0 ; +} +static int contents_atom_parser (const struct ref_format *format,struct used_atom *atom,const char *arg,struct strbuf *err) {
@@ -345,9 +361,8 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato atom->u.contents.option =C_SIG ; else if (!strcmp(arg, "subject")) atom->u.contents.option =C_SUB ; - else if (skip_prefix(arg, "trailers", &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) + else if (check_format_field(arg, "trailers", &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option =C_LINES ;
t/t6300-for-each-ref.sh +9 -0
@@ -823,6 +823,15 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' test_i18ncmp expect actual ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' ' + # error message cannot be checked under i18n + cat >expect <<-EOF && + fatal: unrecognized %(contents) argument: trailersonly + EOF + test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual && + test_i18ncmp expect actual +' + test_expect_success 'basic atom: head contents:trailers' ' git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual && sanitize_pgp <actual >actual.clean &&
Signature · 1 line
gitgitgadget
Re: [PATCH 1/2] t6300: unify %(trailers) and %(contents:trailers) tests
In reply to Hariom Verma via GitGitGadgetQuoted 8 lines · Hariom Verma via GitGitGadget
t/t6300-for-each-ref.sh +0
-0@@ -776,60 +776,39 @@ test_expect_success 'set up trailers for next test' ' ' test_expect_success '%(trailers:unfold) unfolds trailers' '
t/t6300-for-each-ref.sh test_expect_success 'set up trailers for next test' ' · line 787
Quoted 10 lines
t/t6300-for-each-ref.sh +3
-1- git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && { unfold <trailers echo } >expect && + git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && test_cmp expect actual '
Hmph, what is this one doing? Ah, OK, trailers:unfold is tested as before (just the steps to prepare 'expect' and 'actual' got swapped), and because the same expectation holds for contents:trailers:unfold,
we can test it at the same. Makes sense.
t/t6300-for-each-ref.sh test_expect_success 'set up trailers for next test' ' · line 808
Quoted 12 lines
t/t6300-for-each-ref.sh +4
-3test_expect_success '%(trailers:only) and %(trailers:unfold) work together' ' - git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && { grep -v patch.description <trailers | unfold && echo } >expect && + git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && + git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && + test_cmp actual reverse && + test_cmp expect actual &&
This uses different pattern. It may be cleaner to test one side at a time, as we have prepared the 'expect' that should be the same for both, and compare with the expected pattern one at a time; that would eliminate the need for 'reverse', too. I.e.
{
grep -v patch.description trailers | unfold && echo
} >expect &&
git for-each-ref ... only,unfold ... >actual &&
test_cmp expect actual &&
git for-each-ref ... unfold,only ... >actual &&
test_cmp expect actual &&Quoted 6 lines
t/t6300-for-each-ref.sh +0
-2@@ -839,14 +818,7 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' fatal: unknown %(trailers) argument: unsupported EOF test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual && - test_i18ncmp expect actual -'
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 824
Quoted 10 lines
t/t6300-for-each-ref.sh +1
-6- -test_expect_success '%(contents:trailers) rejects unknown trailers arguments' ' - # error message cannot be checked under i18n - cat >expect <<-EOF && - fatal: unknown %(trailers) argument: unsupported - EOF + test_i18ncmp expect actual && test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual && test_i18ncmp expect actual '
Doesn't this highlight a small bug, where an end-user request for an unknown %(contents:trailers:unsupported) is flagged as an error about %(trailers)? Is it OK because we expect that users who use the longer %(contents:trailers) to know that it is a synonym for %(trailers) and the latter is the official way to write it?
Thanks.
Re: [PATCH 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Hariom Verma via GitGitGadgetQuoted 7 lines · Hariom Verma via GitGitGadget
From: Hariom Verma <[email protected]>
The 'contents' atom does not show any error if used with 'trailers' atom and semicolon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
Quoted 8 lines
It is definitely not an expected behavior.
Let's fix this bug.
Mentored-by Christian Couder <[email protected]>Mentored-by Heba Waly <[email protected]>Signed-off-by Hariom Verma <[email protected]>---
Nice spotting. 7a5edbdb (ref-filter.c: parse trailers arguments with %(contents) atom, 2017-10-01) talks about being deliberate about the case where skip_prefix(":") does not find a colon after the "trailers" token, but from the message it is clear that it expected that the case happens only when "trailers" is at the end of the string.
The new helper that is overly verbose and may be overkill.
Shouldn't this be clear enough, equivalent and sufficient?
else if (skip_prefix(arg, "trailers", &arg) &&
(!*arg || *arg == ':'))) {
if (trailers_atom_parser(...);That is, we not just make sure the string begins with "trailers", but also make sure it either (1) ends the string (i.e. the token is just "trailers"), or (2) is followed by a colon ':', before entering the block to handle "trailers[:anything]". If we later add a new atom "trailersonly", that will not be handled here, but elsewhere in the "else if" cascade.
Quoted 43 lines
ref-filter.c | 21 ++++++++++++++++++--- t/t6300-for-each-ref.sh | 9 +++++++++ 2 files changed, 27 insertions(+), 3 deletions(-)ref-filter.c +18
-3@@ -332,6 +332,22 @@ static int trailers_atom_parser(const struct ref_format *format, struct used_atoreturn 0 ; } +static int check_format_field (const char *arg,const char *field,const char **option) +{ +const char *opt; +if (skip_prefix (arg, field, &opt)) { +if (*opt =='\0' ) { + *option =NULL ; +return 1 ; + } +else if (*opt ==':' ) { + *option = ++opt; +return 1 ; + } + } +return 0 ; +} +static int contents_atom_parser (const struct ref_format *format,struct used_atom *atom,const char *arg,struct strbuf *err) {@@ -345,9 +361,8 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato atom->u.contents.option =C_SIG ; else if (!strcmp(arg, "subject")) atom->u.contents.option =C_SUB ; - else if (skip_prefix(arg, "trailers", &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) + else if (check_format_field(arg, "trailers", &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option =C_LINES ;
Re: [PATCH 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 25 lines · Junio C Hamano
Quoted 7 lines · Hariom Verma via GitGitGadget
From: Hariom Verma <[email protected]>
The 'contents' atom does not show any error if used with 'trailers' atom and semicolon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
Quoted 8 lines
It is definitely not an expected behavior.
Let's fix this bug.
Mentored-by Christian Couder <[email protected]>Mentored-by Heba Waly <[email protected]>Signed-off-by Hariom Verma <[email protected]>---
Nice spotting.
7a5edbdb(ref-filter.c: parse trailers arguments with %(contents) atom, 2017-10-01) talks about being deliberate about the case whereskip_prefix(":")does not find a colon after the "trailers" token, but from the message it is clear that it expected that the case happens only when "trailers" is at the end of the string.
Quoted 7 lines
The new helper that is overly verbose and may be overkill.
Shouldn't this be clear enough, equivalent and sufficient?
else if (skip_prefix(arg, "trailers", &arg) && (!*arg || *arg == ':'))) { if (trailers_atom_parser(...);
Ah, no, even with "*arg++ == ':'. This moves arg past "trailers" if given "trailersandsomegarbage" and the next one in "else if" cascade would look at "andsomegarbage"---which is not what we want.
Quoted 7 lines
Quoted 7 lines
ref-filter.c +7
-0+static int check_format_field (const char *arg,const char *field,const char **option) +{ +const char *opt; +if (skip_prefix (arg, field, &opt)) { +if (*opt =='\0' ) { + *option =NULL ; +return 1 ;
Quoted 8 lines
ref-filter.c static int trailers_atom_parser(const struct ref_format *format, struct used_ato · line 349
Quoted 8 lines
ref-filter.c +8
-0+ } +else if (*opt ==':' ) { + *option = ++opt; +return 1 ; + } + } +return 0 ; +}
And the helper does not have such a breakage. It looks good.
Thanks.
Re: [PATCH 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Junio C Hamano
ref-filter.c static int trailers_atom_parser(const struct ref_format *format, struct used_ato · line 346
Quoted 6 lines · Hariom Verma via GitGitGadget
ref-filter.c +6
-0+static int check_format_field (const char *arg,const char *field,const char **option) +{ + else if (*opt == ':') { + *option = ++opt; +return 1 ; + }And the helper does not have such a breakage. It looks good.
One minor comment (not worth a re-roll): I personally found:
*option = ++opt;
more confusing than:
*option = opt + 1;
The ++opt places a higher cognitive load on the reader. As a reviewer, I had to go back and carefully reread the function to see if the side-effect of ++opt had some impact which I didn't notice on the first readthrough. The simpler opt + 1 does not have a side-effect, thus is easier to reason about (and doesn't require me to re-study the function when I encounter it).
Re: [PATCH 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 18 lines · Eric Sunshine
Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Junio C Hamano
ref-filter.c static int trailers_atom_parser(const struct ref_format *format, struct used_ato · line 346
Quoted 6 lines · Hariom Verma via GitGitGadget
ref-filter.c +6
-0+static int check_format_field (const char *arg,const char *field,const char **option) +{ + else if (*opt == ':') { + *option = ++opt; +return 1 ; + }And the helper does not have such a breakage. It looks good.
One minor comment (not worth a re-roll): I personally found:
*option = ++opt;more confusing than:
Quoted 8 lines
*option = opt + 1;The
++optplaces a higher cognitive load on the reader. As a reviewer, I had to go back and carefully reread the function to see if the side-effect of++opthad some impact which I didn't notice on the first readthrough. The simpleropt + 1does not have a side-effect, thus is easier to reason about (and doesn't require me to re-study the function when I encounter it).
That makes the two of us ... thanks.
Re: [PATCH 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Hi,
Quoted 23 lines · Junio C Hamano
Quoted 20 lines · Eric Sunshine
Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Junio C Hamano
ref-filter.c static int trailers_atom_parser(const struct ref_format *format, struct used_ato · line 346
Quoted 6 lines · Hariom Verma via GitGitGadget
ref-filter.c +6
-0+static int check_format_field (const char *arg,const char *field,const char **option) +{ + else if (*opt == ':') { + *option = ++opt; +return 1 ; + }And the helper does not have such a breakage. It looks good.
One minor comment (not worth a re-roll): I personally found:
*option = ++opt;more confusing than:
*option = opt + 1;
Quoted 8 lines
Quoted 6 lines
The
++optplaces a higher cognitive load on the reader. As a reviewer, I had to go back and carefully reread the function to see if the side-effect of++opthad some impact which I didn't notice on the first readthrough. The simpleropt + 1does not have a side-effect, thus is easier to reason about (and doesn't require me to re-study the function when I encounter it).That makes the two of us ... thanks.
It seems like the score is 2-0.
I guess I'm going with winning side.
Will be improved in next version.
Thanks,
Hariom
Re: [PATCH 1/2] t6300: unify %(trailers) and %(contents:trailers) tests
In reply to Junio C HamanoHi,
Quoted 17 lines · Junio C Hamano
Quoted 14 lines · Hariom Verma via GitGitGadget
t/t6300-for-each-ref.sh +1
-8@@ -839,14 +818,7 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' fatal: unknown %(trailers) argument: unsupported EOF test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual && - test_i18ncmp expect actual -' - -test_expect_success '%(contents:trailers) rejects unknown trailers arguments' ' - # error message cannot be checked under i18n - cat >expect <<-EOF && - fatal: unknown %(trailers) argument: unsupported - EOF + test_i18ncmp expect actual && test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual &&
Quoted 8 lines
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 824
Quoted 2 lines
t/t6300-for-each-ref.sh +0
-0test_i18ncmp expect actual 'Doesn't this highlight a small bug, where an end-user request for an unknown %(contents:trailers:unsupported) is flagged as an error about %(trailers)? Is it OK because we expect that users who use the longer %(contents:trailers) to know that it is a synonym for %(trailers) and the latter is the official way to write it?
Maybe.
Another way of thinking is...
'trailers' is an argument to 'contents', likewise here 'unsupported' is an argument to trailers.
Technically, the error message is correct.
Again, I think views on this are highly subjective.
Thanks,
Hariom
v2 cover Fix trailers atom bug and improved tests
In reply to Hariom Verma via GitGitGadgetCurrently, there exists a bug in 'contents' atom. It does not show any error if used with modifier 'trailers' and semicolon is missing before trailers arguments. This small patch series is focused on fixing that bug and also unified 'trailers' and 'contents:trailers' tests. Thus, removed duplicate code from t6300 and made tests more compact.
Hariom Verma (2):
t6300: unify %(trailers) and %(contents:trailers) tests
ref-filter: 'contents:trailers' show error if : is missing
ref-filter.c | 21 +++++++++++++--- t/t6300-for-each-ref.sh | 55 ++++++++++++++--------------------------- 2 files changed, 36 insertions(+), 40 deletions(-)
base-commit: 675a4aaf3b226c0089108221b96559e0baae5de9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-707%2Fharry-hov%2Ffix-trailers-atom-bug-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-707/harry-hov/fix-trailers-atom-bug-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/707
Range-diff vs v1:
1: bd0bb8d0ef ! 1: 4816aa3cfa t6300: unify %(trailers) and %(contents:trailers) tests
@@ t/t6300-for-each-ref.sh: test_expect_success 'set up trailers for next test' '
-
-test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' '
+ git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual &&
-+ git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse &&
-+ test_cmp actual reverse &&
+ test_cmp expect actual &&
++ git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >actual &&
++ test_cmp actual actual &&
git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual &&
- git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse &&
- test_cmp actual reverse &&
+- git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse &&
+- test_cmp actual reverse &&
- {
- grep -v patch.description <trailers | unfold &&
- echo
- } >expect &&
- test_cmp expect actual
+- test_cmp expect actual
++ test_cmp expect actual &&
++ git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >actual &&
++ test_cmp actual actual
'
+ test_expect_success '%(trailers) rejects unknown trailers arguments' '
@@ t/t6300-for-each-ref.sh: test_expect_success '%(trailers) rejects unknown trailers arguments' '
fatal: unknown %(trailers) argument: unsupported
EOF
2: 7daf9335a5 ! 2: 39aa46bce7 ref-filter: 'contents:trailers' show error if `:` is missing
@@ ref-filter.c: static int trailers_atom_parser(const struct ref_format *format, s
+ return 1;
+ }
+ else if (*opt == ':') {
-+ *option = ++opt;
++ *option = opt + 1;
+ return 1;
+ }
+ }Signature · 1 line
gitgitgadget
PATCH v2 1/2 t6300: unify %(trailers) and %(contents:trailers) tests
From: Hariom Verma <[email protected]>
Currently, there are different tests for testing %(trailers) and %(contents:trailers) causing redundant copy.
Its time to get rid of duplicate code.
--- t/t6300-for-each-ref.sh | 56 +++++++++++------------------------------ 1 file changed, 14 insertions(+), 42 deletions(-)
t/t6300-for-each-ref.sh +14 -42
@@ -776,61 +776,40 @@ test_expect_success 'set up trailers for next test' ' ' test_expect_success '%(trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && { unfold <trailers echo } >expect && + git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && { grep -v patch.description <trailers && echo } >expect && + git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) and %(trailers:unfold) work together' ' - git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && { grep -v patch.description <trailers | unfold && echo } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && - { - unfold <trailers - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && - { - grep -v patch.description <trailers && - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' ' + git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >actual && + test_cmp actual actual && git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && - { - grep -v patch.description <trailers | unfold && - echo - } >expect && - test_cmp expect actual + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >actual && + test_cmp actual actual ' test_expect_success '%(trailers) rejects unknown trailers arguments' '
@@ -839,14 +818,7 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' fatal: unknown %(trailers) argument: unsupported EOF test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual && - test_i18ncmp expect actual -' - -test_expect_success '%(contents:trailers) rejects unknown trailers arguments' ' - # error message cannot be checked under i18n - cat >expect <<-EOF && - fatal: unknown %(trailers) argument: unsupported - EOF + test_i18ncmp expect actual && test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual && test_i18ncmp expect actual '
Signature · 1 line
gitgitgadget
PATCH v2 2/2 ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Hariom Verma via GitGitGadgetFrom: Hariom Verma <[email protected]>
The 'contents' atom does not show any error if used with 'trailers' atom and semicolon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
It is definitely not an expected behavior.
Let's fix this bug.
--- ref-filter.c | 21 ++++++++++++++++++--- t/t6300-for-each-ref.sh | 9 +++++++++ 2 files changed, 27 insertions(+), 3 deletions(-)
ref-filter.c +18 -3
@@ -332,6 +332,22 @@ static int trailers_atom_parser(const struct ref_format *format, struct used_atoreturn 0 ; } +static int check_format_field (const char *arg,const char *field,const char **option) +{ +const char *opt; +if (skip_prefix (arg, field, &opt)) { +if (*opt =='\0' ) { + *option =NULL ; +return 1 ; + } +else if (*opt ==':' ) { + *option = opt +1 ; +return 1 ; + } + } +return 0 ; +} +static int contents_atom_parser (const struct ref_format *format,struct used_atom *atom,const char *arg,struct strbuf *err) {
@@ -345,9 +361,8 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato atom->u.contents.option =C_SIG ; else if (!strcmp(arg, "subject")) atom->u.contents.option =C_SUB ; - else if (skip_prefix(arg, "trailers", &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) + else if (check_format_field(arg, "trailers", &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option =C_LINES ;
t/t6300-for-each-ref.sh +9 -0
@@ -823,6 +823,15 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' test_i18ncmp expect actual ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' ' + # error message cannot be checked under i18n + cat >expect <<-EOF && + fatal: unrecognized %(contents) argument: trailersonly + EOF + test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual && + test_i18ncmp expect actual +' + test_expect_success 'basic atom: head contents:trailers' ' git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual && sanitize_pgp <actual >actual.clean &&
Signature · 1 line
gitgitgadget
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 2 lines · Hariom Verma via GitGitGadget
The 'contents' atom does not show any error if used with 'trailers' atom and semicolon is missing before trailers arguments.
Do you mean s/semicolon/colon/ ?
Quoted 15 lines
e.g %(contents:trailersonly) works, while it shouldn't.
It is definitely not an expected behavior.
Let's fix this bug.
Signed-off-by Hariom Verma <[email protected]>---
ref-filter.c +5
-0@@ -332,6 +332,22 @@ static int trailers_atom_parser(const struct ref_format *format, struct used_ato +static int check_format_field (const char *arg,const char *field,const char **option) +{ +const char *opt; +if (skip_prefix (arg, field, &opt)) { +if (*opt =='\0' ) {
ref-filter.c static int trailers_atom_parser(const struct ref_format *format, struct used_ato · line 346
Quoted 10 lines
ref-filter.c +10
-0+ *option =NULL ; +return 1 ; + } +else if (*opt ==':' ) { + *option = opt +1 ; +return 1 ; + } + } +return 0 ; +}
Not necessarily worth a re-roll, but rather than introducing all the above new code...
ref-filter.c static int contents_atom_parser(const struct ref_format *format, struct used_ato · line 363
Quoted 7 lines
ref-filter.c +2
-3@@ -345,9 +361,8 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato -else if (skip_prefix (arg,"trailers" , &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) +else if (check_format_field (arg,"trailers" , &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ;
...an alternative would have been something like:
else if (!strcmp(arg, "trailers")) {
if (trailers_atom_parser(format, atom, NULL, err))
return -1;
} else if (skip_prefix(arg, "trailers:", &arg)) {
if (trailers_atom_parser(format, atom, arg, err))
return -1;
}which is quite simple to reason about (though has the cost of a tiny bit of duplication).
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 823
Quoted 3 lines
t/t6300-for-each-ref.sh +1
-0@@ -823,6 +823,15 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' '
s/semicolon/colon/
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 827
Quoted 1 line
t/t6300-for-each-ref.sh +1
-0+ # error message cannot be checked under i18n
What is this comment about? I realize that you copied it from other nearby tests, but I find that it muddies rather than clarifies.
Quoted 6 lines
t/t6300-for-each-ref.sh +6
-0+ cat >expect <<-EOF && + fatal: unrecognized %(contents) argument: trailersonly + EOF + test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual && + test_i18ncmp expect actual +'
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 10 lines · Eric Sunshine
...an alternative would have been something like:
else if (!strcmp(arg, "trailers")) { if (trailers_atom_parser(format, atom, NULL, err)) return -1; } else if (skip_prefix(arg, "trailers:", &arg)) { if (trailers_atom_parser(format, atom, arg, err)) return -1; }
Quoted 2 lines
which is quite simple to reason about (though has the cost of a tiny bit of duplication).
Yeah, that looks quite simple and straight-forward.
Quoted 5 lines
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 823
Quoted 3 lines
t/t6300-for-each-ref.sh +1
-0@@ -823,6 +823,15 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' 's/semicolon/colon/
Definitely.
Quoted 5 lines
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 827
Quoted 2 lines
t/t6300-for-each-ref.sh +1
-0+ # error message cannot be checked under i18nWhat is this comment about? I realize that you copied it from other nearby tests, but I find that it muddies rather than clarifies.
Yup. If a patch changes test_cmp with test_i18ncmp, the above message belongs to its commit log message, but it is overkill to have it as an in-line comment in every place where test_i18ncmp gets used.
Thanks for a review.
Quoted 6 lines
Quoted 6 lines
t/t6300-for-each-ref.sh +6
-0+ cat >expect <<-EOF && + fatal: unrecognized %(contents) argument: trailersonly + EOF + test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual && + test_i18ncmp expect actual +'
PATCH v3 1/4 t6300: unify %(trailers) and %(contents:trailers) tests
In reply to Hariom Verma via GitGitGadgetFrom: Hariom Verma <[email protected]>
Currently, there are different tests for testing %(trailers) and %(contents:trailers) causing redundant copy.
Its time to get rid of duplicate code.
--- t/t6300-for-each-ref.sh | 56 +++++++++++------------------------------ 1 file changed, 14 insertions(+), 42 deletions(-)
t/t6300-for-each-ref.sh +14 -42
@@ -776,61 +776,40 @@ test_expect_success 'set up trailers for next test' ' ' test_expect_success '%(trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && { unfold <trailers echo } >expect && + git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && { grep -v patch.description <trailers && echo } >expect && + git for-each-ref --format="%(trailers:only)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && test_cmp expect actual ' test_expect_success '%(trailers:only) and %(trailers:unfold) work together' ' - git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && { grep -v patch.description <trailers | unfold && echo } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:unfold) unfolds trailers' ' - git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual && - { - unfold <trailers - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' ' - git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual && - { - grep -v patch.description <trailers && - echo - } >expect && - test_cmp expect actual -' - -test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' ' + git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual && + test_cmp expect actual && + git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >actual && + test_cmp actual actual && git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual && - git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse && - test_cmp actual reverse && - { - grep -v patch.description <trailers | unfold && - echo - } >expect && - test_cmp expect actual + test_cmp expect actual && + git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >actual && + test_cmp actual actual ' test_expect_success '%(trailers) rejects unknown trailers arguments' '
@@ -839,14 +818,7 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' fatal: unknown %(trailers) argument: unsupported EOF test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual && - test_i18ncmp expect actual -' - -test_expect_success '%(contents:trailers) rejects unknown trailers arguments' ' - # error message cannot be checked under i18n - cat >expect <<-EOF && - fatal: unknown %(trailers) argument: unsupported - EOF + test_i18ncmp expect actual && test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual && test_i18ncmp expect actual '
Signature · 1 line
gitgitgadget
v3 cover Fix trailers atom bug and improved tests
In reply to Hariom Verma via GitGitGadgetCurrently, there exists a bug in 'contents' atom. It does not show any error if used with modifier 'trailers' and semicolon is missing before trailers arguments. This small patch series is focused on fixing that bug and also unified 'trailers' and 'contents:trailers' tests. Thus, removed duplicate code from t6300 and made tests more compact.
Change log since v2:
* Used simplified logic as per suggested by Eric (here
https://public-inbox.org/git/CAPig+cRxCvHG70Nd00zBxYFuecu6+Z6uDP8ooN3rx9vPagoYBA@mail.gmail.com/
)
* Unified trailer formatting logic for pretty.c and ref-filter.c
Hariom Verma (4):
t6300: unify %(trailers) and %(contents:trailers) tests
ref-filter: 'contents:trailers' show error if : is missing pretty.c: refactor trailer logic to format_set_trailers_options()
ref-filter: using pretty.c logic for trailers
Documentation/git-for-each-ref.txt | 36 ++++++-- Hariom Verma via GitGitGadget | 0 pretty.c | 83 +++++++++++------- pretty.h | 11 +++ ref-filter.c | 43 +++++----- t/t6300-for-each-ref.sh | 133 ++++++++++++++++++++++------- 6 files changed, 219 insertions(+), 87 deletions(-) create mode 100644 Hariom Verma via GitGitGadget
base-commit: 675a4aaf3b226c0089108221b96559e0baae5de9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-707%2Fharry-hov%2Ffix-trailers-atom-bug-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-707/harry-hov/fix-trailers-atom-bug-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/707
Range-diff vs v2:
1: 4816aa3cfa = 1: 383476b177 t6300: unify %(trailers) and %(contents:trailers) tests 2: 39aa46bce7 ! 2: 659b9835dc ref-filter: 'contents:trailers' show error if `:` is missing
@@ Commit message
ref-filter: 'contents:trailers' show error if : is missing
The 'contents' atom does not show any error if used with 'trailers'
- atom and semicolon is missing before trailers arguments.
+ atom and colon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
@@ Commit message
Let's fix this bug.
+ Acked-by: Eric Sunshine <[email protected]>
## ref-filter.c ##
-@@ ref-filter.c: static int trailers_atom_parser(const struct ref_format *format, struct used_ato
- return 0;
- }
-
-+static int check_format_field(const char *arg, const char *field, const char **option) -+{
-+ const char *opt;
-+ if (skip_prefix(arg, field, &opt)) {
-+ if (*opt == '\0') {
-+ *option = NULL;
-+ return 1;
-+ }
-+ else if (*opt == ':') {
-+ *option = opt + 1;
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
- static int contents_atom_parser(const struct ref_format *format, struct used_atom *atom,
- const char *arg, struct strbuf *err)
- {
@@ ref-filter.c: static int contents_atom_parser(const struct ref_format *format, struct used_ato
atom->u.contents.option = C_SIG;
else if (!strcmp(arg, "subject"))
@@ ref-filter.c: static int contents_atom_parser(const struct ref_format *format, s
- else if (skip_prefix(arg, "trailers", &arg)) {
- skip_prefix(arg, ":", &arg);
- if (trailers_atom_parser(format, atom, *arg ? arg : NULL, err))
-+ else if (check_format_field(arg, "trailers", &arg)) {
++ else if (!strcmp(arg, "trailers")) {
++ if (trailers_atom_parser(format, atom, NULL, err))
++ return -1;
++ } else if (skip_prefix(arg, "trailers:", &arg)) {
+ if (trailers_atom_parser(format, atom, arg, err))
return -1;
} else if (skip_prefix(arg, "lines=", &arg)) {
@@ t/t6300-for-each-ref.sh: test_expect_success '%(trailers) rejects unknown traile
'
+test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' '
-+ # error message cannot be checked under i18n
+ cat >expect <<-EOF &&
+ fatal: unrecognized %(contents) argument: trailersonly
+ EOF
-: ---------- > 3: 712ab9aacf pretty.c: refactor trailer logic to `format_set_trailers_options()` -: ---------- > 4: d491be5d10 ref-filter: using pretty.c logic for trailers
Signature · 1 line
gitgitgadget
PATCH v3 2/4 ref-filter: 'contents:trailers' show error if `:` is missing
From: Hariom Verma <[email protected]>
The 'contents' atom does not show any error if used with 'trailers' atom and colon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
It is definitely not an expected behavior.
Let's fix this bug.
--- ref-filter.c | 8 +++++--- t/t6300-for-each-ref.sh | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-)
ref-filter.c +5 -3
@@ -345,9 +345,11 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato atom->u.contents.option =C_SIG ; else if (!strcmp(arg, "subject")) atom->u.contents.option =C_SUB ; - else if (skip_prefix(arg, "trailers", &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) + else if (!strcmp(arg, "trailers")) { +if (trailers_atom_parser (format, atom,NULL , err)) +return -1 ; + } else if (skip_prefix(arg, "trailers:", &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option =C_LINES ;
t/t6300-for-each-ref.sh +8 -0
@@ -823,6 +823,14 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' test_i18ncmp expect actual ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' ' + cat >expect <<-EOF && + fatal: unrecognized %(contents) argument: trailersonly + EOF + test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual && + test_i18ncmp expect actual +' + test_expect_success 'basic atom: head contents:trailers' ' git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual && sanitize_pgp <actual >actual.clean &&
Signature · 1 line
gitgitgadget
PATCH v3 4/4 ref-filter: using pretty.c logic for trailers
In reply to Hariom Verma via GitGitGadgetFrom: Hariom Verma <[email protected]>
Now, ref-filter is using pretty.c logic for setting trailer options.
New to ref-filter:
:key=<K> - only show trailers with specified key. :valueonly[=val] - only show the value part. :separator=<SEP> - inserted between trailer lines
Enhancement to existing options(now can take value and its optional):
:only[=val]
:unfold[=val]
'val' can be: true, on, yes or false, off, no.
--- Documentation/git-for-each-ref.txt | 36 +++++++-- ref-filter.c | 35 ++++----- t/t6300-for-each-ref.sh | 115 +++++++++++++++++++++++++---- 3 files changed, 151 insertions(+), 35 deletions(-)
Documentation/git-for-each-ref.txt +31 -5
@@ -254,11 +254,37 @@ contents:lines=N:: The first `N` lines of the message. Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1] -are obtained as `trailers` (or by using the historical alias -`contents:trailers`). Non-trailer lines from the trailer block can be omitted -with `trailers:only`. Whitespace-continuations can be removed from trailers so -that each trailer appears on a line by itself with its full content with -`trailers:unfold`. Both can be used together as `trailers:unfold,only`. +are obtained as `trailers[:options]` (or by using the historical alias +`contents:trailers[:options]`). Valid [:option] are: +** 'key=<K>': only show trailers with specified key. Matching is done + case-insensitively and trailing colon is optional. If option is + given multiple times trailer lines matching any of the keys are + shown. This option automatically enables the `only` option so that + non-trailer lines in the trailer block are hidden. If that is not + desired it can be disabled with `only=false`. E.g., + `%(trailers:key=Reviewed-by)` shows trailer lines with key + `Reviewed-by`. +** 'only[=val]': select whether non-trailer lines from the trailer + block should be included. The `only` keyword may optionally be + followed by an equal sign and one of `true`, `on`, `yes` to omit or + `false`, `off`, `no` to show the non-trailer lines. If option is + given without value it is enabled. If given multiple times the last + value is used. +** 'separator=<SEP>': specify a separator inserted between trailer + lines. When this option is not given each trailer line is + terminated with a line feed character. The string SEP may contain + the literal formatting codes described above. To use comma as + separator one must use `%x2C` as it would otherwise be parsed as + next option. If separator option is given multiple times only the + last one is used. E.g., `%(trailers:key=Ticket,separator=%x2C )` + shows all trailer lines whose key is "Ticket" separated by a comma + and a space. +** 'unfold[=val]': make it behave as if interpret-trailer's `--unfold` + option was given. In same way as to for `only` it can be followed + by an equal sign and explicit value. E.g., + `%(trailers:only,unfold=true)` unfolds and shows all trailer lines. +** 'valueonly[=val]': skip over the key part of the trailer line and only + show the value part. Also this optionally allows explicit value. For sorting purposes, fields with numeric values sort in numeric order (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).
ref-filter.c +18 -17
@@ -67,6 +67,11 @@ struct refname_atom {int lstrip, rstrip; }; +struct ref_trailer_buf { +struct string_list filter_list; +struct strbuf sepbuf; +} ref_trailer_buf; + static struct expand_data { struct object_id oid; enum object_type type;
@@ -307,28 +312,24 @@ static int subject_atom_parser(const struct ref_format *format, struct used_atomstatic int trailers_atom_parser (const struct ref_format *format,struct used_atom *atom,const char *arg,struct strbuf *err) { -struct string_list params =STRING_LIST_INIT_DUP ; -int i; - atom->u.contents.trailer_opts.no_divider =1 ; -if (arg) { -string_list_split (¶ms, arg,',' ,-1 ); -for (i =0 ; i < params.nr; i++) { -const char *s = params.items[i].string; -if (!strcmp (s,"unfold" )) - atom->u.contents.trailer_opts.unfold =1 ; -else if (!strcmp (s,"only" )) - atom->u.contents.trailer_opts.only_trailers =1 ; -else { -strbuf_addf (err,_ ("unknown %%(trailers) argument: %s" ), s); -string_list_clear (¶ms,0 ); -return -1 ; - } +const char *argbuf =xstrfmt ("%s)" , arg); +const char *err_arg =NULL ; + +if (format_set_trailers_options (&atom->u.contents.trailer_opts, + &ref_trailer_buf.filter_list, + &ref_trailer_buf.sepbuf, + &argbuf, &err_arg)) { +if (!err_arg) +strbuf_addf (err,_ ("expected %%(trailers:key=<value>)" )); +else +strbuf_addf (err,_ ("unknown %%(trailers) argument: %s" ), err_arg); +free ((char *)err_arg); +return -1 ; } } atom->u.contents.option =C_TRAILERS ; -string_list_clear (¶ms,0 );return 0 ; }
t/t6300-for-each-ref.sh +102 -13
133 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH v3 3/4 pretty.c: refactor trailer logic to `format_set_trailers_options()`
In reply to Hariom Verma via GitGitGadgetFrom: Hariom Verma <[email protected]>
Refactored trailers formatting logic inside pretty.c to a new function format_set_trailers_options().
Also, introduced a code to get invalid trailer arguments. As we would like to use same logic in ref-filter, it's nice to get invalid trailer argument. This will allow us to print accurate error message, while using format_set_trailers_options() in ref-filter.
--- Hariom Verma via GitGitGadget | 0 pretty.c | 83 ++++++++++++++++++++++------------- pretty.h | 11 +++++ 3 files changed, 64 insertions(+), 30 deletions(-) create mode 100644 Hariom Verma via GitGitGadget
Hariom Verma via GitGitGadget new file +0 -0
pretty.c +53 -30
106 lines not on this page · raw message
pretty.h +11 -0
@@ -6,6 +6,7 @@struct commit ;struct strbuf ; +struct process_trailer_options ;/* Commit formats */ enum cmit_fmt {
@@ -139,4 +140,14 @@ const char *format_subject(struct strbuf *sb, const char *msg,/* Check if "cmit_fmt" will produce an empty output. */ int commit_format_is_empty (enum cmit_fmt ); +/* +* Set values of fields in "struct process_trailer_options" +* according to trailers arguments. +*/ +int format_set_trailers_options (struct process_trailer_options *opts, +struct string_list *filter_list, +struct strbuf *sepbuf, +const char **arg, +const char **err); +#endif /* PRETTY_H */
Signature · 1 line
gitgitgadget
Re: [PATCH v3 2/4] ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Hariom Verma via GitGitGadgetQuoted 10 lines · Hariom Verma via GitGitGadget
The 'contents' atom does not show any error if used with 'trailers' atom and colon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
It is definitely not an expected behavior.
Let's fix this bug.
Acked-by Eric Sunshine <[email protected]>
I didn't "ack" this patch. If you think some sort of attribution with my name is warranted, then a "Helped-by:" would be more appropriate.
ref-filter.c static int contents_atom_parser(const struct ref_format *format, struct used_ato · line 350
Quoted 13 lines
Signed-off-by Hariom Verma <[email protected]>---
ref-filter.c +5
-3@@ -345,9 +345,11 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato -else if (skip_prefix (arg,"trailers" , &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) +else if (!strcmp (arg,"trailers" )) { +if (trailers_atom_parser (format, atom,NULL , err)) +return -1 ; + }else if (skip_prefix (arg,"trailers:" , &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ;
This looks better and easier to reason about (but I may be biased in thinking so).
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 823
Quoted 3 lines
t/t6300-for-each-ref.sh +1
-0@@ -823,6 +823,14 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' '
This still needs a s/semicolon/colon/ (mentioned in my previous review).
Re: [PATCH v3 2/4] ref-filter: 'contents:trailers' show error if `:` is missing
Hi Eric,
Quoted 8 lines · Eric Sunshine
Quoted 5 lines · Hariom Verma via GitGitGadget
The 'contents' atom does not show any error if used with 'trailers' atom and colon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
Quoted 8 lines
Quoted 5 lines
It is definitely not an expected behavior.
Let's fix this bug.
Acked-by Eric Sunshine <[email protected]>I didn't "ack" this patch. If you think some sort of attribution with my name is warranted, then a "Helped-by:" would be more appropriate.
Sorry about that. Fixing in the next version.
Quoted 8 lines
Quoted 8 lines
Signed-off-by Hariom Verma <[email protected]>---
ref-filter.c +1
-3@@ -345,9 +345,11 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato -else if (skip_prefix (arg,"trailers" , &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) +else if (!strcmp (arg,"trailers" )) {
Quoted 8 lines
ref-filter.c static int contents_atom_parser(const struct ref_format *format, struct used_ato · line 353
Quoted 5 lines
ref-filter.c +4
-0+if (trailers_atom_parser (format, atom,NULL , err)) +return -1 ; + }else if (skip_prefix (arg,"trailers:" , &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ;This looks better and easier to reason about (but I may be biased in thinking so).
Thanks for the review.
Quoted 5 lines
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 823
Quoted 3 lines
t/t6300-for-each-ref.sh +1
-0@@ -823,6 +823,14 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' 'This still needs a s/semicolon/colon/ (mentioned in my previous review).
Sorry, I missed that too.
Thanks,
Hariom
Re: [PATCH v3 2/4] ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Eric SunshineQuoted 7 lines · Eric Sunshine
Quoted 5 lines · Hariom Verma via GitGitGadget
The 'contents' atom does not show any error if used with 'trailers' atom and colon is missing before trailers arguments.
e.g %(contents:trailersonly) works, while it shouldn't.
Quoted 8 lines
Quoted 5 lines
It is definitely not an expected behavior.
Let's fix this bug.
Acked-by Eric Sunshine <[email protected]>I didn't "ack" this patch. If you think some sort of attribution with my name is warranted, then a "Helped-by:" would be more appropriate.
Yes, I did exactly that after moving it just above Hariom's sign-off.
Quoted 17 lines
ref-filter.c static int contents_atom_parser(const struct ref_format *format, struct used_ato · line 350
Quoted 13 lines
Signed-off-by Hariom Verma <[email protected]>---
ref-filter.c +5
-3@@ -345,9 +345,11 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato -else if (skip_prefix (arg,"trailers" , &arg)) { -skip_prefix (arg,":" , &arg); -if (trailers_atom_parser (format, atom, *arg ? arg :NULL , err)) +else if (!strcmp (arg,"trailers" )) { +if (trailers_atom_parser (format, atom,NULL , err)) +return -1 ; + }else if (skip_prefix (arg,"trailers:" , &arg)) { +if (trailers_atom_parser (format, atom, arg, err))return -1 ;This looks better and easier to reason about (but I may be biased in thinking so).
Quoted 5 lines
t/t6300-for-each-ref.sh test_expect_success '%(trailers) rejects unknown trailers arguments' ' · line 823
Quoted 3 lines
t/t6300-for-each-ref.sh +1
-0@@ -823,6 +823,14 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' ' +test_expect_success 'if arguments, %(contents:trailers) shows error if semicolon is missing' 'This still needs a s/semicolon/colon/ (mentioned in my previous review).
Yup. Tweaked while queueing.
Thanks always for sharp eyes.
Quoted 5 lines · Hariom Verma via GitGitGadget
Currently, there exists a bug in 'contents' atom. It does not show any error if used with modifier 'trailers' and semicolon is missing before trailers arguments. This small patch series is focused on fixing that bug and also unified 'trailers' and 'contents:trailers' tests. Thus, removed duplicate code from t6300 and made tests more compact.
I think we should focus on completing the first two patches and send them to 'next' down to 'master', before extending the scope of the topic by piling more patches that do not have to be part of the topic. Let's take the other two separately from the first two.
Thanks.
Hi,
Quoted 9 lines · Junio C Hamano
Quoted 5 lines · Hariom Verma via GitGitGadget
Currently, there exists a bug in 'contents' atom. It does not show any error if used with modifier 'trailers' and semicolon is missing before trailers arguments. This small patch series is focused on fixing that bug and also unified 'trailers' and 'contents:trailers' tests. Thus, removed duplicate code from t6300 and made tests more compact.
Quoted 4 lines
I think we should focus on completing the first two patches and send them to 'next' down to 'master', before extending the scope of the topic by piling more patches that do not have to be part of the topic. Let's take the other two separately from the first two.
Sure.
Thanks,
Hariom
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Junio C HamanoHi,
Quoted 13 lines · Junio C Hamano
Quoted 10 lines · Eric Sunshine
...an alternative would have been something like:
else if (!strcmp(arg, "trailers")) { if (trailers_atom_parser(format, atom, NULL, err)) return -1; } else if (skip_prefix(arg, "trailers:", &arg)) { if (trailers_atom_parser(format, atom, arg, err)) return -1; }
Quoted 4 lines
Quoted 2 lines
which is quite simple to reason about (though has the cost of a tiny bit of duplication).
Yeah, that looks quite simple and straight-forward.
No doubt, it looks good for "contents:trailers".
What if In future we would like to expand functionalities of other 'contents' options?
Recently, I sent a patch series "Improvements to ref-filter"[1]. A patch in this patch series introduced "sanitize" modifier to "subject" atom. i.e "%(subject:sanitize)".
What if in the future we also want "%(contents:subject:sanitize)" to work? We can duplicate code again. Something like:
```
} else if (!strcmp(arg, "trailers")) {
if (trailers_atom_parser(format, atom, NULL, err))
return -1;
} else if (skip_prefix(arg, "trailers:", &arg)) {
if (trailers_atom_parser(format, atom, arg, err))
return -1;
} else if (!strcmp(arg, "subject")) {
if (subject_atom_parser(format, atom, NULL, err))
return -1;
} else if (skip_prefix(arg, "subject:", &arg)) {
if (subject_atom_parser(format, atom, arg, err))
return -1;
}
```OR
We can just simply use helper. Something like:
```
else if (check_format_field(arg, "subject", &arg)) {
if (subject_atom_parser(format, atom, arg, err))
return -1;
} else if (check_format_field(arg, "trailers", &arg)) {
if (trailers_atom_parser(format, atom, arg, err))
return -1;
```We can use this helper any number of times, whenever there is a need.
Sorry, I missed saying this earlier. But I don't prefer duplicating the code here.
Thanks,
Hariom
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 21 lines · Hariom verma
Quoted 11 lines · Junio C Hamano
Quoted 10 lines · Eric Sunshine
...an alternative would have been something like:
else if (!strcmp(arg, "trailers")) { if (trailers_atom_parser(format, atom, NULL, err)) return -1; } else if (skip_prefix(arg, "trailers:", &arg)) { if (trailers_atom_parser(format, atom, arg, err)) return -1; }Quoted 4 lines
Quoted 2 lines
which is quite simple to reason about (though has the cost of a tiny bit of duplication).
Yeah, that looks quite simple and straight-forward.
Recently, I sent a patch series "Improvements to ref-filter"[1]. A patch in this patch series introduced "sanitize" modifier to "subject" atom. i.e "%(subject:sanitize)".
Quoted 5 lines
What if in the future we also want "%(contents:subject:sanitize)" to work? We can use this helper any number of times, whenever there is a need.
Sorry, I missed saying this earlier. But I don't prefer duplicating the code here.
Pushing back on a reviewer suggestion is fine. Explaining the reason for your position -- as you do here -- helps reviewers understand why you feel the way you do. My review suggestion about making it easier to reason about the code while avoiding a brand new function, at the cost of a minor amount of duplication, was made in the context of this one-off case in which the function increased cognitive load and was used just once (not knowing that you envisioned future callers). If you expect the new function to be re-used by upcoming changes, then that may be a good reason to keep it. Stating so in the commit message will help reviewers see beyond the immediate patch or patch series.
Aside from a couple minor style violations[1,2], I don't particularly oppose the helper function, though I have a quibble with the name check_format_field(), which I don't find helpful, and which (at least for me) increases the cognitive load. The increased cognitive load, I think, comes not only from the function name not spelling out what the function actually does, but also because the function is dual-purpose:
it's both checking that the argument matches a particular token ("trailers", in this case) and extracting the sub-argument. Perhaps naming it match_and_extract_subarg() or something similar would help, though that's a mouthful.
But the observation about the function being dual-purpose (thus potentially confusing) brings up other questions. For instance, is it too special-purpose? If you foresee more callers in the future with multiple-token arguments such as %(content:subject:sanitize), should the function provide more assistance by splitting out each of the sub-arguments rather than stopping at the first? Taking that even further, a generalized helper for "splitting" arguments like that might be useful at the top-level of contents_atom_parser() too, rather than only for specific arguments, such as "trailers". Of course, this may all be way too ambitious for this little bug fix series or even for whatever upcoming changes you're planning, thus not worth pursuing.
As for the helper's implementation, I might have written it like this:
static int check_format_field(...)
{
const char *opt
if (!strcmp(arg, field))
*option = NULL;
else if (skip_prefix(arg, field, opt) && *opt == ':')
*option = opt + 1;
else
return 0;
return 1;
}which is more compact and closer to what I suggested earlier for avoiding the helper function in the first place. But, of course, programming is quite subjective, and you may find your implementation easier to reason about. Plus, your version has the benefit of being slightly more optimal since it avoids an extra string scan, although that probably is mostly immaterial considering that contents_atom_parser() itself contains a long chain of potentially sub-optimal strcmp() and skip_prefix() calls.
Footnotes
[1]: use if (!*opt) rather than if (*opt == '\0') [2]: cuddle the closing brace and else on the same line like this:
`} else if (...) {`Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Hi,
Quoted 29 lines · Eric Sunshine
Quoted 21 lines · Hariom verma
Quoted 11 lines · Junio C Hamano
Quoted 10 lines · Eric Sunshine
...an alternative would have been something like:
else if (!strcmp(arg, "trailers")) { if (trailers_atom_parser(format, atom, NULL, err)) return -1; } else if (skip_prefix(arg, "trailers:", &arg)) { if (trailers_atom_parser(format, atom, arg, err)) return -1; }Quoted 4 lines
Quoted 2 lines
which is quite simple to reason about (though has the cost of a tiny bit of duplication).
Yeah, that looks quite simple and straight-forward.
Recently, I sent a patch series "Improvements to ref-filter"[1]. A patch in this patch series introduced "sanitize" modifier to "subject" atom. i.e "%(subject:sanitize)".
Quoted 5 lines
What if in the future we also want "%(contents:subject:sanitize)" to work? We can use this helper any number of times, whenever there is a need.
Sorry, I missed saying this earlier. But I don't prefer duplicating the code here.
Quoted 10 lines
Pushing back on a reviewer suggestion is fine. Explaining the reason for your position -- as you do here -- helps reviewers understand why you feel the way you do. My review suggestion about making it easier to reason about the code while avoiding a brand new function, at the cost of a minor amount of duplication, was made in the context of this one-off case in which the function increased cognitive load and was used just once (not knowing that you envisioned future callers). If you expect the new function to be re-used by upcoming changes, then that may be a good reason to keep it. Stating so in the commit message will help reviewers see beyond the immediate patch or patch series.
Yeah. I should have mentioned this in the commit message.
Quoted 10 lines
Aside from a couple minor style violations[1,2], I don't particularly oppose the helper function, though I have a quibble with the name
check_format_field(), which I don't find helpful, and which (at least for me) increases the cognitive load. The increased cognitive load, I think, comes not only from the function name not spelling out what the function actually does, but also because the function is dual-purpose:
it's both checking that the argument matches a particular token ("trailers", in this case) and extracting the sub-argument. Perhaps naming itmatch_and_extract_subarg()or something similar would help, though that's a mouthful.
I will fix those violations.
Also, "match_and_extract_subarg()" looks good to me.
Quoted 4 lines
But the observation about the function being dual-purpose (thus potentially confusing) brings up other questions. For instance, is it too special-purpose? If you foresee more callers in the future with multiple-token arguments such as
%(content:subject:sanitize), should
Quoted 8 lines
the function provide more assistance by splitting out each of the sub-arguments rather than stopping at the first? Taking that even further, a generalized helper for "splitting" arguments like that might be useful at the top-level of
contents_atom_parser()too, rather than only for specific arguments, such as "trailers". Of course, this may all be way too ambitious for this little bug fix series or even for whatever upcoming changes you're planning, thus not worth pursuing.
Splitting sub-arguments is done at "<atomname>_atom_parser()". If you mean pre-splitting every argument...
something like: ['contents', 'subject', 'sanitize'] for %(content:subject:sanitize) in contents_atom_parser() ? I'm not able to see how it can be useful.
Sorry, If I got your concerned wrong.
Quoted 14 lines
As for the helper's implementation, I might have written it like this:
static int check_format_field(...) { const char *opt if (!strcmp(arg, field)) *option = NULL; else if (skip_prefix(arg, field, opt) && *opt == ':') *option = opt + 1; else return 0; return 1; }
Quoted 8 lines
which is more compact and closer to what I suggested earlier for avoiding the helper function in the first place. But, of course, programming is quite subjective, and you may find your implementation easier to reason about. Plus, your version has the benefit of being slightly more optimal since it avoids an extra string scan, although that probably is mostly immaterial considering that
contents_atom_parser()itself contains a long chain of potentially sub-optimalstrcmp()andskip_prefix()calls.
"programming is quite subjective"
Yeah, I couldn't agree more.
The change you suggested looks good too. But I'm little inclined to my keeping my changes. I'm curious, what others have to say on this.
Thanks,
Hariom
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Hi,
Quoted 25 lines · Hariom verma
Quoted 13 lines · Eric Sunshine
Quoted 9 lines · Hariom verma
Recently, I sent a patch series "Improvements to ref-filter"[1]. A patch in this patch series introduced "sanitize" modifier to "subject" atom. i.e "%(subject:sanitize)".
What if in the future we also want "%(contents:subject:sanitize)" to work? We can use this helper any number of times, whenever there is a need.
Sorry, I missed saying this earlier. But I don't prefer duplicating the code here.
Quoted 10 lines
Pushing back on a reviewer suggestion is fine. Explaining the reason for your position -- as you do here -- helps reviewers understand why you feel the way you do. My review suggestion about making it easier to reason about the code while avoiding a brand new function, at the cost of a minor amount of duplication, was made in the context of this one-off case in which the function increased cognitive load and was used just once (not knowing that you envisioned future callers). If you expect the new function to be re-used by upcoming changes, then that may be a good reason to keep it. Stating so in the commit message will help reviewers see beyond the immediate patch or patch series.
Quoted 1 line
Yeah. I should have mentioned this in the commit message.
I agree.
Quoted 11 lines
Quoted 10 lines
Aside from a couple minor style violations[1,2], I don't particularly oppose the helper function, though I have a quibble with the name
check_format_field(), which I don't find helpful, and which (at least for me) increases the cognitive load. The increased cognitive load, I think, comes not only from the function name not spelling out what the function actually does, but also because the function is dual-purpose:
it's both checking that the argument matches a particular token ("trailers", in this case) and extracting the sub-argument. Perhaps naming itmatch_and_extract_subarg()or something similar would help, though that's a mouthful.
Quoted 2 lines
I will fix those violations.
Also, "match_and_extract_subarg()" looks good to me.
I am not sure about the "subarg" part of the name. In the for-each-ref doc, names inside %(...) are called "field names", and parts after ":" are called "options". So it might be better to have "field_option" instead of "subarg" in the name.
I think we could also get rid of the "match_and_" part of the suggestion, in the same way as skip_prefix() is not called match_and_skip_prefix(). Readers can just expect that if there is no match the function will return 0.
So maybe "extract_field_option()".
Quoted 13 lines
Quoted 4 lines
But the observation about the function being dual-purpose (thus potentially confusing) brings up other questions. For instance, is it too special-purpose? If you foresee more callers in the future with multiple-token arguments such as
%(content:subject:sanitize), shouldQuoted 8 lines
the function provide more assistance by splitting out each of the sub-arguments rather than stopping at the first? Taking that even further, a generalized helper for "splitting" arguments like that might be useful at the top-level of
contents_atom_parser()too, rather than only for specific arguments, such as "trailers". Of course, this may all be way too ambitious for this little bug fix series or even for whatever upcoming changes you're planning, thus not worth pursuing.
Quoted 5 lines
Splitting sub-arguments is done at "<atomname>_atom_parser()". If you mean pre-splitting every argument...
something like: ['contents', 'subject', 'sanitize'] for%(content:subject:sanitize)incontents_atom_parser()? I'm not able to see how it can be useful.
Yeah, it seems to me that such a splitting would require a complete rewrite of the current code, so I am not sure it's an interesting way forward for now. And anyway adding extract_field_option() goes in the right direction of abstracting the parsing and making the code simpler, more efficient and likely more correct.
Quoted 25 lines
Sorry, If I got your concerned wrong.
Quoted 14 lines
As for the helper's implementation, I might have written it like this:
static int check_format_field(...) { const char *opt if (!strcmp(arg, field)) *option = NULL; else if (skip_prefix(arg, field, opt) && *opt == ':') *option = opt + 1; else return 0; return 1; }Quoted 8 lines
which is more compact and closer to what I suggested earlier for avoiding the helper function in the first place. But, of course, programming is quite subjective, and you may find your implementation easier to reason about. Plus, your version has the benefit of being slightly more optimal since it avoids an extra string scan, although that probably is mostly immaterial considering that
contents_atom_parser()itself contains a long chain of potentially sub-optimalstrcmp()andskip_prefix()calls.
Quoted 5 lines
"programming is quite subjective"
Yeah, I couldn't agree more.The change you suggested looks good too. But I'm little inclined to my keeping my changes. I'm curious, what others have to say on this.
I also prefer a slightly more optimal one even if it's a bit less compact.
Thanks,
Christian.
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
Quoted 6 lines · Christian Couder
I think we could also get rid of the "
match_and_" part of the suggestion, in the same way asskip_prefix()is not calledmatch_and_skip_prefix(). Readers can just expect that if there is no match the function will return 0.So maybe "
extract_field_option()".
If we want to hint more that it works in the way as skip_prefix(), we could call it "skip_field()".
Re: [PATCH v2 2/2] ref-filter: 'contents:trailers' show error if `:` is missing
In reply to Christian CouderHi,
Quoted 26 lines · Christian Couder
Hi,
Quoted 13 lines · Hariom verma
Quoted 10 lines · Eric Sunshine
Aside from a couple minor style violations[1,2], I don't particularly oppose the helper function, though I have a quibble with the name
check_format_field(), which I don't find helpful, and which (at least for me) increases the cognitive load. The increased cognitive load, I think, comes not only from the function name not spelling out what the function actually does, but also because the function is dual-purpose:
it's both checking that the argument matches a particular token ("trailers", in this case) and extracting the sub-argument. Perhaps naming itmatch_and_extract_subarg()or something similar would help, though that's a mouthful.Quoted 2 lines
I will fix those violations.
Also, "match_and_extract_subarg()" looks good to me.I am not sure about the "subarg" part of the name. In the for-each-ref doc, names inside %(...) are called "field names", and parts after ":" are called "options". So it might be better to have "
field_option" instead of "subarg" in the name.
Quoted 6 lines
I think we could also get rid of the "
match_and_" part of the suggestion, in the same way asskip_prefix()is not calledmatch_and_skip_prefix(). Readers can just expect that if there is no match the function will return 0.So maybe "
extract_field_option()".
Makes sense to me.
Quoted 50 lines
Quoted 13 lines
Quoted 4 lines
But the observation about the function being dual-purpose (thus potentially confusing) brings up other questions. For instance, is it too special-purpose? If you foresee more callers in the future with multiple-token arguments such as
%(content:subject:sanitize), shouldQuoted 8 lines
the function provide more assistance by splitting out each of the sub-arguments rather than stopping at the first? Taking that even further, a generalized helper for "splitting" arguments like that might be useful at the top-level of
contents_atom_parser()too, rather than only for specific arguments, such as "trailers". Of course, this may all be way too ambitious for this little bug fix series or even for whatever upcoming changes you're planning, thus not worth pursuing.Quoted 5 lines
Splitting sub-arguments is done at "<atomname>_atom_parser()". If you mean pre-splitting every argument...
something like: ['contents', 'subject', 'sanitize'] for%(content:subject:sanitize)incontents_atom_parser()? I'm not able to see how it can be useful.Yeah, it seems to me that such a splitting would require a complete rewrite of the current code, so I am not sure it's an interesting way forward for now. And anyway adding
extract_field_option()goes in the right direction of abstracting the parsing and making the code simpler, more efficient and likely more correct.Quoted 25 lines
Sorry, If I got your concerned wrong.
Quoted 22 lines
As for the helper's implementation, I might have written it like this:
static int check_format_field(...) { const char *opt if (!strcmp(arg, field)) *option = NULL; else if (skip_prefix(arg, field, opt) && *opt == ':') *option = opt + 1; else return 0; return 1; }which is more compact and closer to what I suggested earlier for avoiding the helper function in the first place. But, of course, programming is quite subjective, and you may find your implementation easier to reason about. Plus, your version has the benefit of being slightly more optimal since it avoids an extra string scan, although that probably is mostly immaterial considering that
contents_atom_parser()itself contains a long chain of potentially sub-optimalstrcmp()andskip_prefix()calls.
Quoted 7 lines
Quoted 5 lines
"programming is quite subjective"
Yeah, I couldn't agree more.The change you suggested looks good too. But I'm little inclined to my keeping my changes. I'm curious, what others have to say on this.
I also prefer a slightly more optimal one even if it's a bit less compact.
+1
Thanks,
Hariom