On Wed, Apr 06, 2022 at 02:20:19AM +0200, Miro Hrončok wrote:
On 06. 04. 22 1:08, Mamoru TASAKA wrote:
> Miro Hrončok wrote on 2022/04/06 4:21:
> > Hello folks,
> >
> > I've realized that if the %install section contains a command that
> > reverses the exit code from success to failure via !, the build does
> > not fail, but it proceeds. In other sections, the build fails. E.g.
> > this:
> >
> > %install
> > ! true
> >
> > Does not fail the build.
> >
> > But this does:
> >
> > %install
> > false
> >
> > As well as this:
> >
> > %build
> > ! true
> I think because on %install section, your line "!
false" is followed by
> "echo UNREACHABLE"
> sentense and later by brp- scripts, and bash "set -e" explanation says:
>
> Exit immediately if a pipeline (which may consist of a
> single simple command), a list, or a compound command
> (see SHELL GRAMMAR above), exits with a non-zero status.
> The shell does not exit if the command that fails is
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> part of the command list immediately following a while
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> or until keyword, part of the test following the if or
> elif reserved words, part of any command executed in a
> && or || list except the command following the final &&
> or ||, any command in a pipeline but the last, or if the
> ^^^^^^^^^
> command's return value is being inverted with !.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Yeah, it's a fairly terrible gotcha. To add to the excellent explanation
by Mamoru, when there's a sequence of commands, the return value of the
last command becomes the return value of the program. Thus bash -c 'set -e; ! true;
true'
returns success, but 'set -e; true; ! true' returns failure.
We fought with this in the systemd testsuite [e.g. 1,2]. One neat treat
is to push the inversion into the command:
! test -e /some/path → test ! -e /some/path
Another trick is to wrap the whole command in a subshell [3]. Then the return
value of the (only) command becomes the return value of the subshell:
! false → ( ! false )
(Only () works. {} doesn't have the same effect.)
[1]
https://github.com/systemd/systemd/commit/ffa328f060
[2]
https://github.com/systemd/systemd/commit/b1e1e5ac25
[3]
https://github.com/systemd/systemd/commit/d6c51c485a
I guess I need to verify the packages where we use `! grep ...` etc.
in %check:
$ rg '^!\s+\S' rpm-specs/
rpm-specs/python-tomli.spec
81:! grep '^Requires-Dist:'
%{buildroot}%{python3_sitelib}/tomli-%{version}.dist-info/METADATA
rpm-specs/symfpu.spec
78:! ./test --allTests
rpm-specs/radamsa.spec
39:! diff -u output1 output2
rpm-specs/python-rpm-macros.spec
133:! grep -E '^#[^%%]*%%[^%%]' %{buildroot}%{rpmmacrodir}/macros.*
rpm-specs/python-pyqtchart.spec
71:! grep %{buildroot} %{buildroot}%{distinfo}/*
rpm-specs/python-bleach.spec
55:! find %{buildroot}%{python3_sitelib}/bleach/ -type d | grep vendor
rpm-specs/ilua.spec
59:! grep Traceback check.log
rpm-specs/hspell.spec
66:! make test | grep FAILED | grep -E -v '1/aspell/[489]'
rpm-specs/gdb.spec
472:! find -name "*.rej" # Should not happen.
762:! grep '_RELOCATABLE.*1' gdb/config.h
rpm-specs/gap-pkg-edim.spec
87:! grep -Fq 'false' log
rpm-specs/csnappy.spec
49:! test -e LICENSE
And
https://src.fedoraproject.org/rpms/pyproject-rpm-macros/blob/rawhide/f/te...
+ other specs there.
This just shows how hard bash is to use correctly. shellcheck helps a
lot, but even it doesn't find all the caveats.
Zbyszek