bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 1/2] maint.mk: Split long argument lists


From: Eric Blake
Subject: Re: [PATCH v3 1/2] maint.mk: Split long argument lists
Date: Wed, 2 Jan 2019 13:31:30 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.3.1

On 12/13/18 9:34 AM, Roman Bolshakov wrote:
> $(VC_LIST_EXCEPT) is usually expanded into arguments for a command.
> When a project contains too many, some operating systems can't pass all
> the arguments because they hit the limit of arguments. FreeBSD and macOS
> are known to have the limit of 256k of arguments.
> 
> More on the issue:
> http://lists.gnu.org/archive/html/bug-gnulib/2015-08/msg00019.html
> https://www.redhat.com/archives/libvir-list/2015-August/msg00758.html
> 
> xargs without flags can be used to limit number of arguments.

This part is fine.

> The
> default number of arguments (max-args for "-n" flag) is
> platform-specific. If argument length exceeds default value for "-s"
> flag (max-chars), xargs will feed less arguments than max-args.

This was relevant to earlier versions, but is now just fluff; I'd drop
it.  What's more, you didn't mention that we are relying on 'echo
$(long_list) | xargs' working because the shell's built-in echo does not
use exec and can therefore process a larger list than what exec
enforces.  I don't mind tweaking that on commit.

> 
> Signed-off-by: Roman Bolshakov <address@hidden>
> ---
>  top/maint.mk | 135 ++++++++++++++++++++++++++++++++-------------------
>  1 file changed, 86 insertions(+), 49 deletions(-)
> 
> diff --git a/top/maint.mk b/top/maint.mk
> index 4889ebacc..1152ad698 100644
> --- a/top/maint.mk
> +++ b/top/maint.mk
> @@ -302,32 +302,46 @@ define _sc_search_regexp
>     fi;                                                                       
> \
>                                                                       \
>     : Filter by content;                                                      
> \
> -   test -n "$$files" && test -n "$$containing"                               
> \
> -     && { files=$$(grep -l "$$containing" $$files); } || :;          \
> -   test -n "$$files" && test -n "$$non_containing"                   \
> -     && { files=$$(grep -vl "$$non_containing" $$files); } || :;     \
> +   test -n "$$files"                                                 \
> +     && test -n "$$containing"                                               
> \

It feels like extra churn to have split this line with no change to its
content, but I also don't mind keeping it split.

> +     && { files=$$(echo "$$files" | xargs grep -l "$$containing"); } \
> +     || :;                                                           \
> +   test -n "$$files"                                                 \
> +     && test -n "$$non_containing"                                   \
> +     && { files=$$(echo "$$files" | xargs grep -vl "$$non_containing"); } \
> +     || :;                                                           \
>                                                                       \
>     : Check for the construct;                                                
> \
>     if test -n "$$files"; then                                                
> \
>       if test -n "$$prohibit"; then                                   \
> -       grep $$with_grep_options $(_ignore_case) -nE "$$prohibit" $$files \
> +       echo "$$files" /dev/null                                              
> \
> +         | xargs                                                     \
> +             grep $$with_grep_options $(_ignore_case) -nE "$$prohibit"       
> \

Not quite canonical. That can cause xargs to invoke:
grep a b c
grep /dev/null

instead of the more typical:

grep /dev/null a b
grep /dev/null c

Remember, 'grep one' output differs from 'grep one two' - so the GOAL is
to ensure that grep always has at least two file, by always including
/dev/null in the list of arguments to EVERY grep invocation, rather than
only to the LAST grep invocation.

But, that said, your formulation "works" in the sense that it is
unlikely that any one single filename would push beyond exec limits, and
therefore xargs will either make a single call (no difference); or split
things so that the first call has more than one file (no /dev/null, but
since there are multiple files things work) and the second call has just
/dev/null (which will have no output, so it won't matter that grep was
called with one file instead of multiple); or split things so that the
first has more than one file, and the second has more than one file
(including /dev/null).

I'm still inclined to touch this up to use the canonical formulation:

'echo $(long_list) | xargs grep /dev/null'

rather than your formulation:

'echo $(long_list) /dev/null | xargs grep'

just so future readers don't have to revisit why yours happens to work.

>           | grep -vE "$${exclude:-^$$}"                                       
> \
> -         && { msg="$$halt" $(_sc_say_and_exit) } || :;                       
> \
> +         && { msg="$$halt" $(_sc_say_and_exit) }                     \
> +         || :;                                                               
> \

Again, this change is just churn.  I don't know that I would have done
it, but I'm also not in the mood to undo your effort.

> @@ -399,25 +413,31 @@ sc_error_exit_success:
>  # "FATAL:" should be fully upper-cased in error messages
>  # "WARNING:" should be fully upper-cased, or fully lower-cased
>  sc_error_message_warn_fatal:
> -     @grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))              \
> -         | grep -E '"Warning|"Fatal|"fatal' &&                       \
> -       { echo '$(ME): use FATAL, WARNING or warning' 1>&2;           \
> -         exit 1; } || :
> +     @$(VC_LIST_EXCEPT)                                              \
> +       | xargs grep -nEA2 '[^rp]error *\(' /dev/null                 \

For comparison to above, this conversion was canonical.

> @@ -845,9 +865,14 @@ sc_prohibit_always-defined_macros:
>         case $$(echo all: | grep -l -f - Makefile) in Makefile);; *)  \
>           echo '$(ME): skipping $@: you lack GNU grep' 1>&2; exit 0;; \
>         esac;                                                         \
> -       $(def_sym_regex) | grep -E -f - $$($(VC_LIST_EXCEPT))         \
> -         && { echo '$(ME): define the above via some gnulib .h file' \
> -               1>&2;  exit 1; } || :;                                \
> +       regex=`$(def_sym_regex)`; export regex;                       \

Using `` is odd, especially since...


> @@ -1033,7 +1065,8 @@ sc_prohibit_test_double_equal:
>  # definition of LDADD from the appropriate Makefile.am and exits 0
>  # when it contains "ICONV".
>  sc_proper_name_utf8_requires_ICONV:
> -     @progs=$$(grep -l 'proper_name_utf8 ''("' $$($(VC_LIST_EXCEPT)));\
> +     @progs=$$($(VC_LIST_EXCEPT)                                     \

...we are using $$() elsewhere.

I don't mind making those changes, if it will let me push today.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]