Compare commits

...

121 Commits

Author SHA1 Message Date
Piraty a45d12d4c3
abuild-rootbld: copy SRCDEST value from host to chroot
Otherwise the default hardcoded in abuild-fetch (var/cache/distfiles) is
used.

(in the same vein as 6864df03aa)

Fixes: 1582617 ("abuild-rootbld: clear environment for bwrap container")
2024-04-26 00:24:09 +02:00
Natanael Copa 68d6aa65f4 abuild: skip /var/run in fhs check
We have many package containing directories under /var/run. Allow those
for now.

Partially reverts commit 08d2d81587 (abuild: extend fhs check)
2024-04-21 10:37:44 +02:00
Natanael Copa c48f8498e7 abuild: allow packages to install under run
I have some vauge memory that it is conveinent for Docker users that the
state dir under /run exists.

Allow this for alpine 3.20 and revisit later.
2024-04-20 08:20:18 +02:00
Natanael Copa eeca95d195 abuild: pass APORTS_BOOTSTRAP to bubblewrap 2024-04-19 23:41:45 +02:00
Natanael Copa 5023838d60 ==== release 3.13.0 ==== 2024-04-17 08:45:34 +02:00
Natanael Copa 7e7b0a5ba3 tests: increase timeout for abuild-fetch to call curl
The CI may be under load.
2024-04-17 08:40:47 +02:00
Natanael Copa 645c3c07a7 abuild: exclude provides for commans with @
the '@' characted serves as a repository separator (eg. pkg@repo) so we
should not add a cmd: provides for binaries having this character.

This avoids conflicts with for example `who` from coreutils and `who@`
from ucspi-tpc6.

fixes https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10074
2024-04-17 08:35:27 +02:00
Natanael Copa e4896c01b8 test: inline bin-in-path APKBUILD
Improves readability. No functional changes
2024-04-17 08:21:40 +02:00
Sertonix 54fd3e4117 abump: preserve in-line comments after pkgver/pkgrel
Fixes [#10133]

[#10133]: https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10133
2024-04-12 11:59:56 +00:00
Sertonix 855992822d abuild: update cachedir logic for rootbld
Closes [#10111]

[#10111]: https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10111
2024-04-12 11:59:04 +00:00
Sertonix 7276042237 abuild: always use $APK instead of apk 2024-04-12 11:59:04 +00:00
Sertonix 6aa8fcc012 abuild: remove libc specific logic
Last use of the '!libc_*' option has been removed in [61cb57cda98].
libpthread special casing only triggers on uclibc.

[61cb57cda98]: https://git.alpinelinux.org/aports/commit/?id=61cb57cda98923032f7ff15f7a0f057bb35aae6d
2024-04-12 11:56:05 +00:00
Sertonix 20b1f47c63 abuild: fix ~ splitting pkgname and pkgver 2024-04-12 11:51:48 +00:00
Sertonix 0e325a2354 abuild: fix python3 depending on python3 2024-04-03 14:09:03 +02:00
Natanael Copa 22e17446f7 Revert "checkapk: Check how many packages depend on a previous soname"
The implementation is difficult to get right. Keep checkapk simple.
Fixes https://gitlab.alpinelinux.org/alpine/abuild/-/merge_requests/229

This reverts commit acfa7d6732.
2024-03-29 12:19:20 +01:00
Sertonix 141da52d19 abuild: warn on go packages without net option 2024-03-29 11:15:43 +00:00
Sertonix 21b5a2298d abuild: fix help message 2024-03-29 11:14:35 +00:00
Sertonix 20c0a15856 functions.sh: fix ABUILD_USERDIR overwrite in ABUILD_CONF 2024-03-29 11:14:35 +00:00
Sertonix 1804361f61 abuild: error on digit+letter+digit version format 2024-03-29 11:12:51 +00:00
Sertonix f0051d2658 doc: document replaces_priority 2024-03-28 22:43:42 +00:00
Hugo Osvaldo Barrera d65a054bc5 Add a man page for abump 2024-03-28 22:42:43 +00:00
Sertonix 17648366cc abuild: invalidate pkgver ending with -r# 2024-03-28 22:41:30 +00:00
Sertonix 2e27c5b202 abuild: sanitycheck pkgver regardless of -d flag 2024-03-28 22:41:30 +00:00
Sertonix a9053617db abuild: stricter pkgname check 2024-03-28 22:40:14 +00:00
Sertonix 73cc75b3e0 abuild: amove: allow spaces in pattern 2024-03-28 18:40:25 +00:00
Sertonix 08d2d81587 abuild: extend fhs check 2024-03-27 14:53:58 +01:00
Timo Teräs ec11f495cd abuild: add an option to keep all directories
This is mainly needed for alpine-baselayout which creates all
directories, and most of them are empty. The code in question
would remove directories we explicitly want alpine-baselayout
to create and own.
2024-03-22 21:56:14 +02:00
Sertonix 8588378efa checkapk: new arch can cause old apk missing 2024-03-13 11:14:34 +00:00
Hugo Osvaldo Barrera 2e987e10ff Remove deprecated option from abuild man page
Using this flag yields:

  >>> ERROR: : Use newapkbuild to create new aports
2024-03-13 11:12:15 +00:00
Natanael Copa 8da2501613 abuild: warn for more version suffixes
give a warning when version suffix a<digit>/b<digit> probably should be
_alpha<digit>/_beta<digit>.

ref: https://gitlab.alpinelinux.org/alpine/apk-tools/-/issues/10972#note_380899
2024-03-13 11:57:50 +01:00
Sertonix 648529aa35 abuild: remove duplicate SOURCE_DATE_EPOCH from .PKGINFO 2024-03-06 13:05:10 +00:00
Sertonix f63c117df6 abuild: avoid variables in sed pattern 2024-03-05 11:59:10 +00:00
Jingyun Hua e3ba1238d3 abuild.in: update autoconf test for loongarch64 2024-03-05 11:56:33 +00:00
Hugo Osvaldo Barrera 1861b23f0c Remove --recursive from abump --help
This flag does not exist.
2024-03-05 11:27:52 +00:00
Hugo Osvaldo Barrera 06ee1d3cfb .editorconfig: add yml rules
While editing .gitlab-ci.yml, my editor kept indenting to tabs due to
the override for [*]. This retains the existing style.
2024-03-05 11:03:27 +00:00
Celeste 19bebd8497 apkbuild-cpan.in: use distribution name cached in %distfiles
instead of sending a duplicate query to metacpan

follow up from what was done in
e448c9a452
2024-03-05 11:01:27 +00:00
Timothy Legge 5710eefb63 apkbuild-cpan.in: remove perl-dev package wherever it occurs
if the package does not have any xs files and the old APKBUILD data is used

The regex to get perl-dev wherever it might occur was breaking my head
2024-03-05 11:01:27 +00:00
Timothy Legge b0fb5c7038 apkbuild-cpan.in: don't add perl-dev if its not needed on recreate 2024-03-05 11:01:27 +00:00
Sertonix 4ae1b39910 abuild: fix quote handling in check_license 2024-02-12 12:39:17 +01:00
Celeste 39c2b44c63 apkbuild-pypi.in: add option to use project homepage as url=
instead of pypi.org page
2024-02-02 02:51:27 +00:00
Celeste 9e336571e1 apkbuild-pypi.in: fixes #10129 move _pkgreal and comment
this makes it easier to see the maintainer line in
an unexpanded diff that shows a three-line context
2024-02-02 02:51:27 +00:00
Celeste 49983f5af5 apkbuild-pypi.in: fix a number of uninitialized value warnings 2024-02-02 02:51:27 +00:00
Celeste fb262fad5e apkbuild-pypi.in: redefine builddir if not based on $_pkgreal 2024-02-02 02:51:27 +00:00
Celeste db578302aa apkbuild-pypi.in: clean up read_assignments_from_file
also, keep the comment associated with provides & replaces, and
return early to avoid running APKBUILD-specific regex matches
2024-02-02 02:51:27 +00:00
Celeste bc4efd7f0c apkbuild-pypi.in: keep options and patches (copied from apkbuild-cpan)
thanks @timlegge for working out how to make this work in apkbuild-cpan
2024-02-02 02:51:27 +00:00
Celeste 9b513da2f4 apkbuild-pypi.in: keep old dependencies during recreate
unless py3-gpep517 or py3-pytest is missing, then
add that in as the template generated uses it.

To force dependencies to be recalculated, use
`recreate deps`.
2024-02-02 02:51:27 +00:00
Celeste a9e956dc16 apkbuild-pypi.in: move requires_dist parsing code to its own function
also, use regex from https://peps.python.org/pep-0508/#names
to parse valid pypi package names in requires_dist
2024-02-02 02:51:26 +00:00
Celeste 9e416f782a apkbuild-pypi.in: keep old license, url, pkgname/desc during recreate 2024-02-02 02:51:26 +00:00
Celeste d05bc1a4af apkbuild-pypi.in: change position of replaces/provides in template
Most Python aports put replaces/provides
between `builddir` and `build()`.

Follow this convention, so they don't change
position when running `apkbuild-pypi recreate`.
2024-02-02 02:51:26 +00:00
Celeste fc863565f1 apkbuild-pypi.in: update url generated in template 2024-02-02 02:51:26 +00:00
Celeste 32c0815828 apkbuild-pypi.in: switch to pypi.org
pypi.python.org now redirects to it
2024-02-02 02:51:26 +00:00
Celeste 81fb95d31a apkbuild-pypi.in: format depends and checkdepends
with `format_depends` function
taken from `apkbuild-cpan.in`
2024-02-02 02:51:26 +00:00
Celeste 250412d18c apkbuild-pypi.in: use pypi json in get_deps
the old method of calling
`python3 ./setup.py --requires`
doesn't seem to be working anymore
2024-02-02 02:51:26 +00:00
Celeste 54550dc597 apkbuild-pypi.in: use $pkgver in source
regex taken from `apkbuild-cpan.in`
2024-02-02 02:51:26 +00:00
Celeste 11c96f25d6 apkbuild-pypi.in: add -pyc subpackage to template 2024-02-02 02:51:26 +00:00
Celeste ad9324fd52 apkbuild-pypi.in: use gpep517 in template
copied from `newapkbuild.in`, should work
even without a `pyproject.toml` due to the
`setuptools.build_meta:__legacy__` backend
2024-02-02 02:51:26 +00:00
Celeste 4a55e30881 apkbuild-pypi.in: remove depends="python3" from template
it is automatically traced since 6806a0d39b
2024-02-02 02:51:26 +00:00
Celeste 157e390ffa apkbuild-pypi.in: create pretty urls in get_source 2024-02-02 02:51:26 +00:00
Timothy Legge 60c00a4d39 apkbuild-cpan.in: Remmove unnecessary/unused code
Should have been removed in:
27c430cc64
2024-02-01 22:08:23 -04:00
Timothy Legge 99cda3db69 apkbuild-cpan.in: fix uninitialized value when running with no parameters
by applying Celeste's suggested fix
2024-02-01 22:08:23 -04:00
Timothy Legge 1dd67c1beb apkbuild-cpan.in: remove unnecessary pragmas 2024-02-01 22:08:17 -04:00
Timothy Legge 9cde1ad278 apkbuild-cpan.in: Standardize the source and patches output 2024-02-01 07:35:23 -04:00
Celeste 0ad7489969 apkbuild-cpan.in: move code that queries metacpan into its own function
this piece of code was repeated in multiple places, so factor it out
2024-01-31 19:29:56 -04:00
Timothy Legge 726e37920c apkbuild-cpan.in: fix read_assignments_from_file
remove unnecessary regex in functions

Return early if not processing an APKBUILD file

and fix undefined variable of there are no patches
2024-01-30 23:05:45 -04:00
Celeste 1c017bb5d5 apkbuild-cpan.in: add newline after inserting *depends=
Upon `apkbuild-cpan upgrade`, an aport without any
checkdepends would get a line like this inserted:
`checkdepends=""subpackages="$pkgname-doc"`

which would then be deleted by the substitution
that removes empty variables, so the net result
is an APKBUILD with the subpackages field removed.

Inserting a newline results in `checkdepends=""`
being a line all by itself, which then gets
correctly removed by the empty variables regex.
2024-01-28 02:50:25 +00:00
Timothy Legge b0f60ee85a apkbuild-cpan.in: fixes #10129 move _pkgreal and comment 2024-01-27 12:10:06 -04:00
Celeste 28edb26d5b apkbuild-cpan.in: fix empty lines in recreated depends variables
this is a preliminary attempt at fixing #10126, however, i think
the whole logic around recreating depends should be reviewed and
improved, as we may want to carry over all the depends from the
old APKBUILD, and not just the non-perl libs, as the old depends
may be compensating for something not declared in the META file.
2024-01-26 22:33:02 -04:00
Celeste b48c12ea86 apkbuild-cpan.in: do not increase number of spaces in options_comment
the regex used to match options_comment in read_assignments_from_file
starts matching immediately after the closing double quote (it does
not remove the prefixing space), so without this change, a new space
is inserted by the template upon each `recreate`.
2024-01-26 21:37:18 -04:00
Celeste 6a8a61f9d8 apkbuild-cpan.in: find Build.PL using glob() in update_functions sub
this is more consistent with the method we use to
find Build.PL / Makefile.PL in the do_depends sub
2024-01-26 21:37:18 -04:00
Celeste 1c771b0d6a apkbuild-cpan.in: keep arch of old APKBUILD
also, prevent removal of `arch=""` line,
which is sometimes used for disabled aports
2024-01-26 21:37:18 -04:00
Celeste ef6aef38b1 apkbuild-cpan.in: sort & de-duplicate dependencies 2024-01-26 21:37:18 -04:00
Celeste 41a36bca95 apkbuild-cpan.in: move .pod files to the -doc subpackage
this `doc()` function is copied from main/perl/APKBUILD
2024-01-26 21:37:18 -04:00
Celeste 3336955a4a apkbuild-cpan.in: update $package_mappings 2024-01-26 21:37:18 -04:00
Celeste fe072f9866 apkbuild-cpan.in: fix empty directories
by not installing .packlist and perllocal.pod.

The call to find -delete has been removed as
the modifications to build() have covered
almost all cases, so deleting .packlist and
perllocal.pod manually is no longer necessary.

Also, increment template version from 3
to 4 to allow easy identification of
aports that have this change applied.
2024-01-26 21:37:18 -04:00
Celeste 7101d6164a apkbuild-cpan.in: also attempt to generate MYMETA from running Build.PL 2024-01-26 21:37:18 -04:00
Celeste 1753907af0 apkbuild-cpan.in: fix use of uninitialized value $1 2024-01-26 21:37:18 -04:00
Timothy Legge c704644b3c Initial attempt to keep the options and patches 2024-01-26 21:37:18 -04:00
Celeste 37e99da359 apkbuild-cpan.in: tidy up abstract before using it as pkgdesc 2024-01-26 21:37:18 -04:00
Celeste 0bb1482c3a New way of calculating builddir & metaprefix
apkbuild-cpan.in: attempt to get a metaprefix if no metafiles exist

apkbuild-cpan.in: try harder to find a metaprefix

apkbuild-cpan.in: redefine builddir if not based on $_pkgreal
2024-01-26 21:37:18 -04:00
Timothy Legge 505a64bfa7 Improve handling of missing meta files and detection of perl-dev requirment 2024-01-26 21:37:18 -04:00
Sertonix cd32e245e2 abuild: fix subpackage setting arch to all explicitly 2024-01-12 18:28:09 +01:00
Natanael Copa 84e29d94f9 ==== release 3.12.0 ==== 2023-10-18 12:32:17 +02:00
Sören Tempel acfa7d6732 checkapk: Check how many packages depend on a previous soname
Since the changeset committed by psykose a while ago in commit
26118d4997 we now extract the
previous soname. We can pass this previous soname to `apk search -R`
to figure out how many packages are linked against this old soname.

I believe this to be useful for reviewing MRs since the checkapk
output will directly tell us if a contributor has missed rebuilds.
It will also inform us when no rebuilds are necessary, e.g. if the
SONAME was changed but no packages is linked against the library.

Example output for `main/libsodium`:

```
>>> Size difference for libsodium: 336 KiB -> 340 KiB
--- filelist-libsodium-old      2023-09-22 11:24:54.799204225 +0200
+++ filelist-libsodium-new      2023-09-22 11:24:54.799204225 +0200
@@ -1,5 +1,5 @@
 .PKGINFO
 usr/
 usr/lib/
-usr/lib/libsodium.so.23
-usr/lib/libsodium.so.23.3.0
+usr/lib/libsodium.so.26
+usr/lib/libsodium.so.26.1.0
SODIFF:
-usr/lib/libsodium.so.23.3.0:    SONAME               libsodium.so.23
+usr/lib/libsodium.so.26.1.0:    SONAME               libsodium.so.26
REBUILDS:
*** 36 packages linked against 'libsodium.so.23' need to be rebuild!
```
2023-10-18 09:39:12 +00:00
Natanael Copa fab41364f7 checkapk: dont require abuild.conf if we have default conf
also add tests
2023-10-18 11:22:47 +02:00
Natanael Copa 643637dd5d checkapk: add test, fix usage
print --help output to stdout and errors to stderr.
2023-10-18 11:07:24 +02:00
Natanael Copa 3a7fdeaaf0 tests: speed up abuild cleanoldpkg test
skip various steps when buliding the package.
2023-10-18 08:46:09 +02:00
Natanael Copa 08126de5f2 tests: add another test for abuild deps
Test that passing only `CHOST=... abuild deps` works as expected
2023-10-17 22:30:00 +02:00
Natanael Copa c73b8f4ca7 tests: test checkdepends
verify that checkdepends is pulled in when it should and not installed
when it shouldn't.
2023-10-17 22:04:56 +02:00
Natanael Copa 852bb238f3 tests: add test for abuild dep
verify that makedepends_build and makedepends_host works as expected.
2023-10-17 19:51:35 +00:00
Natanael Copa 9ed6a92107 make: run tests in parallel 2023-10-17 19:51:35 +00:00
Natanael Copa c63cae3b15 abuild-tar: fix warnings from scan-build
ref: https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10102
2023-10-17 16:33:15 +00:00
Natanael Copa fcdfd871af abuild-sudo: handle errors from setuid/setgid
ref https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10102
2023-10-17 16:33:15 +00:00
Natanael Copa 1332d5b171 abuild-rmtemp: fix build with clang 2023-10-17 16:33:15 +00:00
Natanael Copa 4128fa6392 ci: build with clang and scan-build
ref: https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10102
2023-10-17 16:33:15 +00:00
Natanael Copa a6a95ad633 abuild: set filetype sh for abuild.in 2023-10-17 16:33:15 +00:00
ptrcnull f688130443 abuild: simplify finding repo_template
related to #10069, this keeps the original behaviour when
running in aports and allows for using rootbld in other package repositories
2023-10-12 15:39:09 +00:00
jvoisin dd67240f01 Actually set values for libcpp hardening macros
Otherwise, it wouldn't do much…
2023-09-04 01:56:15 +02:00
sudotac 9fe0d14d7e apkbuild-pypi.in: replace given/when with if/elsif
smartmatch is deprecated in Perl 5.37.10
2023-08-30 05:50:04 +00:00
sudotac 00aa9aab12 apkbuild-pypi.in: use $() instead of backticks 2023-08-30 05:50:04 +00:00
jvoisin 65b5d578b2 Enable more hardening for libcpp
- _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS: This macro is used to enable -Wthread-safety annotations on libc++’s std::mutex and std::lock_guard.
- _LIBCPP_ENABLE_HARDENED_MODE to enable the hardened mode.
2023-08-21 13:37:35 +02:00
psykose 28b97249fa ==== release 3.11.21 ==== 2023-07-17 06:28:54 +02:00
psykose 6c20db871b checkapk: fix a mistaken grep warning
grep: warning: stray \ before -
it matches without \ anyway
2023-07-17 06:12:56 +02:00
psykose cc17a1cc79 checkapk: exit on trap signal
otherwise it cleans up but the loop keeps going and just fails until end,
just spamming the output
2023-07-11 15:38:09 +02:00
Iztok Fister Jr 617df473b0 apkbuild-cpan: fix typo 2023-07-07 22:48:12 +02:00
psykose d4b2415fb1 apkbuild-cpan: run perltidy over the source
it was a mismatch of mixed indents
2023-07-03 23:52:43 +02:00
psykose 0e555d58a7 apkbuild-cpan: port given/when to if/else
the former is deprecated syntax
2023-07-03 23:49:52 +02:00
psykose fc575e8361 abuild: fix a mistake in 0e333003df
the prefix was dropped from the check so it always says it's unregistered
no actual breakage happened as this just prints a warning
2023-07-03 04:45:13 +02:00
psykose cbca6d4f48 ==== release 3.11.20 ==== 2023-06-29 06:02:28 +02:00
psykose 21faeb7f47 checkapk: use grep instead of awk for size checking
the previous implementation had a bug that + chars needed escaping
(which was fixed), and now has another discovered but that pkgnames
could start with a number, so the /^pkg/ match matches the pkgname again
and a size comparison gives you:

>>> Size difference for 7zip: 7zip-22.01-r5 installed size: -> 7zip-23.01-r0 installed size:

using grep -F avoids any magic character expansion and works correctly
in all cases.
2023-06-29 06:00:22 +02:00
psykose 446b68359f tests: make sure move_caches tests don't fail with envs set 2023-06-26 10:33:40 +02:00
psykose 873a4b6654 ==== release 3.11.19 ==== 2023-06-26 10:31:15 +02:00
psykose df31829660 checkapk: don't objdump invalid elfs
cleans up the output a bit for things that have .so in the name
2023-06-26 10:30:49 +02:00
psykose 535afd9544 checkapk: do simple parallel
this is quite trivial and should be safe
2023-06-26 07:52:28 +02:00
psykose 5c25099d4f ==== release 3.11.18 ==== 2023-06-26 07:41:07 +02:00
psykose 9855e304c7 checkapk: ignore missing apk error
prior to the recent reworks, this error handling path was never
triggered, because the script is ran without pipefail, and it was at
the end of a | pipe | line | sort, so all it did was be ignored for 'new
apks', when the old one would fail to fetch and be missing.

since we now do hit this path on fetch failure however, it aborts the
script when a new subpackage/package is added (since the 'old apk' won't
exist), and doesn't output a diff. since before we always ignored this,
ignore the 'old apk' perhaps not existing, which gives the currently
intended behaviour.
2023-06-26 07:41:07 +02:00
psykose d451522e53 ==== release 3.11.17 ==== 2023-06-26 04:25:43 +02:00
psykose 256a249feb checkapk: but actually skip symlinks
boolean logic gets confusing..
2023-06-26 04:25:08 +02:00
psykose d51cf9c2bb ==== release 3.11.16 ==== 2023-06-26 04:23:08 +02:00
psykose fd5ec6b4fa checkapk: skip symlinks
this affected the old version too- duplicate sodiffs on symlinks are useless
2023-06-26 04:22:26 +02:00
psykose 64f2b3af4e ==== release 3.11.15 ==== 2023-06-26 04:15:06 +02:00
psykose 9af4012177 checkapk: also make sure only sofiles objdumped 2023-06-26 04:14:15 +02:00
23 changed files with 1525 additions and 734 deletions

View File

@ -20,3 +20,7 @@ indent_style = space
[Makefile]
indent_size = 8
indent_style = tab
[*.yml]
indent_size = 2
indent_style = space

View File

@ -5,7 +5,27 @@ tests:
image:
name: alpinelinux/abuild-ci
stage: verify
script: [pwd]
script:
- make
- make check
tags:
- docker-alpine
- x86_64
build-clang:
image:
name: alpinelinux/abuild-ci
stage: verify
script: [CC=clang make]
tags:
- docker-alpine
- x86_64
build-scan:
image:
name: alpinelinux/abuild-ci
stage: verify
script: [scan-build --status-bugs make]
tags:
- docker-alpine
- x86_64

View File

@ -168,6 +168,12 @@ file.
Specifies packages that the package replaces. This is typically
used for packages renamed by upstream.
*replaces_priority*
Specifies the numeric value that is used by apk(8) when multiple
packages with *replaces* include the same file. It is also used
to decide which package should define the permissions of a directory
even without *replaces* set.
*subpackages*
Specifies subpackages or split packages built with this
package. Typically, this will include _$pkgname-dev_ for development

View File

@ -1,5 +1,5 @@
PACKAGE := abuild
VERSION := 3.11.14
VERSION := 3.13.0
prefix ?= /usr
bindir ?= $(prefix)/bin
@ -11,7 +11,7 @@ SCRIPTS := abuild abuild-keygen abuild-sign newapkbuild \
abump apkgrel buildlab apkbuild-cpan apkbuild-pypi checkapk \
apkbuild-gem-resolver
USR_BIN_FILES := $(SCRIPTS) abuild-tar abuild-gzsplit abuild-sudo abuild-fetch abuild-rmtemp
MAN_1_PAGES := newapkbuild.1 abuild.1
MAN_1_PAGES := newapkbuild.1 abuild.1 abump.1
MAN_5_PAGES := APKBUILD.5
SAMPLES := sample.APKBUILD sample.initd sample.confd \
sample.pre-install sample.post-install
@ -127,7 +127,7 @@ Kyuafile: tests/Kyuafile
echo "include('tests/Kyuafile')" >> $@
check: $(SCRIPTS) $(USR_BIN_FILES) functions.sh tests/Kyuafile Kyuafile tests/testdata/abuild.key.pub
kyua test || (kyua report --verbose && exit 1)
kyua --variable parallelism=$(shell nproc) test || (kyua report --verbose && exit 1)
install: $(USR_BIN_FILES) $(SAMPLES) $(MAN_PAGES) default.conf abuild.conf functions.sh
install -d $(DESTDIR)/$(bindir) $(DESTDIR)/$(sysconfdir) \

View File

@ -18,7 +18,7 @@
#define PREFIX "/var/tmp/abuild."
static void fail() {
static void fail(void) {
errx(1, "%s", strerror(errno));
}

View File

@ -125,9 +125,11 @@ int main(int argc, const char *argv[])
argv[0] = path;
/* set our uid to root so bbsuid --install works */
setuid(0);
if (setuid(0) < 0)
err(1, "setuid(0) failed");
/* set our gid to root so apk commit hooks run with the same gid as for "sudo apk add ..." */
setgid(0);
if (setgid(0) < 0)
err(1, "setgid(0) failed");
execv(path, (char * const*)argv);
perror(path);
return 1;

View File

@ -221,7 +221,8 @@ static int buf_padto(struct buf *b, size_t alignment)
newsize = (oldsize + alignment - 1) & -alignment;
if (buf_resize(b, newsize)) return -ENOMEM;
b->size = newsize;
memset(b->ptr + oldsize, 0, newsize - oldsize);
if (b->ptr)
memset(b->ptr + oldsize, 0, newsize - oldsize);
return 0;
}
@ -260,6 +261,8 @@ static int buf_add_ext_header_hexdump(struct buf *b, const char *hdr, const unsi
for (i = len; i > 9; i /= 10) len++;
if (buf_resize(b, b->size + len)) return -ENOMEM;
if (b->ptr == NULL)
return 0;
b->size += snprintf(&b->ptr[b->size], len, "%u %s=", len, hdr);
for (i = 0; i < valuelen; i++)
b->size += snprintf(&b->ptr[b->size], 3, "%02x", (int)value[i]);

View File

@ -6,8 +6,7 @@ abuild(1)
# SYNOPSIS
*abuild* [options] [-P _REPODEST_] [-s _SRCDEST_] [-D _DESCRIPTION_] [cmd] ...++
*abuild* [-c] -n _PKGNAME_[-_PKGVER_]
*abuild* [options] [-P _REPODEST_] [-s _SRCDEST_] [-D _DESCRIPTION_] [cmd] ...
# DESCRIPTION
@ -29,7 +28,7 @@ other related operations.
Set APKINDEX description (default: *$repo $(git describe)*)
*-f*
Force specified cmd (skip checks: apk up to date, arch, libc)
Force specified cmd (skip checks: apk up to date, arch)
*-F*
Force run as root

169
abuild.in
View File

@ -1,4 +1,5 @@
#!/bin/ash -e
# vim: set filetype=sh:
# abuild - build apk packages (light version of makepkg)
# Copyright (c) 2008-2015 Natanael Copa <ncopa@alpinelinux.org>
@ -77,17 +78,17 @@ amove() {
d="$(pwd -L)"
cd "$pkgdir"
local pattern f
local pattern f IFS=""
for pattern; do
for f in ${pattern#/}; do # let shell expand the pattern
# strip trailing /
f=${f%/}
if [ "${f%/*}" != "$f" ]; then
mkdir -p "$subpkgdir/${f%/*}"
mv -v "$pkgdir"/$f "$subpkgdir/${f%/*}"
mv -v "$pkgdir/$f" "$subpkgdir/${f%/*}"
else
mkdir -p "$subpkgdir"
mv -v "$pkgdir"/$f "$subpkgdir/"
mv -v "$pkgdir/$f" "$subpkgdir/"
fi
# cleanup
rmdir -p "$f" 2>/dev/null || rmdir -p "${f%/*}" 2>/dev/null || true
@ -179,30 +180,30 @@ spell_error() {
}
verify_pkgname() {
local name=${1%%=*}
case "$name" in
""|*" "*|-*) return 1;;
case $1 in
''|*[!a-zA-Z0-9._+-]*|[!a-zA-Z0-9]*) return 1;;
esac
return 0
}
# check if apkbuild is basically sane
default_sanitycheck() {
local i= j= suggestion=
local i= j=
msg "Checking sanity of $APKBUILD..."
[ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
if [ -z "$nodeps" ]; then
$APK version --check --quiet "$pkgver" ||\
die "$pkgver is not a valid version"
fi
$APK version --check --quiet -- "$pkgver"-r0 || \
die "$pkgver is not a valid version"
[ -z "$pkgrel" ] && die "Missing pkgrel in APKBUILD"
# give 0 as it is always valid and give the pkgrel
$APK version --check --quiet 0-r"$pkgrel" || \
die "$pkgrel is not a valid pkgrel"
# warn when p1 should be _p1
case "$pkgver" in
*[0-9]p[0-9]) warning "pkgver should probably be $(echo "$pkgver" | sed -E -e 's/(.*[0-9])p([0-9])/\1_p\2/')";;
# digit+letter+digit passes the apk2 version check
case $pkgver in
*[0-9][a-z][0-9]*)
die "the digit+letter+digit version format is invalid. Use suffixes instead"
;;
esac
[ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD"
[ -z "$url" ] && die "Missing url in APKBUILD"
[ -z "$license" ] && die "Missing license in APKBUILD"
@ -318,6 +319,9 @@ default_sanitycheck() {
check_secfixes_comment || return 1
makedepends_has 'g++' && ! options_has toolchain && warning "g++ should not be in makedepends"
if makedepends_has 'go' && ! options_has 'net'; then
warning "Go packages require network connection to build. Maybe add 'net' to options"
fi
if ! options_has "!check" && [ -n "$REQUIRE_CHECK" ]; then
(unset check; . "$APKBUILD"; type check >/dev/null 2>&1) || \
@ -606,13 +610,19 @@ subpkg_set() {
fi
}
arch2dir() {
local arch="$1"
[ "$arch" = "noarch" -o "$arch" = "all" ] && arch="$CARCH"
printf '%s\n' "$arch"
}
cleanpkg() {
local i
msg "Cleaning built packages..."
rm -f "$REPODEST/$repo/src/$pkgname-$pkgver-r$pkgrel.src.tar.gz"
for i in $allpackages; do
subpkg_set "$i"
rm -f "$REPODEST/$repo/${subpkgarch/noarch/$CARCH}/$subpkgname-$pkgver-r$pkgrel.apk"
rm -f "$REPODEST/$repo/$(arch2dir "$subpkgarch")/$subpkgname-$pkgver-r$pkgrel.apk"
done
subpkg_unset
@ -660,7 +670,7 @@ mkusers() {
# helper to update config.sub to a recent version
update_config_sub() {
find . -name config.sub | (local changed=false; while read f; do
if ! ./$f riscv64-alpine-linux-musl 2>/dev/null; then
if ! ./$f loongarch64-alpine-linux-musl 2>/dev/null; then
msg "Updating $f"
cp "$sharedir"/${f##*/} "$f" || return 1
changed=true
@ -673,7 +683,7 @@ update_config_sub() {
# helper to update config.guess to a recent version
update_config_guess() {
find . -name config.guess | (local changed=false; while read f; do
if grep -q aarch64 "$f" && grep -q ppc64le "$f" && grep -q riscv64 "$f"; then
if grep -q aarch64 "$f" && grep -q ppc64le "$f" && grep -q riscv64 "$f" && grep -q loongarch64 "$f"; then
msg "No update needed for $f"
else
msg "Updating $f"
@ -768,15 +778,18 @@ targz() {
}
postcheck() {
local dir="$1" name="$2" i= e=0
local dir="$1" name="$2" i= j= e=0
msg "Running postcheck for $name"
# checking for FHS compat
if ! options_has "!fhs"; then
for i in "$dir"/srv/* "$dir"/usr/local/* "$dir"/opt/*; do
if [ -e "$i" ]; then
error "Packages must not put anything under /srv, /usr/local or /opt"
e=1
fi
for i in srv usr/local opt tmp var/tmp var/lock var/empty home sys proc mnt dev; do
for j in "$dir"/"$i"/* "$dir"/"$i"/.[!.]* "$dir"/"$i"/..?*; do
if [ -L "$j" ] || [ -e "$j" ]; then
error "Packages must not put anything under /$i"
e=1
break
fi
done
done
if [ -d "$dir"/usr/var ]; then
error "Found /usr/var, localstatedir is most likely wrong"
@ -830,7 +843,7 @@ postcheck() {
warning "Found /usr/share/man but package name doesn't end with -doc"
fi
# check for uncompressed man pages
i=$(find "$dir"/usr/share/man -name '*.[0-8]' -type f | sed "s|^$dir|\t|")
i=$(find "$dir"/usr/share/man -name '*.[0-8]' -type f | sed -e 's/^/\t/')
if [ -n "$i" ]; then
error "Found uncompressed man pages:"
echo "$i"
@ -853,7 +866,7 @@ postcheck() {
e=1
fi
# check directory permissions
i=$(find "$dir" -type d -perm -777 | sed "s|^$dir|\t|")
i=$(find "$dir" -type d -perm -777 | sed -e 's/^/\t/')
if [ -n "$i" ]; then
warning "World writeable directories found:"
echo "$i"
@ -861,7 +874,7 @@ postcheck() {
# check so we dont have any suid root binaries that are not PIE
i=$(find "$dir" -type f -perm /6000 \
| xargs scanelf --nobanner --etype ET_EXEC \
| sed "s|ET_EXEC $dir|\t|")
| sed -e 's/ET_EXEC /\t/')
if [ -n "$i" ]; then
warning "Found non-PIE files that have SUID:"
echo "$i"
@ -1034,12 +1047,12 @@ check_maintainer() {
check_license() {
local ret=0
local license_list=/usr/share/spdx/license.lst
local exclude="AND OR WITH ( )"
if options_has "!spdx" || ! [ -f "$license_list" ]; then
return 0
fi
local IFS="$IFS()"
local i; for i in $license; do
list_has "$i" $exclude && continue
list_has "$i" AND OR WITH && continue
if ! grep -q -x -F "$i" "$license_list"; then
ret=1
warning "\"$i\" is not a known license"
@ -1084,7 +1097,7 @@ check_depends_dev() {
check_provides() {
local i
for i in $provides; do
if [ "${i%%[<>=]*}" = "$pkgname" ]; then
if [ "${i%%[<>=~]*}" = "$pkgname" ]; then
return 1
fi
done
@ -1145,7 +1158,6 @@ prepare_metafiles() {
if [ -n "$FAKEROOTKEY" ]; then
echo "# using $($FAKEROOT -v)" >> "$pkginfo"
fi
echo "# $(date -u -d @$SOURCE_DATE_EPOCH)" >> "$pkginfo"
cat >> "$pkginfo" <<-EOF
pkgname = $name
pkgver = $pkgver-r$pkgrel
@ -1287,6 +1299,13 @@ prepare_command_provides() {
if ! [ -x "$i" ] || ! [ -f "$i" ]; then
continue
fi
# exclude any provides: lines for commands that has '@' because '@'
# is used as seperator between command name and repository. This
# avoids potential conflicts
# ref: https://gitlab.alpinelinux.org/alpine/abuild/-/issues/10074
case "$i" in
*@*) continue;;
esac
local f=${i##*/}
echo $f >> "$controldir"/.provides-command
done
@ -1479,14 +1498,6 @@ trace_apk_deps() {
autodeps="$autodeps pkgconfig"
fi
# special case for libpthread: we need depend on libgcc
if [ "$CLIBC" = "uclibc" ] && [ -f "$dir"/.needs-so ] \
&& grep -q -w '^libpthread.so.*' "$dir"/.needs-so \
&& ! grep -q -w "^depend = libgcc" "$dir"/.PKGINFO; then
autodeps="$autodeps libgcc"
msg " added libgcc (due to libpthread)"
fi
[ -f "$dir"/.needs-so ] && for i in $(cat "$dir"/.needs-so); do
# first check if its provided by same apkbuild
grep -q -w "^$sonameprefix$i" "$dir"/.provides-so 2>/dev/null && continue
@ -1736,7 +1747,7 @@ scan_python3_dependency() {
fi
local pyver="${site_pkg_dir##*usr/lib/python}"
pyver="${pyver%%/*}"
if [ -n "$pyver" ]; then
if [ -n "$pyver" ] && [ "${subpkgname:-$pkgname}" != python3 ]; then
echo "python3~$pyver" \
>> "$controldir"/.python3-needs
fi
@ -1776,12 +1787,14 @@ human_size() {
create_apks() {
local file= dir= name= ver= apk= datadir= size=
local gzip=$(command -v pigz || echo gzip)
rmdir "$pkgdir"/usr/lib \
"$pkgdir"/usr/bin \
"$pkgdir"/usr/share \
"$pkgdir"/usr \
"$pkgdir"/etc/ \
2>/dev/null || :
if ! options_has "keepdirs"; then
rmdir "$pkgdir"/usr/lib \
"$pkgdir"/usr/bin \
"$pkgdir"/usr/share \
"$pkgdir"/usr \
"$pkgdir"/etc/ \
2>/dev/null || :
fi
if ! options_has "!tracedeps"; then
for file in "$pkgbasedir"/.control.*/.PKGINFO; do
dir="${file%/.PKGINFO}"
@ -1853,8 +1866,8 @@ create_apks() {
abuild-sign -q control.tar.gz || exit 1
msg "Create $apk"
mkdir -p "$REPODEST"/$repo/${subpkgarch/noarch/$CARCH}
cat control.tar.gz data.tar.gz > "$REPODEST"/$repo/${subpkgarch/noarch/$CARCH}/$apk
mkdir -p "$REPODEST/$repo/$(arch2dir "$subpkgarch")"
cat control.tar.gz data.tar.gz > "$REPODEST/$repo/$(arch2dir "$subpkgarch")/$apk"
)
done
}
@ -1896,9 +1909,9 @@ update_abuildrepo_index() {
##NOARCH: These packages are really in $CARCH and do not need their
# own repository. --rewrite-arch is used below to make sure the index
# thinks they are for $CARCH and apk-tools will fetch them from
# correct URL path. Remainder of the script uses ${subpkgarch/noarch/$CARCH}
# correct URL path. Remainder of the script uses $(arch2dir "$subpkgarch")
# when expanding to the target repository path.
[ "$subpkgarch" = "noarch" ] && subpkgarch="$CARCH"
[ "$subpkgarch" = "noarch" -o "$subpkgarch" = "all" ] && subpkgarch="$CARCH"
list_has "$subpkgarch" "$allarch" || allarch="$allarch $subpkgarch"
done
subpkg_unset
@ -2290,17 +2303,12 @@ check_arch() {
return $ret
}
# return true if libc is not masked in options
check_libc() {
! options_has "!libc_$CLIBC"
}
# check if package is up to date
apk_up2date() {
local i s
for i in $allpackages; do
subpkg_set "$i"
if [ ! -f "$REPODEST/$repo/${subpkgarch/noarch/$CARCH}/$subpkgname-$pkgver-r$pkgrel.apk" ]; then
if [ ! -f "$REPODEST/$repo/$(arch2dir "$subpkgarch")/$subpkgname-$pkgver-r$pkgrel.apk" ]; then
subpkg_unset
return 1
fi
@ -2315,7 +2323,7 @@ apk_up2date() {
else
s="$startdir/${i##*/}"
fi
if [ "$s" -nt "$REPODEST/$repo/${pkgarch/noarch/$CARCH}/$pkgname-$pkgver-r$pkgrel.apk" ]; then
if [ "$s" -nt "$REPODEST/$repo/$(arch2dir "$pkgarch")/$pkgname-$pkgver-r$pkgrel.apk" ]; then
return 1
fi
done
@ -2327,7 +2335,7 @@ abuildindex_up2date() {
for i in $allpackages; do
subpkg_set "$i"
local dir="$REPODEST"/$repo/${subpkgarch/noarch/$CARCH}
local dir="$REPODEST/$repo/$(arch2dir "$subpkgarch")"
local idx="$dir"/APKINDEX.tar.gz
local file="$dir"/$subpkgname-$pkgver-r$pkgrel.apk
@ -2345,7 +2353,6 @@ abuildindex_up2date() {
up2date() {
check_arch || return 0
check_libc || return 0
apk_up2date && abuildindex_up2date
}
@ -2359,17 +2366,17 @@ calcdeps() {
builddeps="$builddeps $i"
done
for i in $EXTRADEPENDS_HOST $EXTRADEPENDS_TARGET $makedepends_host; do
[ "$pkgname" = "${i%%[<>=]*}" ] && continue
[ "$pkgname" = "${i%%[<>=~]*}" ] && continue
list_has $i $hostdeps && continue
subpackages_has ${i%%[<>=]*} || hostdeps="$hostdeps $i"
subpackages_has ${i%%[<>=~]*} || hostdeps="$hostdeps $i"
done
else
[ -z "$makedepends" ] && makedepends="$makedepends_build $makedepends_host"
want_check && makedepends="$makedepends $checkdepends"
for i in $EXTRADEPENDS_BUILD $EXTRADEPENDS_HOST $1 $depends $makedepends; do
[ "$pkgname" = "${i%%[<>=]*}" ] && continue
[ "$pkgname" = "${i%%[<>=~]*}" ] && continue
list_has $i $builddeps && continue
subpackages_has ${i%%[<>=]*} || builddeps="$builddeps $i"
subpackages_has ${i%%[<>=~]*} || builddeps="$builddeps $i"
done
hostdeps="$EXTRADEPENDS_TARGET"
fi
@ -2507,23 +2514,19 @@ rootbld() {
return
fi
apk info -eq abuild-rootbld || die "rootbld: abuild-rootbld package not installed"
$APK info -eq abuild-rootbld || die "rootbld: abuild-rootbld package not installed"
[ $CBUILD = $CHOST ] || die "rootbld: set CBUILD=$CHOST to build for $CHOST"
if ! [ $CBUILD_ARCH = "$(apk --print-arch)" ]; then
local cachedir=/etc/apk/cache
if ! [ $CBUILD_ARCH = "$($APK --print-arch)" ]; then
# cross-building, so check for binfmt registration
local qarch="$(rootbld_qemu_arch)"
if ! [ -f "/proc/sys/fs/binfmt_misc/$qarch" ]; then
if ! [ -f "/proc/sys/fs/binfmt_misc/qemu-$qarch" ]; then
warning "rootbld: binfmt registration missing for $qarch binaries"
fi
# TODO: it's not safe to mix a cache dir between architectures,
# so we have to use something other than /etc/apk/cache
# to get a cache when cross-qemu-building.
#local cachedir=""
else
# not cross-building in qemu, so use host cache
local cachedir="/etc/apk/cache"
# Old versions of apk have cache conflicts
$APK info -eq 'cmd:apk>=2.14.1' || cachedir=""
fi
logcmd "chroot building building $repo/$pkgname-$pkgver-r$pkgrel"
@ -2622,7 +2625,10 @@ rootbld() {
--setenv CARCH "$CARCH" \
--setenv HOME "$HOME" \
--setenv REPODEST "$REPODEST" \
--setenv SRCDEST "$SRCDEST" \
--setenv ABUILD_USERDIR "$ABUILD_USERDIR" \
${ABUILD_BOOTSTRAP:+--setenv ABUILD_BOOTSTRAP "$ABUILD_BOOTSTRAP"} \
${APORTS_BOOTSTRAP:+--setenv APORTS_BOOTSTRAP "$APORTS_BOOTSTRAP"} \
--setenv SOURCE_DATE_EPOCH "$SOURCE_DATE_EPOCH" \
--setenv ABUILD_LAST_COMMIT "$ABUILD_LAST_COMMIT" \
--setenv PATH ${USE_CCACHE:+/usr/lib/ccache/bin:}/bin:/usr/bin:/sbin:/usr/sbin \
@ -2716,7 +2722,7 @@ deplist_has() {
local i
shift
for i in $@; do
i=${i%%[<>=]*}
i=${i%%[<>=~]*}
[ "$needle" = "$i" ] && return 0
[ "$needle" = "!$i" ] && return 1
done
@ -2772,12 +2778,9 @@ uninstalldeps() { undeps; }
index() { update_abuildrepo_index; }
all() {
if ! [ -n "$force" ]; then
if ! check_arch; then
echo "Package not available for the target architecture ($CARCH). Aborting."
return 0
fi
check_libc || return 0
if ! [ -n "$force" ] && ! check_arch; then
echo "Package not available for the target architecture ($CARCH). Aborting."
return 0
fi
if up2date && [ -z "$force" ]; then
msg "Package is up to date"
@ -2840,7 +2843,7 @@ usage() {
-c Enable colored output
-d Disable dependency checking
-D Set APKINDEX description (default: \$repo \$(git describe))
-f Force specified cmd (skip checks: apk up to date, arch, libc)
-f Force specified cmd (skip checks: apk up to date, arch)
-F Force run as root
-h Show this help
-k Keep built packages, even if APKBUILD or sources are newer
@ -2848,7 +2851,7 @@ usage() {
-m Disable colors (monochrome)
-P Set REPODEST as the repository location for created packages
-q Quiet
-r Install missing dependencies from system repository (using sudo)
-r Install missing dependencies from system repository (using \$SUDO_APK)
-s Set source package destination directory
-v Verbose: show every command as it is run (very noisy)
@ -2864,7 +2867,7 @@ usage() {
fetch Fetch sources to \$SRCDEST (consider: 'abuild fetch verify')
index Regenerate indexes in \$REPODEST
listpkg List target packages
package Install project into $pkgdir
package Install project into \$pkgdir
prepare Apply patches
rootbld Build package in clean chroot
rootpkg Run 'package', the split functions and create apks as fakeroot
@ -2938,7 +2941,7 @@ repo=${startdir%/*}
repo=${repo##*/}
aportsgit=${APORTSDIR:-${startdir}}
repo_template=$aportsgit/$repo/.rootbld-repositories
repo_template=$startdir/../.rootbld-repositories
SRCDEST=${SRCDEST:-$startdir}

53
abump.1.scd Normal file
View File

@ -0,0 +1,53 @@
abump(1)
# NAME
*abump* - bump pkgver in an APKBUILD file
# SYNOPSIS
*abump* [-s _CVE-1_,...] [-f _ISSUE_] [-k|--keep] _PKGNAME-1.2.3_
# DESCRIPTION
*abump* updates the *pkgver* in an APKBUILD file, updates its checksums,
rebuilds it, and finally creates a new commit commit with the changes resulting.
*abump* operates looks for the specified package in nested directories inside
the current working, assuming a layout like that of the aports repository.
# OPTIONS
*-s, --security CVE1,...*
Include CVE in the *secfixes* comment section.
*-f, --fixes ISSUE*
Include *Fixes #ISSUE* in the commit message. This will close the upstream
issue when the commit is merged into the aports master branch.
*-k, --keep*
Keep existing packages.
*-h, --help*
Print help information and exit.
# ENVIRONMENT
APORTSDIR
Force operating on an alternate directory.
# EXAMPLES
```
abump mml-1.0.0
abump glibmm2.68-2.78.0
abump telegram-desktop-4.11.8
```
# SEE ALSO
abuild(1), apkgrel(1), newapkbuild(1), APKBUILD(5), apk(8).
# AUTHORS
Natanael Copa <_ncopa@alpinelinux.org_> and open source contributors.

View File

@ -73,8 +73,8 @@ fixes #${fixes#\#}
fi
msg "$message"
sed -i -e "s/^pkgver=.*/pkgver=$ver/" \
-e "s/^pkgrel=.*/pkgrel=0/" \
sed -i -e "s/^pkgver=[^ ]*/pkgver=$ver/" \
-e "s/^pkgrel=[^ ]*/pkgrel=0/" \
APKBUILD
$ABUILD $abuild_opts checksum all
@ -96,7 +96,7 @@ fixes #${fixes#\#}
usage() {
cat <<-__EOF__
$program $program_version - bump pkgver in APKBUILDs
Usage: $program [-s CVE-1,CVE-2,...] [-f ISSUE] [-R|--recursive] [-k|--keep] PKGNAME-1.2.3 ...
Usage: $program [-s CVE-1,CVE-2,...] [-f ISSUE] [-k|--keep] PKGNAME-1.2.3 ...
Options:
-s, --security CVE1,CVE-2,... Security update
-f, --fixes ISSUE Fixes ISSUE

File diff suppressed because it is too large Load Diff

View File

@ -4,50 +4,52 @@ use strict;
use warnings;
use autodie qw(:all);
use feature qw(:5.14);
use experimental 'switch';
use LWP::UserAgent;
use LWP::ConnCache;
use JSON;
use URI;
use Text::Wrap qw(wrap $columns);
use File::Basename qw(dirname);
our $packager = '';
my %pkgmap = ();
my %licenses = ();
my $template = <<'EOF';
# Automatically generated by apkbuild-pypi, template 3
# Automatically generated by apkbuild-pypi, template 4
[% authors %]
pkgname=[% pkgname %]
#_pkgreal is used by apkbuild-pypi to find modules at PyPI
_pkgreal=[% pkgreal %]
pkgver=[% pkgver %]
pkgrel=[% pkgrel %]
#_pkgreal is used by apkbuild-pypi to find modules at PyPI
_pkgreal=[% pkgreal %]
pkgdesc="[% pkgdesc %]"
provides="[% provides %]"
replaces="[% replaces %]"
url="http://packages.python.org/pypi/[% pkgreal %]"
url="[% url %]"
arch="noarch"
license="[% license %]"
depends="python3"
checkdepends="python3-dev"
makedepends="py3-setuptools"
subpackages=""
depends=""
makedepends="py3-gpep517 py3-setuptools py3-wheel"
checkdepends="py3-pytest"
subpackages="$pkgname-pyc"
source="[% source %]"
builddir="$srcdir/$_pkgreal-$pkgver"
builddir="[% builddir %]"
options="[% options %]"[% options_comment %]
[% compatibility %]
build() {
python3 setup.py build
gpep517 build-wheel \
--wheel-dir .dist \
--output-fd 3 3>&1 >&2
}
check() {
python3 setup.py test
python3 -m venv --clear --without-pip --system-site-packages .testenv
.testenv/bin/python3 -m installer .dist/*.whl
.testenv/bin/python3 -m pytest
}
package() {
PYTHONPATH=$pkgdir`python3 -c "import site; print(site.getsitepackages()[0])"` \
python3 setup.py install \
--prefix=/usr \
--root="$pkgdir" \
--single-version-externally-managed
python3 -m installer -d "$pkgdir" \
.dist/*.whl
}
EOF
@ -73,14 +75,31 @@ sub read_assignments_from_file {
my %mline = $text =~ /^(\w+)\s*=\s*\"([^\"]*)\".*$/mg;
my %hash = ( %sline, %mline );
my $authors = join("\n", $text =~ /^# Contributor: .*$/mg, $text =~ /^# Maintainer: .*$/mg);
return \%hash if $filename ne 'APKBUILD';
my $authors = join( "\n",
$text =~ /^# Contributor: .*$/mg,
$text =~ /^# Maintainer: .*$/mg );
$hash{'authors'} = $authors if length($authors) > 1;
my $provides = $text =~ m/provides=\"(.*)\"".*/mg;
$hash{'provides'} = $1 if length($provides) >= 1;
if ($text =~ m/^provides=\"(.*)\"(.*)$/m) {
$hash{'provides'} = $1;
$hash{'provides_comment'} = $2;
}
my $requires = $text =~ m/^requires=\"(.*)\"".*$/mg;
$hash{'requires'} = $1 if length($requires) >= 1;
if ($text =~ m/^replaces=\"(.*)\"(.*)$/m) {
$hash{'replaces'} = $1;
$hash{'replaces_comment'} = $2;
}
# workaround for `builddir="$srcdir"/$_pkgname-$pkgver`
if ($text =~ m/^builddir=\"(.*)\"([^\s]*)/m) {
$hash{'builddir'} = $1 . $2;
}
if ($text =~ m/^options=\"(.*)\"(.*)$/m) {
$hash{'options'} = $1;
$hash{'options_comment'} = $2;
}
return \%hash;
}
@ -94,6 +113,7 @@ sub map_pypi_to_apk {
sub map_license {
my ($license) = @_;
$license //= '';
$license =~ s/ or / /g;
return $license;
@ -101,48 +121,131 @@ sub map_license {
sub get_source {
my ($distdata) = @_;
my $pkgname = $distdata->{info}{name};
my $source;
for my $url (@{$distdata->{urls}}) {
return $url->{url} if $url->{python_version} eq 'source'
if ($url->{python_version} eq 'source') {
$source = URI->new($url->{url});
last;
}
}
die "Unable to locate sources for $pkgname.\n" unless $source;
my $filename = ($source->path_segments)[-1];
my $pretty_path = substr($pkgname, 0, 1) . "/$pkgname";
my $pretty_url = $source->clone;
$pretty_url->path("/packages/source/$pretty_path/$filename");
my $response = $ua->head($pretty_url);
if ($response->is_success) {
return $pretty_url->as_string;
} else {
return $source->as_string;
}
die "Unable to locate sources for $distdata->{name}.\n";
}
sub read_apkbuild {
return read_assignments_from_file('APKBUILD');
}
sub format_line {
my $line = shift;
return "\t" . $line . "\n";
}
sub format_source {
my $srcurl = shift;
my $orig_src = shift;
$orig_src =~ s/^\s+//mg;
$orig_src =~ s/\s+/ /g;
my @sources = split (/\s/, $orig_src);
return $srcurl if @sources <= 1;
shift @sources if $sources[0] =~ m/pkgver/;
my $patches;
for my $patch (@sources) {
next if $patch eq "";
$patches .= format_line($patch);
}
return $srcurl . "\n" . ($patches // '') . "\t";
}
sub write_apkbuild {
my ($distdata, $apkbuild) = @_;
my $replaces = undef;
my $provides = undef;
my $authors = undef;
my $license = undef;
my $url = undef;
my $pkgname = undef;
my $pkgdesc = undef;
my $pkgrel = 0;
my $builddir = undef;
my $options = undef;
my $options_comment = undef;
my $orig_source = "";
if (our $use_homepage) {
$url =
$distdata->{info}{project_urls}{Homepage}
|| $distdata->{info}{home_page};
}
if (defined $apkbuild) {
$authors = $apkbuild->{authors};
$provides = $apkbuild->{provides};
$replaces = $apkbuild->{replaces};
$license = $apkbuild->{license};
$url = $apkbuild->{url};
$pkgname = $apkbuild->{pkgname};
$pkgdesc = $apkbuild->{pkgdesc};
$pkgrel = $apkbuild->{pkgrel};
$builddir = $apkbuild->{builddir};
$options = $apkbuild->{options} if defined $apkbuild->{options};
$options_comment = $apkbuild->{options_comment} if defined $apkbuild->{options_comment};
$orig_source = $apkbuild->{source};
if ($apkbuild->{pkgver} eq $distdata->{info}{version}) {
$pkgrel++;
}
}
my $pkgreal = $distdata->{info}{name};
my $srcurl = get_source($distdata);
my %repl = (
authors => ($authors or "# Contributor: $packager\n# Maintainer: $packager"),
pkgname => map_pypi_to_apk($distdata->{info}{name}),
pkgreal => $distdata->{info}{name},
pkgname => ($pkgname or map_pypi_to_apk($pkgreal)),
pkgreal => $pkgreal,
pkgver => $distdata->{info}{version},
pkgrel => $pkgrel,
source => get_source($distdata),
license => map_license($distdata->{info}{license}),
pkgdesc => $distdata->{info}{summary},
provides => ($provides or ''),
replaces => ($replaces or ''),
source => format_source($srcurl, $orig_source),
license => ($license or map_license($distdata->{info}{license})),
url => ($url or "https://pypi.org/project/${pkgreal}/"),
pkgdesc => ($pkgdesc or $distdata->{info}{summary} or "Python module for $pkgreal"),
builddir => ($builddir or ''),
options => ($options or ''),
options_comment => ($options_comment or ''),
);
$repl{compatibility} = "";
if ($replaces) {
my $comment = $apkbuild->{'replaces_comment'} // '';
$repl{compatibility} .= "\nreplaces=\"$replaces\"" . $comment;
}
if ($provides) {
my $comment = $apkbuild->{'provides_comment'} // '';
$repl{compatibility} .= "\nprovides=\"$provides\"" . $comment;
}
$repl{compatibility} .= "\n" if $replaces or $provides;
$repl{source} =~ s/-$repl{pkgver}/-\$pkgver/g;
$template =~ s/\[% (.*?) %\]/$repl{$1}/g;
open my $fh, '>:utf8', 'APKBUILD';
@ -154,8 +257,15 @@ sub write_apkbuild {
return \%repl;
}
sub unpack_source {
system('abuild checksum unpack');
}
sub prepare_tree {
system('abuild checksum unpack prepare');
my %options = @_;
unpack_source if $options{unpack};
system('abuild prepare');
}
sub find_package_name {
@ -188,42 +298,172 @@ sub find_package_name {
sub get_data {
my ($package) = @_;
my $response = $ua->get("https://pypi.python.org/pypi/$package/json");
my $response = $ua->get("https://pypi.org/pypi/$package/json");
$response->is_success or die $response->status_line;
my $distdata = $json->decode($response->decoded_content);
return $distdata;
}
sub get_deps {
my ($data) = @_;
sub parse_requires_dist {
my $reqs = shift;
chdir "src/$data->{pkgreal}-$data->{pkgver}";
my $reqs = `python3 ./setup.py --requires`;
# Valid PyPI regex: https://peps.python.org/pep-0508/#names
my $pypi_regex = qr/(?i)([A-Z0-9][A-Z0-9][A-Z0-9._-]*[A-Z0-9])/;
my @reqs = split /\n/, $reqs;
my @depends =
map { m/$pypi_regex/; $1 || () }
grep { $_ !~ m/; extra ==/ }
@$reqs;
foreach my $i (0 .. $#reqs) {
$reqs[$i] =~ s/(\(|\s+).*$//;
$reqs[$i] = map_pypi_to_apk($reqs[$i]);
my @checkdeps =
map { m/$pypi_regex/; $1 || () }
grep { m/; extra == ["'](tests|pytest)["']/ }
@$reqs;
my %reqs = (
depends => \@depends,
checkdeps => \@checkdeps,
);
return \%reqs;
}
sub format_depends {
my $deps = shift;
$columns = 102;
$deps =~ s/ {2,}/ /g;
$deps =~ s/^\s//g;
$deps =~ s/\s$//g;
if ( length($deps) >= $columns ) {
$deps = wrap( "\t", "\t", $deps );
}
$deps =~ s/\s$//g;
chdir '../..';
if ( length($deps) >= $columns ) {
$deps = "\n" . $deps . "\n\t";
}
return $deps;
}
sub get_deps {
my ($distdata, $data) = @_;
my $reqs = parse_requires_dist($distdata->{info}{requires_dist});
my %depends = ('py3-pytest' => 'py3-pytest');
my @depends =
map {
my $apkname = map_pypi_to_apk($_);
if (exists $depends{$apkname}) { () }
else { $depends{$apkname} = $apkname }
}
@{$reqs->{depends}};
my @checkdeps =
map {
my $apkname = map_pypi_to_apk($_);
exists($depends{$apkname}) ? () : $apkname
}
@{$reqs->{checkdeps}};
my $apk = read_file('APKBUILD');
$reqs = join ' ', @reqs;
my $depends = format_depends(join ' ', @depends);
$apk =~ s/pymakedepends=""/pymakedepends="$reqs"/;
$apk =~ s/^depends=""/depends="$depends"/m;
unshift @checkdeps, 'py3-pytest';
my $checkdeps = format_depends(join ' ', @checkdeps);
$apk =~ s/^checkdepends="py3-pytest"/checkdepends="$checkdeps"/m;
# remove empty variables
$apk =~ s/.*=""\n//g;
$apk =~ s/.*="".{0,}\n//g;
open my $fh, '>:utf8', 'APKBUILD';
print $fh $apk;
say "Requires: $reqs";
say "Requires: @depends\n\nCheckDepends: @checkdeps";
}
sub write_old_deps {
my ($data, $apkbuild) = @_;
my $apk = read_file('APKBUILD');
if (my $depends = $apkbuild->{depends}) {
$apk =~ s/^depends=".*"/depends="$depends"/m;
}
if (my $makedeps = $apkbuild->{makedepends}) {
if ($makedeps =~ m/py3-gpep517/) {
$apk =~ s/^makedepends=".*"/makedepends="$makedeps"/m;
} else {
$apk =~ s/^makedepends="(.*)"/makedepends="$1 $makedeps"/m;
}
}
if (my $checkdeps = $apkbuild->{checkdepends}) {
if ($checkdeps =~ m/py3-pytest/) {
$apk =~ s/^checkdepends=".*"/checkdepends="$checkdeps"/m;
} else {
$apk =~ s/^checkdepends="(.*)"/checkdepends="$1 $checkdeps"/m;
}
}
# remove empty variables
$apk =~ s/.*="".{0,}\n//g;
open my $fh, '>:utf8', 'APKBUILD';
print $fh $apk;
}
sub update_builddir {
my $apkbuild = read_apkbuild;
my $pkgreal = $apkbuild->{'_pkgreal'};
my $pkgname = $apkbuild->{pkgname};
my $pkgver = $apkbuild->{pkgver};
my $oldbuilddir = $apkbuild->{builddir};
my $build_path = glob("
src/*${pkgver}/pyproject.toml
src/*${pkgver}/setup.py
");
if ($build_path) {
my $newbuilddir = dirname($build_path);
$newbuilddir =~ s/src/\$srcdir/;
$newbuilddir =~ s/$pkgreal/\$_pkgreal/;
$newbuilddir =~ s/$pkgver/\$pkgver/;
my $apk = read_file('APKBUILD');
if ($pkgname eq $pkgreal and
$newbuilddir eq '$srcdir/$_pkgreal-$pkgver') {
# this will be deleted by the remove empty
# variables regex in get_deps/write_old_deps
$apk =~ s/^builddir=".*"/builddir=""/m;
$newbuilddir = '<same as default, deleted>';
} elsif ($newbuilddir eq $oldbuilddir) {
return;
} else {
$apk =~ s/^builddir=".*"/builddir="$newbuilddir"/m;
}
print "\n\$builddir redefined:\n\t",
"OLD: $oldbuilddir, NEW: $newbuilddir\n\n";
open my $fh, '>:utf8', 'APKBUILD';
print $fh $apk;
}
}
my $abuild_conf = read_assignments_from_file('/etc/abuild.conf');
@ -234,95 +474,104 @@ $packager = $user_abuild_conf->{PACKAGER} if $user_abuild_conf->{PACKAGER};
sub usage {
say <<'EOF';
Usage: apkbuild-pypi [create <package> | check | recreate | upgrade | update]
Usage: apkbuild-pypi [create <package> [homepage] | check | recreate [deps] | upgrade | update]
In the repository root:
create <package>: Creates an APKBUILD for <package>
create <package> homepage: Creates an APKBUILD for <package> with url= field set to project homepage, if available
In the package root:
check : Reports current & latest version of the package
recreate : Recreates the APKBUILD
recreate [deps] : Recreates the APKBUILD [also recalculate dependencies]
upgrade : Upgrades to the latest version of the package
update : Updates APKBUILD metadata
EOF
}
given ($ARGV[0]) {
when ('create') {
my $package = $ARGV[1];
$package or die usage;
if (! defined $ARGV[0]) {
die usage;
} elsif ($ARGV[0] eq 'create') {
my $package = $ARGV[1];
$package or die usage;
my $distdata = get_data($package);
my $apkname = map_pypi_to_apk($package);
my $distdata = get_data($package);
my $apkname = map_pypi_to_apk($package);
mkdir $apkname;
chdir $apkname;
mkdir $apkname;
chdir $apkname;
my $data = write_apkbuild($distdata, undef);
prepare_tree;
if ($ARGV[2] and $ARGV[2] eq 'homepage') { our $use_homepage = 1; }
get_deps($data);
} when ('recreate') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version} =~ s/^[^0-9]+//r;
if ($pkgver ne $apkbuild->{pkgver}) {
#Reset pkgrel on upgrade on recreate
say "Upgrading PyPI module from $apkbuild->{pkgver} to $pkgver";
$apkbuild->{pkgrel}=0;
}
my $data = write_apkbuild($distdata, $apkbuild);
my $data = write_apkbuild($distdata, undef);
unpack_source;
update_builddir;
prepare_tree;
get_deps($data);
} when ('upgrade') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version};
if ($pkgver ne $apkbuild->{pkgver}) {
say "Upgrading PyPI package from $apkbuild->{pkgver} to $pkgver";
my $text = read_file('APKBUILD');
$text =~ s/^(pkgver)=.*$/$1=$pkgver/mg or
die "Can't find pkgver line in APKBUILD";
$text =~ s/^(pkgrel)=.*$/$1=0/mg or
die "Can't find pkgrel line in APKBUILD";
open my $fh, '>:utf8', 'APKBUILD';
print $fh $text;
close $fh;
} else {
say "Already up to date with PyPI";
}
} when ('check') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version};
say "$apkbuild->{pkgname}: Latest version: $pkgver Packaged version: $apkbuild->{pkgver}";
if ($pkgver ne $apkbuild->{pkgver}) {
exit(1);
}
} when ('update') {
prepare_tree;
} default {
die usage;
get_deps($distdata, $data);
prepare_tree( unpack => 0 );
} elsif ($ARGV[0] eq 'recreate') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version} =~ s/^[^0-9]+//r;
if ($pkgver ne $apkbuild->{pkgver}) {
#Reset pkgrel on upgrade on recreate
say "Upgrading PyPI module from $apkbuild->{pkgver} to $pkgver";
$apkbuild->{pkgrel}=0;
}
my $data = write_apkbuild($distdata, $apkbuild);
unpack_source;
update_builddir;
if ($ARGV[1] and $ARGV[1] eq 'deps') { get_deps($distdata, $data); }
else { write_old_deps($data, $apkbuild); }
prepare_tree( unpack => 0 );
} elsif ($ARGV[0] eq 'upgrade') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version};
if ($pkgver ne $apkbuild->{pkgver}) {
say "Upgrading PyPI package from $apkbuild->{pkgver} to $pkgver";
my $text = read_file('APKBUILD');
$text =~ s/^(pkgver)=.*$/$1=$pkgver/mg or
die "Can't find pkgver line in APKBUILD";
$text =~ s/^(pkgrel)=.*$/$1=0/mg or
die "Can't find pkgrel line in APKBUILD";
open my $fh, '>:utf8', 'APKBUILD';
print $fh $text;
close $fh;
} else {
say "Already up to date with PyPI";
}
} elsif ($ARGV[0] eq 'check') {
my $apkbuild = read_apkbuild;
if (! defined $apkbuild->{_pkgreal}) {
$apkbuild->{_pkgreal} = find_package_name($apkbuild);
}
my $distdata = get_data($apkbuild->{_pkgreal});
my $pkgver = $distdata->{info}{version};
say "$apkbuild->{pkgname}: Latest version: $pkgver Packaged version: $apkbuild->{pkgver}";
if ($pkgver ne $apkbuild->{pkgver}) {
exit(1);
}
} elsif ($ARGV[0] eq 'update') {
prepare_tree( unpack => 1 );
} else {
die usage;
}

View File

@ -17,21 +17,41 @@ fi
usage() {
cat >&2 <<-__EOF__
cat <<-__EOF__
$program $program_version - find ABI breakages in package upgrades
Usage: $program
Usage: $program [-h|--help]
Run in the directory of a built package.
Options:
-h, --help Print this help
__EOF__
}
args=$(getopt -o h --long help \
-n "$program" -- "$@")
if [ $? -ne 0 ]; then
usage >&2
exit 2
fi
eval set -- "$args"
while true; do
case $1 in
-h|--help) usage; exit 0;;
--) shift; break;;
*) exit 1;; # getopt error
esac
shift
done
if [ $# -gt 0 ]; then
usage
usage >&2
exit 2
fi
if ! [ -f "$ABUILD_CONF" ] && ! [ -f "$ABUILD_USERCONF" ]; then
if ! [ -f "$ABUILD_CONF" ] && ! [ -f "$ABUILD_USERCONF" ] && ! [ -f "$ABUILD_DEFCONF" ]; then
die "no abuild.conf found"
fi
@ -47,7 +67,7 @@ fi
startdir="$PWD"
tmpdir=$(mktemp -d -t checkpkg-script.XXXXXX)
trap "rm -rf '$tmpdir'" INT EXIT
trap "rm -rf '$tmpdir'; exit" INT EXIT
cd "$tmpdir" || die "failed to create temp dir"
# storage for downloaded/copied apks
@ -79,11 +99,16 @@ for i in $pkgname $subpackages; do
fi
# For our local repo (newsize) apk info might return multiple packages, e.g. if different
# version of the package where build previously. Filter out this specific pkgver using awk.
newsize=$(apk info --repositories-file /dev/null --repository "$REPODEST"/$repo --size $_pkgname | \
awk "/^${pkg//+/\\+}/ { found = 1 } /^[0-9]+/ { if (found) { print \$0; exit } }")
oldsize=$(apk info --repositories-file "$tmpdir"/repositories --size "$_pkgname" | \
awk '/^[0-9]+/ { print $0 }' | head -1)
# version of the package where built previously. However, for a repo only one of pkgname=pkgver-rpkgrel can exist.
# Filter out this specific pkgver with grep, as it can have only one match, then take the second line:
# 7zip-23.01-r0 installed size:
# 1668 KiB
newsize="$(apk info --repositories-file /dev/null --repository "$REPODEST"/$repo --size $_pkgname | \
grep -F "$pkg" -A1 | \
tail -n1)"
oldsize="$(apk info --repositories-file "$tmpdir"/repositories --size "$_pkgname" | \
grep -F "$_pkgname" -A1 | \
tail -n1)"
if [ "$oldsize" = "$newsize" ]; then
msg "No size differences for $_pkgname."
@ -92,15 +117,17 @@ for i in $pkgname $subpackages; do
fi
apk fetch --quiet --repositories-file "$tmpdir"/repositories --stdout "$_pkgname" > apks/old.apk \
|| die "failed to download old pkg, maybe run 'apk update'?"
|| msg2 "Old apk for $_pkgname missing. (new package/arch? broken internet?)"
# pre-uncompress to not decompress twice
# we do a decompression + tar -t for the file list, but then later we might do a full extraction for sodiff.
# to not decompress here and then later again, store the intermediate tar
$gunzip -c 2>/dev/null < apks/old.apk > apks/old.tar
tar -t -f apks/old.tar 2>/dev/null | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-old"
$gunzip -c "$filepath" < "$filepath" > apks/new.tar
tar -t -f apks/new.tar | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-new"
$gunzip -c 2>/dev/null < apks/old.apk > apks/old.tar &
$gunzip -c "$filepath" < "$filepath" > apks/new.tar &
wait
tar -t -f apks/old.tar 2>/dev/null | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-old" &
tar -t -f apks/new.tar | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-new" &
wait
diff -U3 "filelist-$_pkgname-old" "filelist-$_pkgname-new"
@ -108,16 +135,22 @@ for i in $pkgname $subpackages; do
echo "SODIFF:"
mkdir -p "$_pkgname-pkg-old" "$_pkgname-pkg-new"
tar -C "$_pkgname-pkg-old" -x -f apks/old.tar > /dev/null
tar -C "$_pkgname-pkg-new" -x -f apks/new.tar > /dev/null
tar -C "$_pkgname-pkg-old" 2>/dev/null -x -f apks/old.tar > /dev/null &
tar -C "$_pkgname-pkg-new" -x -f apks/new.tar > /dev/null &
wait
# filter to things that start with -+ but strip the header (---/+++)
diff -U0 "filelist-$_pkgname-old" "filelist-$_pkgname-new" | grep -E '^(\+|\-)[A-Za-z0-9]+' | while read -r diff_sofile; do
diff -U0 "filelist-$_pkgname-old" "filelist-$_pkgname-new" | grep -E '^(\+|-)[A-Za-z0-9]+' | grep '\.so' | while read -r diff_sofile; do
case "$diff_sofile" in
-*) path="$_pkgname-pkg-old"; sofile="${diff_sofile#\-}" ;;
+*) path="$_pkgname-pkg-new"; sofile="${diff_sofile#\+}" ;;
esac
echo "$diff_sofile: " "$(objdump -p "$path"/"$sofile" | grep SONAME)"
# skip symlinks (only adds duplicate output or is dangling), and things that aren't valid elfs
# matching .so above matches anything with .so in the name, e.g. xyz.sourceforge
if ! [ -L "$path"/"$sofile" ] && readelf -h "$path"/"$sofile" >/dev/null 2>&1; then
echo "$diff_sofile: " "$(objdump -p "$path"/"$sofile" | grep SONAME)"
fi
done
else
msg "No soname differences for $_pkgname."

View File

@ -1,5 +1,6 @@
export CFLAGS="-Os -fstack-clash-protection -Wformat -Werror=format-security"
export CXXFLAGS="-Os -fstack-clash-protection -Wformat -Werror=format-security -D_GLIBCXX_ASSERTIONS=1"
export CXXFLAGS="-Os -fstack-clash-protection -Wformat -Werror=format-security"
export CXXFLAGS="$CXXFLAGS -D_GLIBCXX_ASSERTIONS=1 -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS=1 -D_LIBCPP_ENABLE_HARDENED_MODE=1"
export LDFLAGS="-Wl,--as-needed,-O1,--sort-common"
export GOFLAGS="-buildmode=pie -modcacherw -trimpath -buildvcs=false"
# Do note that these should work with at least GDC and LDC

View File

@ -98,11 +98,11 @@ readconfig() {
[ -n "${USE_COLORS+x}" ] && _USE_COLORS="$USE_COLORS"
[ -n "${USE_CCACHE+x}" ] && _USE_CCACHE="$USE_CCACHE"
: ${ABUILD_DEFCONF:=${ABUILD_SHAREDIR:-$sharedir}/default.conf}
[ -f "$ABUILD_DEFCONF" ] && . "$ABUILD_DEFCONF"
: ${ABUILD_CONF:=$sysconfdir/abuild.conf}
[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"
: ${ABUILD_USERDIR:=$HOME/.abuild}
: ${ABUILD_USERCONF:=$ABUILD_USERDIR/abuild.conf}
[ -f "$ABUILD_DEFCONF" ] && . "$ABUILD_DEFCONF"
[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"
[ -f "$ABUILD_USERCONF" ] && . "$ABUILD_USERCONF"
APORTSDIR=${_APORTSDIR-$APORTSDIR}

View File

@ -141,7 +141,7 @@ abuild_fetch_locking_body() {
pid1=\$!
# give enough time for abuild-fetch to call curl
sleep 0.2
sleep 0.5
# the first stamp should not exist, second instance should block the retry
if [ -e stamp3 ]; then

View File

@ -23,13 +23,17 @@ init_tests \
abuild_invalid_pkgnames \
abuild_invalid_subpkgnames \
abuild_invalid_subpkg_version \
abuild_provide_pkgname \
abuild_subpackage_arch \
abuild_large_doc_subpackage \
abuild_bigdocs \
abuild_warn_pkgver_patch_version \
abuild_pkgver_digit_letter_digit \
abuild_multiline_license \
abuild_license_spdx \
abuild_git_ceiling \
abuild_package_size_zero \
abuild_package_size_nonzero \
abuild_keepdirs \
abuild_amove \
abuild_doc \
abuild_dev \
@ -45,7 +49,8 @@ init_tests \
abuild_command_provides \
abuild_gocache_dir \
abuild_cargo_home_dir \
abuild_fish_comp_split
abuild_fish_comp_split \
abuild_deps
export ABUILD_SHAREDIR=$(atf_get_srcdir)/..
export ABUILD_CONF=/dev/null
@ -411,6 +416,9 @@ abuild_valid_pkgnames_body() {
TESTSUBNAME=foo atf_check -s exit:0 \
-e match:"Checking sanity" \
abuild sanitycheck
TESTNAME="more_+-2.0-complicated" atf_check -s exit:0 \
-e match:"Checking sanity" \
abuild sanitycheck
}
abuild_invalid_pkgnames_body() {
@ -426,6 +434,12 @@ abuild_invalid_pkgnames_body() {
TESTNAME="foo with spaces" atf_check -s exit:1 \
-e match:"Checking sanity" \
abuild sanitycheck
TESTNAME="width@at" atf_check -s exit:1 \
-e match:"Checking sanity" \
abuild sanitycheck
TESTNAME="width=equal" atf_check -s exit:1 \
-e match:"Checking sanity" \
abuild sanitycheck
}
abuild_invalid_subpkgnames_body() {
@ -449,6 +463,42 @@ abuild_invalid_subpkg_version_body() {
abuild all
}
abuild_provide_pkgname_body() {
init_keys
cp -ra "$testrepo"/test-pkgname .
cd test-pkgname
TESTNAME=provided atf_check -s exit:1 \
-e match:"provides must not contain" \
abuild sanitycheck
TESTNAME=test TESTPROVIDES='test~1' atf_check -s exit:1 \
-e match:"provides must not contain" \
abuild sanitycheck
TESTNAME=test TESTPROVIDES='test=1' atf_check -s exit:1 \
-e match:"provides must not contain" \
abuild sanitycheck
TESTNAME=test TESTPROVIDES='test>1' atf_check -s exit:1 \
-e match:"provides must not contain" \
abuild sanitycheck
TESTNAME=test TESTPROVIDES='test<=1' atf_check -s exit:1 \
-e match:"provides must not contain" \
abuild sanitycheck
}
abuild_subpackage_arch_body() {
init_keys
cp -ra "$testrepo" .
cd testrepo/subpackage-arch
arch="$(abuild -A)"
for i in noarch all "$arch"; do
TESTSUBARCH="$i" abuild all
[ -f "$REPODEST/testrepo/$arch/test-pkgname-$i-1.0-r0.apk" ] || \
atf_fail "Failed to place $i arch subpackage correctly"
rm -rf "$REPODEST/testrepo"
done
}
abuild_large_doc_subpackage_body() {
init_keys
cp -ra "$testrepo"/large-doc-subpkg .
@ -467,14 +517,11 @@ abuild_bigdocs_body() {
abuild all
}
abuild_warn_pkgver_patch_version_body() {
abuild_pkgver_digit_letter_digit_body() {
cp -ra "$testrepo"/test-pkgname .
cd test-pkgname
TESTPKGVER=1.0_p1 atf_check -s exit:0 \
-e not-match:'WARNING' \
abuild sanitycheck
TESTPKGVER=1.0p1 atf_check -s exit:0 \
-e match:'WARNING.*1.0_p1' \
TESTPKGVER=1.0p1 atf_check -s exit:1 \
-e match:'ERROR.*version' \
abuild sanitycheck
}
@ -482,10 +529,18 @@ abuild_multiline_license_body() {
cp -ra "$testrepo"/test-licenses .
cd test-licenses
abuild rootpkg
atf_check -o match:'^license = MIT AND GPL-3.0-only OR GPL-3.0-or-later AND BSD-Clause-4$' \
atf_check -o match:'^license = MIT AND \(GPL-3.0-only OR GPL-3.0-or-later AND BSD-Clause-4\)$' \
cat pkg/.control.test-licenses/.PKGINFO
}
abuild_license_spdx_body() {
cp -ra "$testrepo"/test-licenses .
cd test-licenses
TESTPKGVER=1.0_p1 atf_check -s exit:0 \
-e not-match:'WARNING' \
abuild sanitycheck
}
abuild_git_ceiling_body() {
init_keys
git init
@ -587,6 +642,32 @@ abuild_package_size_nonzero_body() {
cat pkg/.control.test-size/.PKGINFO
}
abuild_keepdirs_body() {
init_keys
mkdir -p test-amove
cd test-amove
cat > APKBUILD <<-EOF
# Maintainer: Test User 123 <123@example.com>
# test package
pkgname="test-keepdirs"
pkgver="1.0"
pkgrel=0
pkgdesc='Dummy test package - keepdirs'
url='https://gitlab.alpinelinux.org/alpine/aports'
arch='noarch'
license='MIT'
options='keepdirs'
package() {
mkdir -p "\$pkgdir"/usr/bin
}
EOF
abuild rootpkg || atf_fail "abuild rootpkg failed"
test -d pkg/test-keepdirs/usr/bin || atf_fail "$i failed"
}
abuild_amove_body() {
init_keys
mkdir -p test-amove
@ -608,7 +689,8 @@ abuild_amove_body() {
\$pkgname-bin:_bin
\$pkgname-sbin:_sbin
\$pkgname-var:_var
\$pkgname-usr:_usr"
\$pkgname-usr:_usr
\$pkgname-space:_space"
package() {
mkdir -p "\$pkgdir"/etc \
@ -620,6 +702,7 @@ abuild_amove_body() {
"\$pkgdir"/etc/\$pkgname.conf \
"\$pkgdir"/bin/hello \
"\$pkgdir"/sbin/shello \
"\$pkgdir"/sbin/space' ' \
"\$pkgdir"/var/lib/\$pkgname/testfile \
"\$pkgdir"/usr/share/a \
"\$pkgdir"/usr/share/b
@ -647,6 +730,10 @@ abuild_amove_body() {
# glob *
amove usr/share/*
}
_space() {
# with space
amove sbin/space' '
}
EOF
abuild rootpkg || atf_fail "abuild rootpkg failed"
@ -658,8 +745,9 @@ abuild_amove_body() {
test-amove-var/var/lib/test-amove/testfile \
test-amove-usr/usr/share/a \
test-amove-usr/usr/share/b \
test-amove-space/sbin/space' ' \
; do \
test -f pkg/$i || atf_fail "$i failed"
test -f pkg/"$i" || atf_fail "$i failed"
done
}
@ -830,7 +918,7 @@ abuild_cleanoldpkg_body() {
mkdir -p "\$pkgdir"
}
EOF
CARCH=$arch atf_check -e not-empty abuild
CARCH=$arch atf_check -e not-empty abuild clean unpack rootpkg
done
done
@ -950,14 +1038,35 @@ abuild_setcap_binary_with_option_body() {
abuild_command_provides_body() {
init_keys
cp -ra "$testrepo"/bin-in-path .
cd bin-in-path
mkdir testprovides
cd testprovides
cat >APKBUILD<<-EOF
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=testprovides
pkgver=1.0
pkgrel=0
pkgdesc="Dummy test package that installs a file and directory in path"
url="https://gitlab.alpinelinux.org/alpine/aports"
arch="noarch"
license="MIT"
prepare() { mkdir -p "\$builddir"; }
build() { true; }
check() { true; }
package() {
mkdir -p "\$pkgdir/usr/bin"
printf "%s\n" '#!/bin/sh' >"\$pkgdir/usr/bin/foo"
chmod +x "\$pkgdir/usr/bin/foo"
cp -a "\$pkgdir/usr/bin/foo" "\$pkgdir/usr/bin/foo@"
mkdir -p "\$pkgdir/usr/bin/dir/"
}
EOF
abuild rootpkg
atf_check \
-o match:"provides = cmd:foo=1.0-r0" \
-o not-match:"provides = cmd:foo@=1.0-r0" \
-o not-match:"provides = cmd:dir=1.0-r0" \
grep '^provides = ' pkg/.control.bin-in-path/.PKGINFO
grep '^provides = ' pkg/.control.testprovides/.PKGINFO
}
abuild_gocache_dir_body() {
@ -984,6 +1093,7 @@ abuild_gocache_dir_body() {
}
EOF
unset GOCACHE
MOVE_CACHES=1 \
atf_check -s exit:0 \
-o match:"dir:.*/tmp/go" \
@ -1014,6 +1124,7 @@ abuild_cargo_home_dir_body() {
}
EOF
unset CARGO_HOME
MOVE_CACHES=1 \
atf_check -s exit:0 \
-o match:"dir:.*/tmp/cargo" \
@ -1061,3 +1172,74 @@ abuild_fish_comp_split_body() {
exit 1
fi
}
create_mock_apk() {
mkdir -p bin
cat > bin/apk <<-EOF
#!/bin/sh
if [ "\$1" = "--print-arch" ]; then
echo 'aarch64'
exit 0
fi
echo apk "\$@" >&2
EOF
chmod +x bin/apk
ln -s apk bin/abuild-apk
PATH="$PWD/bin:$PATH"
}
abuild_deps_body() {
create_mock_apk
mkdir testdeps
cd testdeps
cat >APKBUILD <<-EOF
# Maintainer: Joe User <juser@example.com>
pkgname="testdeps"
pkgver="1.0"
pkgrel=0
pkgdesc="Dummy test package"
url="https://gitlab.alpinelinux.org/alpine/aports"
arch="noarch"
license="MIT"
depends="foo"
makedepends="bar"
checkdepends="checkdep"
makedepends_host="hostdep"
makedepends_build="builddep"
EOF
# native build. pull in both depends and makedepends
# do not install in any --root
atf_check \
-e match:'Installing for build: foo bar checkdep$' \
-e match:'apk add .*--virtual .makedepends-testdeps foo bar checkdep' \
-e not-match:'apk add .*--root' \
abuild deps
# dont install checkdep with ABUILD_BOOTSTRAP
ABUILD_BOOTSTRAP=1 atf_check \
-e not-match:"apk add.*checkdep" \
abuild deps
# crosscompile:
# install makedepends_build without --root
# install makedepends_host with --root
CTARGET='s390x' CHOST='ppc64le' CBUILDROOT="$PWD/root" atf_check \
-e match:'Installing for build: builddep' \
-e match:'Installing for host: hostdep' \
-e match:'apk add .*--virtual .makedepends-testdeps builddep' \
-e not-match:'apk add.*--root.*builddep' \
-e match:'apk add .*--root.*hostdep' \
-e match:'apk add .*--arch s390x.*hostdep' \
-e not-match:'apk add.*checkdep' \
abuild deps
# crosscompile, set only CHOST
CHOST='armhf' atf_check \
-e match:'apk add.*builddep' \
-e not-match:'apk add.*--root.*builddep' \
-e match:'apk add.*--root.*--arch armhf.*hostdep' \
-e not-match:'apk add.*--arch armhf.*builddep' \
abuild deps
}

40
tests/checkapk_test Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env atf-sh
. $(atf_get_srcdir)/test_env.sh
init_tests \
checkapk_help \
checkapk_invalid_opt \
checkapk_missing_abuild_conf \
checkapk_missing_apkbuild
DATADIR=$(atf_get_srcdir)/testdata
export ABUILD_SHAREDIR=$(atf_get_srcdir)/..
export ABUILD_CONF=/dev/null
export ABUILD_USERCONF=/dev/null
checkapk_help_body() {
atf_check -s exit:0 \
-o match:"Usage:" \
checkapk --help
}
checkapk_invalid_opt_body() {
atf_check -s not-exit:0 \
-e match:"Usage:" \
checkapk --invalid
}
checkapk_missing_abuild_conf_body() {
ABUILD_DEFCONF=/dev/null atf_check \
-s not-exit:0 \
-e match:"no abuild.conf found" \
checkapk
}
checkapk_missing_apkbuild_body() {
atf_check \
-s not-exit:0 \
-e match:"must be run in the directory of a built package" \
checkapk
}

View File

@ -1,33 +0,0 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
# test package
pkgname=bin-in-path
pkgver=1.0
pkgrel=0
pkgdesc="Dummy test package that installs a file and directory in path"
url="https://gitlab.alpinelinux.org/alpine/aports"
arch="noarch"
license="MIT"
source=""
prepare() {
mkdir -p "$builddir"
}
build() {
true
}
check() {
true
}
package() {
mkdir -p "$pkgdir/usr/bin"
cat >"$pkgdir/usr/bin/foo" <<EOF
#!/bin/sh
EOF
chmod +x "$pkgdir/usr/bin/foo"
mkdir -p "$pkgdir/usr/bin/dir/"
}

View File

@ -0,0 +1,24 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
# test package
pkgname=${TESTNAME-test-pkgname}
pkgver="${TESTPKGVER-1.0}"
pkgrel=0
pkgdesc="Dummy subpackage arch"
url="https://gitlab.alpinelinux.org/alpine/aports"
arch="noarch"
license="MIT"
subpackages="$pkgname-$TESTSUBARCH:_sub:$TESTSUBARCH"
options="!archcheck"
check() {
true
}
package() {
mkdir -p "$pkgdir"
}
_sub() {
mkdir -p "$subpkgdir"
}

View File

@ -8,10 +8,10 @@ pkgdesc='Dummy test package that has multi-line licenses'
url='https://gitlab.alpinelinux.org/alpine/aports'
arch='noarch'
license='MIT AND
GPL-3.0-only OR
(GPL-3.0-only OR
GPL-3.0-or-later AND
BSD-Clause-4
BSD-Clause-4)
'
prepare() {

View File

@ -8,6 +8,7 @@ pkgdesc="Dummy test package that fails to build"
url="https://gitlab.alpinelinux.org/alpine/aports"
arch="noarch"
license="MIT"
provides="${TESTPROVIDES-provided}"
subpackages="${TESTSUBNAME-$pkgname-sub}:_sub"
prepare() {