[pacman-dev] [PATCH] makepkg: allow the use of only a package() function
For some packages, generally the 'any' arch ones, a build step is not required and therefore can be skipped. In these cases, a package() function without a build() one is sufficient. As a side effect, this commit makes meta packages without any function at all in the PKGBUILD possible. Fixes FS#15147. Signed-off-by: Cedric Staniewski <cedric@gmx.ca> --- doc/PKGBUILD.5.txt | 12 ++++++------ scripts/makepkg.sh.in | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index 28dd8c7..2d6589b 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -233,10 +233,10 @@ name. The syntax is: `source=('filename::url')`. build() Function ---------------- -In addition to the above directives, the build() bash function comprises the -remainder of the PKGBUILD. This is directly sourced and executed by makepkg, so -anything that bash or the system has available is available for use here. Be -sure any exotic commands used are covered by `makedepends`. +In addition to the above directives, the optional build() bash function usually +comprises the remainder of the PKGBUILD. This is directly sourced and executed by +makepkg, so anything that bash or the system has available is available for use +here. Be sure any exotic commands used are covered by `makedepends`. All of the above variables such as `pkgname` and `pkgver` are available for use in the build function. In addition, makepkg defines three variables for your @@ -263,8 +263,8 @@ package() Function An optional package() function can be specified in addition to the build() function. This function is run immediately after the build() function. When specified in combination with the fakeroot BUILDENV option in linkman:makepkg.conf[5], fakeroot -usage will be limited to running the packaging stage. The build() function will be -run as the user calling makepkg. +usage will be limited to running the packaging stage. An existing build() function +will be run as the user calling makepkg. Package Splitting ----------------- diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index a6780d7..2b540b4 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -72,6 +72,7 @@ LOGGING=0 SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 +BUILDFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST="" @@ -140,7 +141,9 @@ clean_up() { rm -rf "$pkgdir" "$srcdir" if [ -n "$pkgbase" ]; then # Can't do this unless the BUILDSCRIPT has been sourced. - rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* + if (( BUILDFUNC )); then + rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* + fi if [ "$PKGFUNC" -eq 1 ]; then rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package.log"* elif [ "$SPLITPKG" -eq 1 ]; then @@ -1754,6 +1757,12 @@ if [ "${#pkgname[@]}" -gt "1" ]; then SPLITPKG=1 fi +# test for available PKGBUILD functions +# The exclamation mark is required here to avoid triggering the ERR trap when +# a tested function does not exist. +if [[ $(! type -t build) = "function" ]]; then + BUILDFUNC=1 +fi if [ "$(type -t package)" = "function" ]; then PKGFUNC=1 elif [ $SPLITPKG -eq 0 -a "$(type -t package_${pkgname})" = "function" ]; then @@ -1814,7 +1823,7 @@ fi if [ "$INFAKEROOT" -eq 1 ]; then if [ "$SPLITPKG" -eq 0 ]; then if [ "$PKGFUNC" -eq 0 ]; then - if [ "$REPKG" -eq 0 ]; then + if (( BUILDFUNC && ! REPKG )); then run_build tidy_install fi @@ -1928,7 +1937,7 @@ else if [ "$(check_buildenv fakeroot)" != "y" -o $EUID -eq 0 ]; then if [ "$REPKG" -eq 0 ]; then devel_update - run_build + (( BUILDFUNC )) && run_build fi if [ "$SPLITPKG" -eq 0 ]; then if [ "$PKGFUNC" -eq 1 ]; then @@ -1953,7 +1962,7 @@ else else if [ "$REPKG" -eq 0 -a \( "$PKGFUNC" -eq 1 -o "$SPLITPKG" -eq 1 \) ]; then devel_update - run_build + (( BUILDFUNC )) && run_build cd "$startdir" fi -- 1.6.5.2
Cedric Staniewski wrote:
For some packages, generally the 'any' arch ones, a build step is not required and therefore can be skipped. In these cases, a package() function without a build() one is sufficient.
As a side effect, this commit makes meta packages without any function at all in the PKGBUILD possible.
Fixes FS#15147.
Signed-off-by: Cedric Staniewski <cedric@gmx.ca> --- <snip>
+# test for available PKGBUILD functions +# The exclamation mark is required here to avoid triggering the ERR trap when +# a tested function does not exist. +if [[ $(! type -t build) = "function" ]]; then + BUILDFUNC=1 +fi
This certainly appears to work, but can you explain how? Here is my understanding. The "!" means that when build() is not present, the function will still return 0 (not triggering the err trap) and the comparison then fails. When build() function is present, the type -t... outputs "function" but returns 1. How is the err trap not set of then? Is it because there is a value output? Anyway, this is certainly a good catch for when applying the [[ & (( patch. The rest of the patch looks good to me. Allan
Allan McRae wrote:
Cedric Staniewski wrote:
For some packages, generally the 'any' arch ones, a build step is not required and therefore can be skipped. In these cases, a package() function without a build() one is sufficient.
As a side effect, this commit makes meta packages without any function at all in the PKGBUILD possible.
Fixes FS#15147.
Signed-off-by: Cedric Staniewski <cedric@gmx.ca> --- <snip>
+# test for available PKGBUILD functions +# The exclamation mark is required here to avoid triggering the ERR trap when +# a tested function does not exist. +if [[ $(! type -t build) = "function" ]]; then + BUILDFUNC=1 +fi
This certainly appears to work, but can you explain how? Here is my understanding. The "!" means that when build() is not present, the function will still return 0 (not triggering the err trap) and the comparison then fails. When build() function is present, the type -t... outputs "function" but returns 1. How is the err trap not set of then? Is it because there is a value output?
There is no real explanation, only "that's how it works in bash". ;)
From bash's manpage:
trap [-lp] [[arg] sigspec ...] [...] The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a command executed in a && or || list, or if the command's return value is being inverted via !.
Note that apparently only the test/[ builtin is meant here. Your explanation is correct for return codes, but it is not applicable here, because the ERR signal is not the same as a return code greater than zero. Given this script: ----------------- #!/bin/bash set -E trap 'echo >&2 "error"' ERR echo test1 type -t package echo ret: $? echo echo test2 ! type -t package echo ret: $? echo echo test3 type -t package || echo 1 echo ret: $? echo echo test4 type -t package && echo 1 echo ret: $? echo ----------------- It will generate the following output.
$ ./test.sh test1 error ret: 1
test2 ret: 0
test3 1 ret: 0
test4 ret: 1
The interesting case is the last one. "type -t package" returns the return code 1 and an ERR signal, but the ERR trap is not triggered, even though "echo 1" is actually never executed. So, there are several possibilities to catch the ERR signal and I only went for the exclamation mark, because it is the shortest one :). It would also be possible to use "|| echo" if you think it is easier to understand, however, it implies a wrong assumption (return code > 0 = ERR) in my opinion and the "echo" is not needed here.
Anyway, this is certainly a good catch for when applying the [[ & (( patch. The rest of the patch looks good to me.
I thought I already comment about this in the thread. Anyway, you are aware of it now.
Allan
On Sun, Nov 01, 2009 at 05:45:27PM +0000, Cedric Staniewski wrote:
Allan McRae wrote:
From bash's manpage:
trap [-lp] [[arg] sigspec ...] [...] The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a command executed in a && or || list, or if the command's return value is being inverted via !.
Note that apparently only the test/[ builtin is meant here.
I get the same results with both test/[ as with [[ Reusing your code,
set -E trap 'echo >&2 "error"' ERR
false [ false ] [[ false ]] (( 0 )) ! true
Only the 'false' by itself triggers the trap. [ and [[ and treated the same.
Isaac Good wrote:
On Sun, Nov 01, 2009 at 05:45:27PM +0000, Cedric Staniewski wrote:
Allan McRae wrote:
From bash's manpage:
trap [-lp] [[arg] sigspec ...] [...] The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a command executed in a && or || list, or if the command's return value is being inverted via !. Note that apparently only the test/[ builtin is meant here.
I get the same results with both test/[ as with [[
Reusing your code,
set -E trap 'echo >&2 "error"' ERR
false [ false ] [[ false ]] (( 0 )) ! true
Only the 'false' by itself triggers the trap. [ and [[ and treated the same.
You missed a small, but important part of the sentence:
part of the test *in an if statement*
Consequently, this script -------------------- #!/bin/bash set -E trap 'echo >&2 "error"' ERR echo test1 if test $(type -t package); then echo 1 fi echo test2 if [ $(type -t package) ]; then echo 1 fi echo test3 if [[ $(type -t package) ]]; then echo 1 fi echo test4 if (( $(type -t package) )); then echo 1 fi -------------------- results in $ ./test.sh test1 test2 test3 error test4 error
Cedric Staniewski wrote:
Isaac Good wrote:
On Sun, Nov 01, 2009 at 05:45:27PM +0000, Cedric Staniewski wrote:
Allan McRae wrote:
From bash's manpage:
trap [-lp] [[arg] sigspec ...] [...] The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a command executed in a && or || list, or if the command's return value is being inverted via !.
Note that apparently only the test/[ builtin is meant here.
I get the same results with both test/[ as with [[
Reusing your code,
set -E trap 'echo >&2 "error"' ERR
false [ false ] [[ false ]] (( 0 )) ! true
Only the 'false' by itself triggers the trap. [ and [[ and treated the same.
You missed a small, but important part of the sentence:
part of the test *in an if statement*
Consequently, this script -------------------- #!/bin/bash set -E trap 'echo >&2 "error"' ERR
echo test1 if test $(type -t package); then echo 1 fi
echo test2 if [ $(type -t package) ]; then echo 1 fi
echo test3 if [[ $(type -t package) ]]; then echo 1 fi
echo test4 if (( $(type -t package) )); then echo 1 fi --------------------
results in
$ ./test.sh test1 test2 test3 error test4 error
Thanks for the explanation. This all makes perfect sense to me now. Patch is push to my working branch. Allan
On Sun, Nov 01, 2009 at 07:29:20PM +0000, Cedric Staniewski wrote:
Isaac Good wrote:
On Sun, Nov 01, 2009 at 05:45:27PM +0000, Cedric Staniewski wrote:
Allan McRae wrote:
From bash's manpage:
trap [-lp] [[arg] sigspec ...] [...] The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a command executed in a && or || list, or if the command's return value is being inverted via !. Note that apparently only the test/[ builtin is meant here.
I get the same results with both test/[ as with [[
Reusing your code,
set -E trap 'echo >&2 "error"' ERR
false [ false ] [[ false ]] (( 0 )) ! true
Only the 'false' by itself triggers the trap. [ and [[ and treated the same.
You missed a small, but important part of the sentence:
part of the test *in an if statement*
Consequently, this script -------------------- #!/bin/bash set -E trap 'echo >&2 "error"' ERR
echo test1 if test $(type -t package); then echo 1 fi
echo test2 if [ $(type -t package) ]; then echo 1 fi
echo test3 if [[ $(type -t package) ]]; then echo 1 fi
echo test4 if (( $(type -t package) )); then echo 1 fi --------------------
results in
$ ./test.sh test1 test2 test3 error test4 error
I brought this up in FreeNode/#bash and at the very least there is an error in the man pages. More likely a bug in [[. This should be reported upstream to Chet (bash). - Isaac
participants (3)
-
Allan McRae
-
Cedric Staniewski
-
Isaac Good