diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py index 99ac123ede2..060f0381bdc 100644 --- a/lib/spack/spack/cmd/__init__.py +++ b/lib/spack/spack/cmd/__init__.py @@ -726,8 +726,8 @@ def group_arguments( Arguments: args: list of arguments to split into groups max_group_size: max number of elements in any group (default 500) - prefix_length: length of any additional arguments to be passed before the groups from args; - defaults to 0 characters. + prefix_length: length of any additional arguments (including spaces) to be passed before + the groups from args; default is 0 characters max_group_length: max length of characters that if a group of args is joined by " " On unix, ths defaults to SC_ARG_MAX from sysconf. On Windows the default is the max usable for CreateProcess (32,768 chars) @@ -735,18 +735,22 @@ def group_arguments( """ if max_group_length is None: max_group_length = 32768 # default to the Windows limit - if hasattr(os, "sysconf"): - # sysconf is only on unix and returns -1 if an option isn't present - sysconf_max = os.sysconf("SC_ARG_MAX") - if sysconf_max != -1: - max_group_length = sysconf_max + if hasattr(os, "sysconf"): # sysconf is only on unix + try: + sysconf_max = os.sysconf("SC_ARG_MAX") + if sysconf_max != -1: # returns -1 if an option isn't present + max_group_length = sysconf_max + except (ValueError, OSError): + pass # keep windows default if SC_ARG_MAX isn't in sysconf_names group: List[str] = [] grouplen, space = prefix_length, 0 - for i, arg in enumerate(args): + for arg in args: arglen = len(arg) if arglen > max_group_length: - raise ValueError(f"Argument is longer than the maximum command line size: '{arg}'") + raise ValueError(f"Argument is longer than max command line size: '{arg}'") + if arglen + prefix_length > max_group_length: + raise ValueError(f"Argument with prefix is longer than max command line size: '{arg}'") next_grouplen = grouplen + arglen + space if len(group) == max_group_size or next_grouplen > max_group_length: diff --git a/lib/spack/spack/cmd/pkg.py b/lib/spack/spack/cmd/pkg.py index b8e51522055..f63ceb5f495 100644 --- a/lib/spack/spack/cmd/pkg.py +++ b/lib/spack/spack/cmd/pkg.py @@ -185,8 +185,11 @@ def pkg_grep(args, unknown_args): if not all_paths: return 0 # no packages to search + # these args start every command invocation (grep arg1 arg2 ...) + all_prefix_args = grep.exe + args.grep_args + unknown_args + prefix_length = sum(len(arg) for arg in all_prefix_args) + len(all_prefix_args) + # set up iterator and save the first group to ensure we don't end up with a group of size 1 - prefix_length = len(" ".join(args.grep_args + unknown_args)) groups = spack.cmd.group_arguments(all_paths, prefix_length=prefix_length) # You can force GNU grep to show filenames on every line with -H, but not POSIX grep.