buildah
buildah copied to clipboard
bash completion error with `shopt -s failglob`
I have failglob set in my interactive shells, and buildah's bash completion doesn't seem to work with that. In this output from bash --norc, I pressed tab after buildah :
bash-5.2$ . /etc/bash_completion
bash-5.2$ shopt -s failglob
bash-5.2$ buildah bash: no match: @(--cgroup-manager|--registries-conf|--registries-conf-dir|--root|--runroot|--storage-driver|--storage-opt|--userns-uid-map|--userns-gid-map)
bash: [: 1: unary operator expected
I'm not seeing this error on my system, but then it (Fedora 41) doesn't have a /etc/bash_completion file. Could it be specific to your package, system, or distribution?
Doesn't look like it, I just tried again with the file from the git repo, which is the same as the file on my system:
$ LC_ALL=C.UTF-8 bash --norc
bash-5.2$ git show --oneline
e8d8be71c (HEAD -> main, origin/main, origin/HEAD) Merge pull request #6070 from containers/renovate/github.com-opencontainers-runc-1.x
bash-5.2$ diff -u /usr/share/bash-completion/completions/buildah contrib/completions/bash/buildah
bash-5.2$ . contrib/completions/bash/buildah
bash-5.2$ shopt -s failglob
bash-5.2$ buildah bash: _get_comp_words_by_ref: command not found
bash: [: 1: unary operator expected
bash: no match: @(--cgroup-manager|--registries-conf|--registries-conf-dir|--root|--runroot|--storage-driver|--storage-opt|--userns-uid-map|--userns-gid-map)
The _get_comp_words_by_ref error is because I didn't source bash completion itself, I think, but the no match error is still there. If I source /usr/share/bash-completion/bash_completion (which it looks like Fedora 41 provides?) instead, I get the original error:
$ LC_ALL=C.UTF-8 bash --norc
bash-5.2$ . /usr/share/bash-completion/bash_completion
bash-5.2$ shopt -s failglob
bash-5.2$ buildah bash: no match: @(--cgroup-manager|--registries-conf|--registries-conf-dir|--root|--runroot|--storage-driver|--storage-opt|--userns-uid-map|--userns-gid-map)
bash: [: 1: unary operator expected
Do you get the bug if you source /usr/share/bash-completion/bash_completion?
Ah, it wasn't being picked up automatically when I launched a subshell.
@Luap99 I'm told you know more about this than I do. Should we be using the output of the cobra completion builtin instead of this manually maintained file, as podman does?
This reproduces easily but your cwd must be empty in order to trigger a glob error (i.e no files to expand to)
AFAICT the reason this fails is because "$cur" is empty in the case statement and the the * match then seem to expend files instead of matching against the passed in variable but I could be wrong on that as I am not big in shell scripting.
@Luap99 I'm told you know more about this than I do. Should we be using the output of the cobra completion builtin instead of this manually maintained file, as podman does?
Overall yes that is so much easier to maintain. Each flag and command is completed by default so no need to ever update the shell scripts. And you get bash, zsh, fish and powershell completion. To actually complete the arguments right argument values you now must write that stuff in go via custom completion functions, cmd/podman/common/completion.go in podman is worth to start to take a look. I went really fancy over there, for example all our custom go templates can be auto completed (see AutocompleteFormat in the file) , i.e.
$ podman inspect --format {{.
{{.AppArmorProfile}} {{.ExecIDs}} {{.IsInfra}} {{.OCIConfigPath}} {{.SizeRootFs}}
{{.Args}} {{.GraphDriver. {{.IsService}} {{.OCIRuntime}} {{.SizeRw}}
{{.BoundingCaps}} {{.HostConfig. {{.KubeExitCodePropagation}} {{.Path}} {{.State.
{{.Config. {{.HostnamePath}} {{.LockNumber}} {{.PidFile}} {{.StaticDir}}
{{.ConmonPidFile}} {{.HostsPath}} {{.MountLabel}} {{.Pod}} {{.UseImageHostname}}
{{.Created. {{.ID}} {{.Mounts}} {{.ProcessLabel}} {{.UseImageHosts}}
{{.Dependencies}} {{.Image}} {{.Name}} {{.ResolvConfPath}}
{{.Driver}} {{.ImageDigest}} {{.Namespace}} {{.RestartCount}}
{{.EffectiveCaps}} {{.ImageName}} {{.NetworkSettings. {{.Rootfs}}
There is some cost to this of course. For example in podman I require that every option and command have a custom shell completion function set to avoid people forgetting to write them via cmd/podman/shell_completion_test.go
Even here in buildah I already added quite a lot of them https://github.com/containers/buildah/blob/3e3baeeb2ca535440cee53cb059c7afd0fdc484b/pkg/cli/common.go#L318
So I don't think it would be to difficult to switch. It all depends on how much work we want to put in to write these completion functions, images/container names should be there for the main commands at least to avoid regressions int he completion user experience I suppose.
AFAICT the reason this fails is because "$cur" is empty in the case statement and the the
*match then seem to expend files instead of matching against the passed in variable but I could be wrong on that as I am not big in shell scripting.
Do you mean in the code below?
https://github.com/containers/buildah/blob/3e3baeeb2ca535440cee53cb059c7afd0fdc484b/contrib/completions/bash/buildah#L217-L222
I'm not sure, but I think the issue is that __buildah_pos_first_nonflag is taking a glob as an argument, with the expectation that the glob is expanded inside of the function, but not outside when the function arguments are being built up. Changing $(__buildah_to_extglob "$options_with_args") to "$(__buildah_to_extglob "$options_with_args")" would fix it, I think, so that the glob is only expanded inside of __buildah_pos_first_nonflag.
Overall yes that is so much easier to maintain.
I don't know the specifics of that framework, but in general I'm a big fan of avoiding shell when possible.
A friendly reminder that this issue had no activity for 30 days.