Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Allan McRae
7175062526 Store and read name of alternatives
Add the names of supplied alternatives to the .PKGINFO file.  Read and store
these values in libalpm.  This information is currently not used anywhere.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-12-12 11:54:51 +10:00
Allan McRae
7ceee8805b makepkg: add basic support for alternatives
Alternatives are specified in makepkg via (e.g.):

alternative=('sh')

There should be a file (e.g.) sh.alternative alongside the PKGBUILD containing
a list of symlinks to be created with the alternative is active.  This file is
stored in the root of the package as (e.g.) .ALTERNATIVE.sh.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-12-12 11:54:49 +10:00
10 changed files with 97 additions and 5 deletions

View file

@ -402,8 +402,8 @@ All options and directives for the split packages default to the global values
given in the PKGBUILD. Nevertheless, the following ones can be overridden within given in the PKGBUILD. Nevertheless, the following ones can be overridden within
each split package's packaging function: each split package's packaging function:
`pkgdesc`, `arch`, `url`, `license`, `groups`, `depends`, `optdepends`, `pkgdesc`, `arch`, `url`, `license`, `groups`, `depends`, `optdepends`,
`provides`, `conflicts`, `replaces`, `backup`, `options`, `install`, and `provides`, `conflicts`, `replaces`, `backup`, `options`, `install`,
`changelog`. `changelog` and `alternative`.
Note that makepkg does not consider split package `depends` when checking Note that makepkg does not consider split package `depends` when checking
if dependencies are installed before package building and with `--syncdeps`. if dependencies are installed before package building and with `--syncdeps`.

View file

@ -2555,6 +2555,12 @@ alpm_filelist_t *alpm_pkg_get_files(alpm_pkg_t *pkg);
*/ */
alpm_list_t *alpm_pkg_get_backup(alpm_pkg_t *pkg); alpm_list_t *alpm_pkg_get_backup(alpm_pkg_t *pkg);
/** Returns the list of alternatives provided by the package
* @param pkg a pointer to package
* @return a reference to a list of char* objects
*/
alpm_list_t *alpm_pkg_get_alternatives(alpm_pkg_t *pkg);
/** Returns the database containing pkg. /** Returns the database containing pkg.
* Returns a pointer to the alpm_db_t structure the package is * Returns a pointer to the alpm_db_t structure the package is
* originating from, or NULL if the package was loaded from a file. * originating from, or NULL if the package was loaded from a file.

View file

@ -195,6 +195,12 @@ static alpm_list_t *_cache_get_backup(alpm_pkg_t *pkg)
return pkg->backup; return pkg->backup;
} }
static alpm_list_t *_cache_get_alternatives(alpm_pkg_t *pkg)
{
LAZY_LOAD(INFRQ_DESC);
return pkg->alternatives;
}
/** /**
* Open a package changelog for reading. Similar to fopen in functionality, * Open a package changelog for reading. Similar to fopen in functionality,
* except that the returned 'file stream' is from the database. * except that the returned 'file stream' is from the database.
@ -349,6 +355,7 @@ static const struct pkg_operations local_pkg_ops = {
.get_replaces = _cache_get_replaces, .get_replaces = _cache_get_replaces,
.get_files = _cache_get_files, .get_files = _cache_get_files,
.get_backup = _cache_get_backup, .get_backup = _cache_get_backup,
.get_alternatives = _cache_get_alternatives,
.changelog_open = _cache_changelog_open, .changelog_open = _cache_changelog_open,
.changelog_read = _cache_changelog_read, .changelog_read = _cache_changelog_read,
@ -804,6 +811,8 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
READ_AND_SPLITDEP(info->conflicts); READ_AND_SPLITDEP(info->conflicts);
} else if(strcmp(line, "%PROVIDES%") == 0) { } else if(strcmp(line, "%PROVIDES%") == 0) {
READ_AND_SPLITDEP(info->provides); READ_AND_SPLITDEP(info->provides);
} else if(strcmp(line, "%ALTERNATIVES%") == 0) {
READ_AND_STORE_ALL(info->alternatives);
} }
} }
fclose(fp); fclose(fp);
@ -1040,6 +1049,15 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, int inforeq)
write_deps(fp, "%CONFLICTS%", info->conflicts); write_deps(fp, "%CONFLICTS%", info->conflicts);
write_deps(fp, "%PROVIDES%", info->provides); write_deps(fp, "%PROVIDES%", info->provides);
if(info->alternatives) {
fputs("%ALTERNATIVES%\n", fp);
for(lp = info->alternatives; lp; lp = lp->next) {
fputs(lp->data, fp);
fputc('\n', fp);
}
fputc('\n', fp);
}
fclose(fp); fclose(fp);
fp = NULL; fp = NULL;
} }

View file

@ -244,6 +244,8 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
CALLOC(backup, 1, sizeof(alpm_backup_t), return -1); CALLOC(backup, 1, sizeof(alpm_backup_t), return -1);
STRDUP(backup->name, ptr, FREE(backup); return -1); STRDUP(backup->name, ptr, FREE(backup); return -1);
newpkg->backup = alpm_list_add(newpkg->backup, backup); newpkg->backup = alpm_list_add(newpkg->backup, backup);
} else if(strcmp(key, "alternative") == 0) {
newpkg->alternatives = alpm_list_add(newpkg->alternatives, strdup(ptr));
} else if(strcmp(key, "force") == 0) { } else if(strcmp(key, "force") == 0) {
/* deprecated, skip it */ /* deprecated, skip it */
} else if(strcmp(key, "makepkgopt") == 0) { } else if(strcmp(key, "makepkgopt") == 0) {

View file

@ -98,6 +98,7 @@ static alpm_list_t *_pkg_get_provides(alpm_pkg_t *pkg) { return pkg->provides;
static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg) { return pkg->replaces; } static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg) { return pkg->replaces; }
static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg) { return &(pkg->files); } static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg) { return &(pkg->files); }
static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg) { return pkg->backup; } static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg) { return pkg->backup; }
static alpm_list_t *_pkg_get_alternatives(alpm_pkg_t *pkg) { return pkg->alternatives; }
static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg) static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg)
{ {
@ -162,6 +163,7 @@ const struct pkg_operations default_pkg_ops = {
.get_replaces = _pkg_get_replaces, .get_replaces = _pkg_get_replaces,
.get_files = _pkg_get_files, .get_files = _pkg_get_files,
.get_backup = _pkg_get_backup, .get_backup = _pkg_get_backup,
.get_alternatives = _pkg_get_alternatives,
.changelog_open = _pkg_changelog_open, .changelog_open = _pkg_changelog_open,
.changelog_read = _pkg_changelog_read, .changelog_read = _pkg_changelog_read,
@ -418,6 +420,13 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(alpm_pkg_t *pkg)
return pkg->ops->get_backup(pkg); return pkg->ops->get_backup(pkg);
} }
alpm_list_t SYMEXPORT *alpm_pkg_get_alternatives(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return NULL);
pkg->handle->pm_errno = ALPM_ERR_OK;
return pkg->ops->get_alternatives(pkg);
}
alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg) alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg)
{ {
/* Sanity checks */ /* Sanity checks */
@ -632,6 +641,7 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
newpkg->optdepends = list_depdup(pkg->optdepends); newpkg->optdepends = list_depdup(pkg->optdepends);
newpkg->conflicts = list_depdup(pkg->conflicts); newpkg->conflicts = list_depdup(pkg->conflicts);
newpkg->provides = list_depdup(pkg->provides); newpkg->provides = list_depdup(pkg->provides);
newpkg->alternatives = alpm_list_strdup(pkg->alternatives);
if(pkg->files.count) { if(pkg->files.count) {
size_t filenum; size_t filenum;
@ -709,6 +719,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
free_deplist(pkg->provides); free_deplist(pkg->provides);
alpm_list_free(pkg->removes); alpm_list_free(pkg->removes);
_alpm_pkg_free(pkg->oldpkg); _alpm_pkg_free(pkg->oldpkg);
FREELIST(pkg->alternatives);
if(pkg->origin == ALPM_PKG_FROM_FILE) { if(pkg->origin == ALPM_PKG_FROM_FILE) {
FREE(pkg->origin_data.file); FREE(pkg->origin_data.file);

View file

@ -66,6 +66,7 @@ struct pkg_operations {
alpm_list_t *(*get_replaces) (alpm_pkg_t *); alpm_list_t *(*get_replaces) (alpm_pkg_t *);
alpm_filelist_t *(*get_files) (alpm_pkg_t *); alpm_filelist_t *(*get_files) (alpm_pkg_t *);
alpm_list_t *(*get_backup) (alpm_pkg_t *); alpm_list_t *(*get_backup) (alpm_pkg_t *);
alpm_list_t *(*get_alternatives) (alpm_pkg_t *);
void *(*changelog_open) (alpm_pkg_t *); void *(*changelog_open) (alpm_pkg_t *);
size_t (*changelog_read) (void *, size_t, const alpm_pkg_t *, void *); size_t (*changelog_read) (void *, size_t, const alpm_pkg_t *, void *);
@ -120,6 +121,7 @@ struct _alpm_pkg_t {
alpm_list_t *provides; alpm_list_t *provides;
alpm_list_t *removes; /* in transaction targets only */ alpm_list_t *removes; /* in transaction targets only */
alpm_pkg_t *oldpkg; /* in transaction targets only */ alpm_pkg_t *oldpkg; /* in transaction targets only */
alpm_list_t *alternatives;
const struct pkg_operations *ops; const struct pkg_operations *ops;

View file

@ -0,0 +1,41 @@
#!/bin/bash
#
# alternative.sh - Check the files associated with the 'alternative'
# array exist.
#
# Copyright (c) 2020 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_ALTERNATIVE_SH" ]] && return
LIBMAKEPKG_LINT_PKGBUILD_ALTERNATIVE_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
source "$LIBRARY/util/pkgbuild.sh"
source "$LIBRARY/lint_pkgbuild/util.sh"
lint_pkgbuild_functions+=('lint_alternative')
lint_alternative() {
local ret=0
check_files_exist 'alternative' "${alternative[@]/%/.alternative}" || ret=1
return $ret
}

View file

@ -1,6 +1,7 @@
libmakepkg_module = 'lint_pkgbuild' libmakepkg_module = 'lint_pkgbuild'
sources = [ sources = [
'alternative.sh.in',
'arch.sh.in', 'arch.sh.in',
'arch_specific.sh.in', 'arch_specific.sh.in',
'backup.sh.in', 'backup.sh.in',

View file

@ -28,8 +28,8 @@ source "$LIBRARY/util/util.sh"
known_hash_algos=({ck,md5,sha{1,224,256,384,512},b2}) known_hash_algos=({ck,md5,sha{1,224,256,384,512},b2})
pkgbuild_schema_arrays=(arch backup checkdepends conflicts depends groups pkgbuild_schema_arrays=(alternative arch backup checkdepends conflicts depends
license makedepends noextract optdepends options groups license makedepends noextract optdepends options
provides replaces source validpgpkeys provides replaces source validpgpkeys
"${known_hash_algos[@]/%/sums}") "${known_hash_algos[@]/%/sums}")
@ -42,7 +42,7 @@ pkgbuild_schema_arch_arrays=(checkdepends conflicts depends makedepends
pkgbuild_schema_package_overrides=(pkgdesc arch url license groups depends pkgbuild_schema_package_overrides=(pkgdesc arch url license groups depends
optdepends provides conflicts replaces optdepends provides conflicts replaces
backup options install changelog) backup options install changelog alternative)
readonly -a known_hash_algos pkgbuild_schema_arrays \ readonly -a known_hash_algos pkgbuild_schema_arrays \
pkgbuild_schema_strings pkgbuild_schema_arch_arrays \ pkgbuild_schema_strings pkgbuild_schema_arch_arrays \

View file

@ -630,6 +630,7 @@ write_pkginfo() {
write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }" write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }"
write_kv_pair "makedepend" "${makedepends[@]}" write_kv_pair "makedepend" "${makedepends[@]}"
write_kv_pair "checkdepend" "${checkdepends[@]}" write_kv_pair "checkdepend" "${checkdepends[@]}"
write_kv_pair "alternative" "${alternative[@]}"
} }
write_buildinfo() { write_buildinfo() {
@ -710,6 +711,16 @@ create_package() {
fi fi
done done
# check for alternative files
for i in ${alternative[@]}; do
msg2 "$(gettext "Adding %s file...")" "$i.alternative"
if ! cp "$startdir/$i.alternative" ".ALTERNATIVE.$i"; then
error "$(gettext "Failed to add %s file to package.")" "$i.alternative"
exit $E_MISSING_FILE
fi
chmod 644 ".ALTERNATIVE.$i"
done
# tar it up # tar it up
local fullver=$(get_full_version) local fullver=$(get_full_version)
local pkg_file="$PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT}" local pkg_file="$PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT}"