Added the concept of package properties in the API.
See the NEWS file and xbps-bin(8) for more information.
This commit is contained in:
parent
d25bc35711
commit
de296d8192
18
NEWS
18
NEWS
@ -1,5 +1,23 @@
|
||||
xbps-0.8.0 (???):
|
||||
|
||||
* Added the concept of package properties in the API. At this moment
|
||||
only one property is fully working, "virtual". When xbps-bin(8)
|
||||
sets this property for a package, its virtual package list will be
|
||||
set in the XBPS_REGPKGDB plist in a package dictionary and the matching
|
||||
logic will always prefer its virtual packages over the real ones.
|
||||
You can do wonderful things with this, like always using development
|
||||
package versions, or simply customize what packages you want to
|
||||
install rather than the default ones. As a real example, you can now
|
||||
use the 'xbps-devel' package rather than the stable package version
|
||||
'xbps' before installing the system and package dependencies will
|
||||
still be resolved:
|
||||
|
||||
"$ xbps-bin set-prop virtual xbps-devel"
|
||||
"$ xbps-bin install xbps-base-system"
|
||||
|
||||
Only packages that have the "provides" object are valid for the
|
||||
"virtual" property.
|
||||
|
||||
* Moved the "replaces" handling logic into the API. But instead of
|
||||
removing any package, the packages that should be replaced are
|
||||
added into the transaction dictionary and marked as "remove".
|
||||
|
@ -46,6 +46,7 @@ struct list_pkgver_cb {
|
||||
static void __attribute__((noreturn))
|
||||
usage(void)
|
||||
{
|
||||
xbps_end();
|
||||
fprintf(stderr,
|
||||
"Usage: xbps-bin [options] [target] [arguments]\n"
|
||||
"See xbps-bin(8) for more information.\n");
|
||||
@ -434,6 +435,23 @@ main(int argc, char **argv)
|
||||
|
||||
rv = find_files_in_packages(argv[1]);
|
||||
|
||||
} else if (strcasecmp(argv[0], "set-prop") == 0) {
|
||||
if (argc < 2 || argc > 3)
|
||||
usage();
|
||||
/*
|
||||
* Sets a property in a package.
|
||||
*/
|
||||
rv = xbps_property_set(argv[1], argv[2]);
|
||||
|
||||
} else if (strcasecmp(argv[0], "unset-prop") == 0) {
|
||||
/*
|
||||
* Unsets a property in a package.
|
||||
*/
|
||||
if (argc < 2 || argc > 3)
|
||||
usage();
|
||||
|
||||
rv = xbps_property_unset(argv[1], argv[2]);
|
||||
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
|
@ -37,15 +37,31 @@
|
||||
int
|
||||
show_pkg_info_from_metadir(const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t d;
|
||||
prop_dictionary_t d, regpkgd, pkgpropsd;
|
||||
|
||||
d = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGPROPS);
|
||||
if (d == NULL)
|
||||
return errno;
|
||||
return EINVAL;
|
||||
|
||||
regpkgd = xbps_regpkgdb_dictionary_get();
|
||||
pkgpropsd = xbps_find_pkg_in_dict_by_name(regpkgd,
|
||||
"properties", pkgname);
|
||||
if (pkgpropsd == NULL) {
|
||||
show_pkg_info(d, false);
|
||||
prop_object_release(d);
|
||||
goto out;
|
||||
}
|
||||
if (prop_dictionary_get(pkgpropsd, "hold"))
|
||||
prop_dictionary_set_bool(d, "hold", true);
|
||||
if (prop_dictionary_get(pkgpropsd, "update-first"))
|
||||
prop_dictionary_set_bool(d, "update-first", true);
|
||||
if (prop_dictionary_get(pkgpropsd, "provides"))
|
||||
prop_dictionary_set_bool(d, "virtual-prefer", true);
|
||||
|
||||
show_pkg_info(d, false);
|
||||
prop_object_release(d);
|
||||
|
||||
out:
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -57,7 +73,7 @@ show_pkg_files_from_metadir(const char *pkgname)
|
||||
|
||||
d = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
||||
if (d == NULL)
|
||||
return errno;
|
||||
return EINVAL;
|
||||
|
||||
rv = show_pkg_files(d);
|
||||
prop_object_release(d);
|
||||
|
@ -1,4 +1,13 @@
|
||||
.TH "XBPS\-BIN" "8" "30/01/2011" "\ \&" "\ \&"
|
||||
'\" t
|
||||
.\" Title: xbps-bin
|
||||
.\" Author: [see the "AUTHORS" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||
.\" Date: 02/05/2011
|
||||
.\" Manual: \ \&
|
||||
.\" Source: \ \&
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "XBPS\-BIN" "8" "02/05/2011" "\ \&" "\ \&"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * set default formatting
|
||||
.\" -----------------------------------------------------------------
|
||||
@ -16,18 +25,15 @@ xbps-bin \- XBPS command for binary packages
|
||||
\fBxbps\-bin\fR [\fIoptions\fR] \fItarget\fR [\fIpkgname\fR]
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
The xbps\-bin(8) command is used to handle binary packages created for the \fBXBPS binary package system\fR\&. You can use it to install, remove, list or show information about any binary package\&. Binary packages can be installed from local (\fIdirectory\fR) or remote repositories (\fIhttp\fR, \fIhttps\fR or \fIftp\fR), see xbps\-repo(8) for information about repositories\&.
|
||||
The xbps\-bin(8) command is used to handle binary packages created for the XBPS binary package system\&. You can use it to install, remove, update, list or show information about any binary package\&. Binary packages can be installed from \fIlocal (directories)\fR or \fIremote repositories (http, https or ftp)\fR, see xbps\-repo(8) for information about repositories\&.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
\fB\-c\fR \fIcachedir\fR
|
||||
.RS 4
|
||||
Sets the
|
||||
\fIcache\fR
|
||||
directory to store downloaded binary packages from remote repositories\&. By default it\(cqs set to
|
||||
Sets the cache directory to store downloaded binary packages from remote repositories\&. By default it\(cqs set to
|
||||
\fI/var/cache/xbps\fR
|
||||
and it\(cqs always relative to the
|
||||
\fIroot\fR
|
||||
directory\&. So if you use a
|
||||
\fIroot directory\fR\&. So if you use a
|
||||
\fIrootdir\fR
|
||||
of
|
||||
\fI/blah\fR, it will become
|
||||
@ -36,22 +42,22 @@ of
|
||||
.PP
|
||||
\fB\-d\fR
|
||||
.RS 4
|
||||
Enables extra debugging output to be shown to stderr.
|
||||
Enables extra debugging output to be shown to stderr\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-D\fR
|
||||
.RS 4
|
||||
Only show the URLs to download the binary packages from repositories.
|
||||
This is useful if you want to download them by other means, and later you
|
||||
can move them to the \fIcachedir\fR to start the installation.
|
||||
This option can be used for the \fIinstall\fR, \fIupdate\fR and \fIautoupdate\fR
|
||||
targets.
|
||||
Only show the URLs to download the binary packages from repositories\&. This is useful if you want to download them by other means, and later you can move them to the
|
||||
\fIcachedir\fR
|
||||
to start the installation\&. This option can be used for the install, update and autoupdate targets\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-F\fR
|
||||
.RS 4
|
||||
Used currently in the \fIremove\fR target. If set, package will be removed even if other packages
|
||||
are currently depending on it, i.e package is a dependency of other packages. Use this option with care.
|
||||
Used currently in the
|
||||
\fIremove\fR
|
||||
target\&. If set, package will be removed even if other packages are currently depending on it, i\&.e package is a dependency of other packages\&.
|
||||
\fIUse this option with care\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-f\fR
|
||||
@ -61,8 +67,14 @@ Used currently in the
|
||||
\fIreconfigure\fR
|
||||
and
|
||||
\fIremove\fR
|
||||
targets\&. If set, package(s) will be reconfigured regardless of its state if working with the
|
||||
\fIreconfigure target, or to force removal of package files even if its hash doesn\(cqt match in the "purge\fR"
|
||||
targets\&. If set,
|
||||
\fIpackage(s)\fR
|
||||
will be
|
||||
\fIreconfigured\fR
|
||||
regardless of its state in the reconfigure target, or to
|
||||
\fIforce\fR
|
||||
removal of package files even if its hash doesn\(cqt match in the
|
||||
\fIpurge\fR
|
||||
and
|
||||
\fIremove\fR
|
||||
targets\&.
|
||||
@ -81,8 +93,7 @@ targets, if enabled after removing a package it is also purged\&.
|
||||
.RS 4
|
||||
Used currently in the
|
||||
\fIremove\fR
|
||||
target, to recursively remove packages that aren\(cqt required by other installed
|
||||
packages and that were installed by the package that we want to remove\&.
|
||||
target, to recursively remove packages that aren\(cqt required by other installed packages and that were installed by the package that we want to remove\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-r\fR \fIrootdir\fR
|
||||
@ -93,9 +104,7 @@ directory\&. By default the root directory is set to
|
||||
\fI/\fR\&. Please note that the database directory is always set to
|
||||
\fI/var/db/xbps\fR
|
||||
independently of
|
||||
\fIrootdir\fR\&. So if you use a
|
||||
\fIrootdir\fR
|
||||
of
|
||||
\fIrootdir\fR\&. So if you use a rootdir of
|
||||
\fI/blah\fR, metadata stuff will go into
|
||||
\fI/blah/var/db/xbps\fR\&.
|
||||
.RE
|
||||
@ -107,7 +116,9 @@ Shows verbose messages\&. Useful while installing and removing packages\&.
|
||||
.PP
|
||||
\fB\-y\fR
|
||||
.RS 4
|
||||
Assume "yes" to all questions\&. This will bypass all questions and immediately proceed with the task, use this option with care\&.
|
||||
Assume
|
||||
\fIyes\fR
|
||||
to all questions\&. This will bypass all questions and immediately proceed with the task, use this option with care\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-V\fR
|
||||
@ -116,14 +127,11 @@ Shows the current XBPS release version (library and code)\&.
|
||||
.RE
|
||||
.SH "TARGETS"
|
||||
.sp
|
||||
Please note that all targets are \fBcase insensitive\fR\&.
|
||||
Please note that all targets are case insensitive\&.
|
||||
.PP
|
||||
\fBautoremove\fR
|
||||
.RS 4
|
||||
Removes
|
||||
\fIleaf\fR
|
||||
packages\&. These packages were installed as dependencies and currently there is not any package depending on it, directly or indirectly\&. Usually it is safe to always answer
|
||||
\fIyes\fR\&.
|
||||
Removes leaf packages\&. These packages were installed as dependencies and currently there is not any package depending on it, directly or indirectly\&. Usually it is safe to always answer yes\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBautoupdate\fR
|
||||
@ -131,108 +139,117 @@ packages\&. These packages were installed as dependencies and currently there is
|
||||
Updates all currently installed packages to the most newer version available in repository pool\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBcheck \fR\fB\fIpkgname(s)\fR\fR\fB | \fR\fB\fIall\fR\fR
|
||||
\fBcheck \fR\fB\fIpkgname(s) | all\fR\fR
|
||||
.RS 4
|
||||
Checks for integrity errors in installed packages\&. The checks are to found missing run\-time dependencies, missing and modified package files and metadata files\&. If the
|
||||
\fBall\fR
|
||||
keyword is used,
|
||||
\fIall\fR
|
||||
packages currently installed will be checked, otherwise only
|
||||
\fBpkgname\fR\&.
|
||||
keyword is used, all packages currently installed will be checked, otherwise only
|
||||
\fIpkgname(s)\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBfind-files\fR \fR\fB\fIpattern\fR\fR
|
||||
\fBfind\-files \fR\fB\fIpattern\fR\fR
|
||||
.RS 4
|
||||
Prints the name of the installed "\fBpackage(s)\fR" matching the \fBpattern\fR on its file list.
|
||||
Prints the name of the installed
|
||||
\fIpackage(s)\fR
|
||||
matching the pattern on its file list\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBinstall \fR\fB\fIpkgname(s)\fR\fR\fB | \fR\fB\fIpkgpattern(s)\fR\fR
|
||||
\fBinstall \fR\fB\fIpkgname(s) | pkgpattern(s)\fR\fR
|
||||
.RS 4
|
||||
Install binary package(s) from repository pool by specifying "\fBpkgname(s)\fR" or "\fBpackage pattern(s)\fR"\&. The first repository matching the arguments will be used\&. The package(s) will be
|
||||
Install binary package(s) from repository pool by specifying
|
||||
\fIpkgname(s)\fR
|
||||
or
|
||||
\fIpackage pattern(s)\fR\&. The first repository matching the arguments will be used\&. The package(s) will be
|
||||
\fIdownloaded\fR
|
||||
(if found in a remote repository),
|
||||
\fIunpacked\fR
|
||||
and
|
||||
\fIconfigured\fR\&. The
|
||||
\fIunpack stage will execute the \fR\fI\fBpre\-install\fR\fR\fI action on its \fR\fI\fBINSTALL\fR\fR\fI script, and unpack its files\&. The "configure\fR"
|
||||
stage will run the
|
||||
\fBpost\-install\fR
|
||||
action set on its
|
||||
\fBINSTALL\fR
|
||||
script and will change its state to
|
||||
\fBinstalled\fR
|
||||
in the package database\&.
|
||||
\fIunpack\fR
|
||||
stage will execute the pre\-install action on its INSTALL script, and unpack its files\&. The
|
||||
\fIconfigure\fR
|
||||
stage will run the post\-install action set on its INSTALL script and will change its
|
||||
\fIstate\fR
|
||||
to installed in the package database\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBlist [\fR\fB\fIstate\fR\fR]
|
||||
\fBlist [\fR\fB\fIstate\fR\fR\fB]\fR
|
||||
.RS 4
|
||||
Lists all currently installed packages\&. Optionally another argument can be specified to
|
||||
list only packages with the specified \fIstate\fR. By default only packages that are fully
|
||||
installed will be listed if no \fIstate\fR has been specified. Accepted states are:
|
||||
\fBconfig\-files\fR, \fBunpacked\fR and \fBinstalled\fR.
|
||||
Lists all currently installed packages\&. Optionally another argument can be specified to list only packages with the specified
|
||||
\fIstate\fR\&. By default only packages that are
|
||||
\fIfully installed\fR
|
||||
will be listed if
|
||||
\fIstate\fR
|
||||
has not been specified\&. Accepted states are:
|
||||
\fIconfig\-files\fR,
|
||||
\fIunpacked\fR
|
||||
and
|
||||
\fIinstalled\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBlist\-manual\fR
|
||||
.RS 4
|
||||
Lists packages that were installed
|
||||
\fImanually\fR
|
||||
by the user, i\&.e not as dependencies of any other package\&.
|
||||
Lists packages that were installed manually by the user, i\&.e not as dependencies of any other package\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBpurge \fR\fB\fIpkgname\fR\fR\fB | \fR\fB\fIall\fR\fR
|
||||
\fBpurge \fR\fB\fIpkgname | all\fR\fR
|
||||
.RS 4
|
||||
Purge an installed package,
|
||||
\fBpkgname\fR
|
||||
Purge an installed package:
|
||||
\fIpkgname\fR
|
||||
or
|
||||
\fBall\fR
|
||||
packages\&. The
|
||||
\fIpurge\fR
|
||||
stage runs the
|
||||
\fBpost\-remove\fR
|
||||
action set in the
|
||||
\fBREMOVE\fR
|
||||
script in its metadata directory ( /var/db/xbps/metadata/\fIpkgname\fR
|
||||
) and will remove configuration (if they were not modified by the user) and metadata files\&. The package will be fully removed from the system once it has been
|
||||
\fBpurged\fR\&. If
|
||||
\fIall\fR
|
||||
packages\&. The purge stage runs the post\-remove action set in the REMOVE script in its metadata directory
|
||||
\fI(/var/db/xbps/metadata/pkgname)\fR
|
||||
and will remove configuration (if they were not modified by the user) and metadata files\&. The package will be fully removed from the system once it has been purged\&. If
|
||||
\fB\-f\fR
|
||||
option is used, configuration files that have been modified
|
||||
\fBWILL BE REMOVED, BEWARE WITH THIS!\fR\&.
|
||||
option is used, configuration files that have been
|
||||
\fImodified WILL BE REMOVED\&. BEWARE WITH THIS!\fR
|
||||
.RE
|
||||
.PP
|
||||
\fBreconfigure \fR\fB\fIpkgname\fR\fR\fB | \fR\fB\fIall\fR\fR
|
||||
\fBreconfigure \fR\fB\fIpkgname | all\fR\fR
|
||||
.RS 4
|
||||
Reconfigure an
|
||||
\fBunpacked\fR
|
||||
package\&. Packages in this state are not fully installed, because they were not configured for whatever reason\&. The
|
||||
\fIconfigure\fR
|
||||
stage will run the
|
||||
\fIpost\-install\fR
|
||||
action set on its
|
||||
\fBINSTALL\fR
|
||||
script and will change its state to
|
||||
\fBinstalled\fR
|
||||
in the package database\&. The
|
||||
Reconfigure an unpacked package\&. Packages in this state are not fully installed, because they were not configured for whatever reason\&. The configure stage will run the post\-install action set on its INSTALL script and will change its state to installed in the package database\&. The
|
||||
\fIall\fR
|
||||
keyword can be used to reconfigure all not configured packages\&. If
|
||||
\fB\-f\fR
|
||||
option is used, the package will be reconfigured even if its state is already
|
||||
\fBinstalled\fR\&.
|
||||
option is used, the package will be reconfigured even if its state is already installed\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBremove \fR\fB\fIpkgname(s)\fR\fR
|
||||
.RS 4
|
||||
Removes the installed package
|
||||
\fIpkgname(s)\fR\&. Its files will be removed and its state will be changed to
|
||||
\fBconfig\-files\fR
|
||||
\fIconfig\-files\fR
|
||||
in the package database\&. Configuration files, its metadata directory/files and its information in the package database are preserved\&. To fully remove a package in
|
||||
\fBconfig\-files\fR
|
||||
state, it must be
|
||||
\fBpurged\fR
|
||||
with the
|
||||
\fBpurge\fR
|
||||
command or alternatively use the \fI\-p\fR flag \&. If
|
||||
\fIconfig\-files\fR
|
||||
state, it must be purged with the
|
||||
\fIpurge\fR
|
||||
command or alternatively use the
|
||||
\fB\-p\fR
|
||||
flag \&. If
|
||||
\fB\-f\fR
|
||||
option is used, package files will be removed even if its SHA256 hash doesn\(cqt match\&.
|
||||
option is used, package files will be
|
||||
\fBremoved even if its SHA256 hash don\(cqt match\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBset\-prop \fR\fB\fIproperty\fR\fR\fB \fR\fB\fIpkgname\fR\fR
|
||||
.RS 4
|
||||
Sets a
|
||||
\fIproperty\fR
|
||||
for a package as specified in
|
||||
\fIpkgname\fR\&. See the
|
||||
\fIPROPERTIES\fR
|
||||
section below for more information\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBunset\-prop \fR\fB\fIproperty\fR\fR\fB \fR\fB\fIpkgname\fR\fR
|
||||
.RS 4
|
||||
Unsets a
|
||||
\fIproperty\fR
|
||||
for a package as specified in
|
||||
\fIpkgname\fR\&. See the
|
||||
\fIPROPERTIES\fR
|
||||
section below for more information\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBshow \fR\fB\fIpkgname\fR\fR
|
||||
@ -243,31 +260,23 @@ Shows information for installed package
|
||||
.PP
|
||||
\fBshow\-deps \fR\fB\fIpkgname\fR\fR
|
||||
.RS 4
|
||||
Shows the list of dependencies that
|
||||
\fIpkgname\fR
|
||||
requires at run time\&.
|
||||
Shows the list of dependencies that pkgname requires at run time\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBshow\-files \fR\fB\fIpkgname\fR\fR
|
||||
.RS 4
|
||||
Shows the list of files that
|
||||
\fIpkgname\fR
|
||||
contains\&.
|
||||
Shows the list of files that pkgname contains\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBshow\-orphans\fR
|
||||
.RS 4
|
||||
Shows the list of package orphans currently installed. Package orphans
|
||||
are packages that were installed as dependencies of another package, but
|
||||
no other package currently depends on.
|
||||
Shows the list of package orphans currently installed\&. Package orphans are packages that were installed as dependencies of another package, but no other package currently depends on\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBshow\-revdeps \fR\fB\fIpkgname\fR\fR
|
||||
.RS 4
|
||||
Shows the reverse dependencies for
|
||||
\fIpkgname\fR\&. Reverse dependencies are packages that are currently depending in
|
||||
\fIpkgname\fR
|
||||
directly\&.
|
||||
\fIpkgname\fR\&. Reverse dependencies are packages that are currently depending in pkgname directly\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBupdate \fR\fB\fIpkgname(s)\fR\fR
|
||||
@ -276,8 +285,8 @@ Updates
|
||||
\fIpkgname(s)\fR
|
||||
to the most newer version available in repository pool\&. This can be used if only
|
||||
\fIpkgname(s)\fR
|
||||
needs to be updated, unlike the
|
||||
\fBautoupdate\fR
|
||||
need to be updated, unlike the
|
||||
\fIautoupdate\fR
|
||||
target that will update all currently installed packages\&.
|
||||
.RE
|
||||
.SH "PACKAGE STATES"
|
||||
@ -296,17 +305,40 @@ The package has been unpacked in destination root directory, but it is not fully
|
||||
.PP
|
||||
\fBconfig\-files\fR
|
||||
.RS 4
|
||||
The package has been removed but configuration files and its metadata directory are still available (and it is still registered in the package database)\&. You can
|
||||
\fIpurge\fR
|
||||
safely packages that are in this state, modified configuration files will be preserved\&.
|
||||
The package has been removed but configuration files and its metadata directory are still available (and it is still registered in the package database)\&. You can purge safely packages that are in this state, modified configuration files will be preserved\&.
|
||||
.RE
|
||||
.SH "PROPERTIES"
|
||||
.sp
|
||||
Properties can be specified for packages to control behaviour of some aspects in XBPS\&. The following is the list of properties currently implemented:
|
||||
.PP
|
||||
\fBhold\fR
|
||||
.RS 4
|
||||
When this property is set for a package, it will be put on
|
||||
\fIhold\fR
|
||||
i\&.e the package won\(cqt be updated even if there is a newer version in registered repositories\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBupdate\-first\fR
|
||||
.RS 4
|
||||
When this property is set, the package will always be updated before all other packages, regardless of its package dependencies\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBvirtual\fR
|
||||
.RS 4
|
||||
When this property is set, the virtual packages that target package supports via the
|
||||
\fBproperties\fR
|
||||
object will have preference over other packages matching its
|
||||
\fIpackage name\fR\&. A real example is any package that
|
||||
\fIprovides\fR
|
||||
the
|
||||
\fBsyslog\-daemon\-0\fR
|
||||
virtual package, if there are two packages supporting this you can choose which one will be installed\&.
|
||||
.RE
|
||||
.SH "FILES"
|
||||
.PP
|
||||
\fB/var/db/xbps\fR
|
||||
.RS 4
|
||||
xbps global
|
||||
\fImetadata\fR
|
||||
directory\&.
|
||||
xbps global metadata directory\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB/var/db/xbps/metadata/<pkgname>\fR
|
||||
@ -326,64 +358,80 @@ Installed package metadata properties\&.
|
||||
.PP
|
||||
\fB/var/db/xbps/regpkgdb\&.plist\fR
|
||||
.RS 4
|
||||
Registered packages plist database\&.
|
||||
xbps master packages/properties database plist file\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB/var/cache/xbps\fR
|
||||
.RS 4
|
||||
xbps
|
||||
\fIcache\fR
|
||||
directory for downloaded binary packages\&.
|
||||
xbps cache directory for downloaded binary packages\&.
|
||||
.RE
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
Install a package by specifying its name:
|
||||
\fBInstall\fR a package by specifying its \fBname\fR:
|
||||
.RS 4
|
||||
|
||||
$ xbps\-bin install foo
|
||||
.RE
|
||||
.PP
|
||||
Install a package by specifying a package pattern:
|
||||
\fBInstall\fR a package by specifying a \fBpackage pattern\fR:
|
||||
.RS 4
|
||||
$ xbps\-bin install "\fBfoo>=3\&.0\fR"
|
||||
|
||||
$ xbps\-bin install "foo>=3\&.0"
|
||||
.RE
|
||||
.PP
|
||||
Install multiple packages by specifying names and package patterns:
|
||||
\fBInstall multiple\fR packages by specifying \fBnames\fR and \fBpackage patterns\fR:
|
||||
.RS 4
|
||||
$ xbps\-bin install foo "\fBblah⇐4\&.0\fR" baz\-2\&.0 "\fBblob>4\&.[0\-9]\fR"
|
||||
|
||||
$ xbps\-bin install foo "blah<=4\&.0" baz\-2\&.0 "blob>4\&.[0\-9]"
|
||||
.RE
|
||||
.PP
|
||||
Find the package that owns the file \fB/bin/mount\fR:
|
||||
\fBFind\fR the package that owns the file \fB/bin/mount\fR:
|
||||
.RS 4
|
||||
|
||||
$ xbps\-bin find\-files /bin/mount
|
||||
.RE
|
||||
.PP
|
||||
Find the packages that match the pattern "\fB/usr/lib/libav\&*\fR":
|
||||
\fBFind\fR the packages that match the pattern \fB"/usr/lib/libav\fR"*:
|
||||
.RS 4
|
||||
$ xbps\-bin find\-files "/usr/lib/libav\&*"
|
||||
|
||||
$ xbps\-bin find\-files "/usr/lib/libav*"
|
||||
.RE
|
||||
.PP
|
||||
Remove and purge the package \fBproplib-devel\fR:
|
||||
\fBRemove and purge\fR the package \fBproplib\-devel\fR:
|
||||
.RS 4
|
||||
$ xbps\-bin -yp remove proplib\-devel
|
||||
|
||||
$ xbps\-bin \-yp remove proplib\-devel
|
||||
.RE
|
||||
.PP
|
||||
Remove and purge the package \fBbsdtar\fR and recursively all packages that
|
||||
were installed automatically by it:
|
||||
\fBRemove and purge\fR the package \fBbsdtar\fR and \fBrecursively\fR all packages that were installed automatically by it:
|
||||
.RS 4
|
||||
$ xbps\-bin -Rp remove bsdtar
|
||||
|
||||
$ xbps\-bin \-Rp remove bsdtar
|
||||
.RE
|
||||
.PP
|
||||
\fBSets\fR the \fIvirtual\fR property in the \fBxbps\-devel\fR package:
|
||||
.RS 4
|
||||
|
||||
$ xbps\-bin set\-prop virtual xbps\-devel
|
||||
.RE
|
||||
.PP
|
||||
\fBUnsets\fR the \fIhold\fR property in the \fBcoreutils\fR package:
|
||||
.RS 4
|
||||
|
||||
$ xbps\-bin unset\-prop hold coreutils
|
||||
.RE
|
||||
.SH "BUGS"
|
||||
.sp
|
||||
Probably, but I try to make this not happen\&. Use it under your own responsability and enjoy your life\&.
|
||||
.sp
|
||||
Report bugs in \fIhttp://code\&.google\&.com/p/xbps\fR\&.
|
||||
Report bugs in http://code\&.google\&.com/p/xbps\&.
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
xbps\-repo(8), xbps\-src(8)
|
||||
.sp
|
||||
The XBPS project: \fIhttp://code\&.google\&.com/p/xbps\fR
|
||||
The XBPS project: http://code\&.google\&.com/p/xbps
|
||||
.sp
|
||||
To build binary packages, the xbps\-src(8) shell script is the command designed for this task\&. This must be retrieved from a Mercurial repository, available at \fIhttp://xbps\-src\&.xbps\&.googlecode\&.com/hg/\fR\&.
|
||||
To build binary packages, the xbps\-src(8) shell script is the command designed for this task\&. This must be retrieved from a Mercurial repository, available at http://xbps\-src\&.xbps\&.googlecode\&.com/hg/\&.
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
The \fBXBPS binary package system\fR has been designed and implemented by Juan Romero Pardines <xtraeme@gmail\&.com>\&.
|
||||
The X Binary Package System has been designed and implemented by Juan Romero Pardines <xtraeme@gmail\&.com>\&.
|
||||
|
@ -216,7 +216,8 @@ main(int argc, char **argv)
|
||||
if (argc != 2)
|
||||
usage();
|
||||
|
||||
dict = xbps_find_pkg_dict_from_plist_by_name(plist, argv[1]);
|
||||
dict = xbps_find_pkg_dict_from_plist_by_name(plist,
|
||||
"packages", argv[1]);
|
||||
if (dict == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
||||
* @def XBPS_RELVER
|
||||
* Current library release date.
|
||||
*/
|
||||
#define XBPS_RELVER "20110201"
|
||||
#define XBPS_RELVER "20110205"
|
||||
|
||||
/**
|
||||
* @def XBPS_META_PATH
|
||||
@ -174,6 +174,31 @@ int xbps_configure_all_pkgs(void);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @addtogroup pkgprops */
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* Sets the property \a prop in a package matching the name \a pkgname.
|
||||
*
|
||||
* @param[in] prop Property key to be set.
|
||||
* @param[in] pkgname Package name to set the property.
|
||||
*
|
||||
* @return 0 on success, otherwise an errno value.
|
||||
*/
|
||||
int xbps_property_set(const char *prop, const char *pkgname);
|
||||
|
||||
/**
|
||||
* Unsets the property \a prop in a package matching the name \a pkgname.
|
||||
*
|
||||
* @param[in] prop Property key to be unset.
|
||||
* @param[in] pkgname Package name to unset the property.
|
||||
*
|
||||
* @return 0 on success, otherwise an errno value.
|
||||
*/
|
||||
int xbps_property_unset(const char *prop, const char *pkgname);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* @ingroup vermatch
|
||||
*
|
||||
@ -436,7 +461,8 @@ prop_dictionary_t xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict,
|
||||
* a package name.
|
||||
*
|
||||
* @param[in] plist Path to a plist file.
|
||||
* @param[in] pkgname Package name to look for.
|
||||
* @param[in] key Proplib array's key name.
|
||||
* @param[in] pkgname Package name to match in array.
|
||||
*
|
||||
* @return The package's proplib dictionary on success, NULL otherwise and
|
||||
* errno is set appropiately. Returned dictionary is copied via
|
||||
@ -444,8 +470,25 @@ prop_dictionary_t xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict,
|
||||
* release the object with prop_object_release() when done.
|
||||
*/
|
||||
prop_dictionary_t xbps_find_pkg_dict_from_plist_by_name(const char *plist,
|
||||
const char *key,
|
||||
const char *pkgname);
|
||||
|
||||
/**
|
||||
* Finds the package's proplib dictionary in a plist file by specifying
|
||||
* a package pattern.
|
||||
*
|
||||
* @param[in] plist Path to a plist file.
|
||||
* @param[in] key Proplib array's key name.
|
||||
* @param[in] pattern Package pattern to match in array.
|
||||
*
|
||||
* @return The package's proplib dictionary on success, NULL otherwise and
|
||||
* errno is set appropiately. Returned dictionary should be released with
|
||||
* prop_object_release() when it's not any longer needed.
|
||||
*/
|
||||
prop_dictionary_t xbps_find_pkg_dict_from_plist_by_pattern(const char *plist,
|
||||
const char *key,
|
||||
const char *pattern);
|
||||
|
||||
/**
|
||||
* Finds a package's dictionary searching in the registered packages
|
||||
* database by using a package name or a package pattern.
|
||||
|
@ -199,6 +199,19 @@ int HIDDEN xbps_file_chdir_exec(const char *path, const char *arg, ...);
|
||||
int HIDDEN xbps_repository_pkg_replaces(prop_dictionary_t,
|
||||
prop_dictionary_t);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* From lib/plist.c
|
||||
*/
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_user_in_dict_by_name(prop_dictionary_t,
|
||||
const char *,
|
||||
const char *);
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_user_in_dict_by_pattern(prop_dictionary_t,
|
||||
const char *,
|
||||
const char *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_XBPS_API_IMPL_H_ */
|
||||
|
@ -40,10 +40,10 @@ endif
|
||||
OBJS = package_configure.o package_config_files.o package_orphans.o
|
||||
OBJS += package_remove.o package_remove_obsoletes.o package_state.o
|
||||
OBJS += package_unpack.o package_requiredby.o package_register.o
|
||||
OBJS += package_purge.o package_replaces.o initend.o
|
||||
OBJS += package_purge.o package_replaces.o package_properties.o
|
||||
OBJS += transaction_dictionary.o transaction_sortdeps.o
|
||||
OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o
|
||||
OBJS += util.o pkgmatch.o mkpath.o
|
||||
OBJS += util.o pkgmatch.o mkpath.o initend.o
|
||||
OBJS += regpkgdb_dictionary.o repository_register.o
|
||||
OBJS += repository_findpkg.o repository_plist.o repository_finddeps.o
|
||||
OBJS += repository_pool.o repository_sync_index.o
|
||||
|
268
lib/package_properties.c
Normal file
268
lib/package_properties.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <xbps_api.h>
|
||||
#include "xbps_api_impl.h"
|
||||
|
||||
/**
|
||||
* @file lib/package_properties.c
|
||||
* @brief Package properties routines
|
||||
* @defgroup pkgprops Package property functions
|
||||
*
|
||||
* Set and unset global properties for packages in the regpkgdb
|
||||
* plist file and its "properties" array object.
|
||||
*/
|
||||
int
|
||||
xbps_property_set(const char *key, const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t d, repo_pkgd = NULL, pkgd = NULL;
|
||||
prop_array_t props, provides = NULL, virtual = NULL;
|
||||
prop_string_t virtualpkg;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
bool regpkgd_alloc, pkgd_alloc, virtual_alloc, propbool;
|
||||
|
||||
assert(key != NULL);
|
||||
assert(pkgname != NULL);
|
||||
|
||||
regpkgd_alloc = pkgd_alloc = virtual_alloc = propbool = false;
|
||||
|
||||
if ((d = xbps_regpkgdb_dictionary_get()) == NULL) {
|
||||
/*
|
||||
* If regpkgdb dictionary doesn't exist, create it
|
||||
* and the properties array.
|
||||
*/
|
||||
d = prop_dictionary_create();
|
||||
if (d == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
regpkgd_alloc = true;
|
||||
props = prop_array_create();
|
||||
if (props == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set(d, "properties", props)) {
|
||||
rv = EINVAL;
|
||||
prop_object_release(props);
|
||||
goto out;
|
||||
}
|
||||
prop_object_release(props);
|
||||
}
|
||||
props = prop_dictionary_get(d, "properties");
|
||||
if (prop_object_type(props) != PROP_TYPE_ARRAY) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* If package dictionary doesn't exist, create it.
|
||||
*/
|
||||
pkgd = xbps_find_pkg_in_array_by_name(props, pkgname);
|
||||
if (pkgd == NULL) {
|
||||
pkgd = prop_dictionary_create();
|
||||
if (pkgd == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
pkgd_alloc = true;
|
||||
prop_dictionary_set_cstring_nocopy(pkgd, "pkgname", pkgname);
|
||||
if (!prop_array_add(props, pkgd)) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(key, "virtual") == 0) {
|
||||
/*
|
||||
* Sets the "virtual" property in package.
|
||||
*/
|
||||
virtual = prop_dictionary_get(pkgd, "provides");
|
||||
if (virtual == NULL) {
|
||||
virtual = prop_array_create();
|
||||
if (virtual == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
virtual_alloc = true;
|
||||
virtualpkg = prop_string_create_cstring(pkgname);
|
||||
if (virtualpkg == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
prop_string_append_cstring(virtualpkg, ">=0");
|
||||
prop_dictionary_set(pkgd, "pkgpattern", virtualpkg);
|
||||
prop_object_release(virtualpkg);
|
||||
virtualpkg = NULL;
|
||||
} else {
|
||||
/* property already set */
|
||||
xbps_dbg_printf("%s: property `%s' already set!\n",
|
||||
pkgname, key);
|
||||
rv = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Get the package object from repository pool.
|
||||
*/
|
||||
repo_pkgd = xbps_repository_pool_find_pkg(pkgname, false, false);
|
||||
if (repo_pkgd == NULL) {
|
||||
xbps_dbg_printf("%s: cannot find pkg dictionary "
|
||||
"in repository pool.\n", pkgname);
|
||||
rv = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
provides = prop_dictionary_get(repo_pkgd, "provides");
|
||||
if (provides == NULL) {
|
||||
xbps_dbg_printf("%s: pkg dictionary no provides "
|
||||
"array!\n", pkgname);
|
||||
prop_object_release(repo_pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set(pkgd, "provides", provides)) {
|
||||
prop_object_release(repo_pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prop_object_release(repo_pkgd);
|
||||
|
||||
} else if ((strcmp(key, "hold") == 0) ||
|
||||
(strcmp(key, "update-first") == 0)) {
|
||||
/*
|
||||
* Sets the property "key" in package.
|
||||
*/
|
||||
if (prop_dictionary_get_bool(pkgd, key, &propbool)) {
|
||||
rv = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
prop_dictionary_set_bool(pkgd, key, true);
|
||||
} else {
|
||||
/* invalid property */
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Add array with new properties set into the regpkgdb
|
||||
* dictionary.
|
||||
*/
|
||||
if (!prop_dictionary_set(d, "properties", props)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Write regpkgdb dictionary to plist file.
|
||||
*/
|
||||
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_externalize_to_zfile(d, plist)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (virtual_alloc)
|
||||
prop_object_release(virtual);
|
||||
if (pkgd_alloc)
|
||||
prop_object_release(pkgd);
|
||||
if (regpkgd_alloc)
|
||||
prop_object_release(d);
|
||||
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
xbps_property_unset(const char *key, const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t d, pkgd;
|
||||
prop_array_t props;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
|
||||
assert(key != NULL);
|
||||
assert(pkgname != NULL);
|
||||
|
||||
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
|
||||
return ENODEV;
|
||||
|
||||
props = prop_dictionary_get(d, "properties");
|
||||
if (prop_object_type(props) != PROP_TYPE_ARRAY) {
|
||||
rv = ENODEV;
|
||||
goto out;
|
||||
}
|
||||
pkgd = xbps_find_pkg_in_array_by_name(props, pkgname);
|
||||
if (pkgd == NULL) {
|
||||
rv = ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if ((strcmp(key, "virtual") == 0) ||
|
||||
(strcmp(key, "hold") == 0) ||
|
||||
(strcmp(key, "update-first") == 0)) {
|
||||
/* remove the property object matching the key */
|
||||
prop_dictionary_remove(pkgd, key);
|
||||
} else {
|
||||
/* invalid property */
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* If pkg dictionary does not contain any property, remove
|
||||
* the object completely.
|
||||
*/
|
||||
if (!prop_dictionary_get(d, "virtual") &&
|
||||
!prop_dictionary_get(d, "hold") &&
|
||||
!prop_dictionary_get(d, "update-first"))
|
||||
xbps_remove_pkg_from_array_by_name(props, pkgname);
|
||||
|
||||
if (!prop_dictionary_set(d, "properties", props)) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Write regpkgdb dictionary to plist file.
|
||||
*/
|
||||
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_externalize_to_zfile(d, plist)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return rv;
|
||||
}
|
@ -216,10 +216,13 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
|
||||
}
|
||||
array = prop_dictionary_get(dict, "packages");
|
||||
if (array == NULL) {
|
||||
rv = EINVAL;
|
||||
if (newpkg)
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
array = prop_array_create();
|
||||
if (!prop_dictionary_set(dict, "packages", array)) {
|
||||
rv = EINVAL;
|
||||
if (newpkg)
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if ((rv = set_new_state(pkgd, state)) != 0) {
|
||||
if (newpkg)
|
||||
|
237
lib/plist.c
237
lib/plist.c
@ -167,27 +167,32 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict,
|
||||
return rv;
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_dict_from_plist_by_name(const char *plist, const char *pkgname)
|
||||
static prop_dictionary_t
|
||||
find_pkg_dict_from_plist(const char *plist,
|
||||
const char *key,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
{
|
||||
prop_dictionary_t dict, obj, res;
|
||||
|
||||
assert(plist != NULL);
|
||||
assert(pkgname != NULL);
|
||||
assert(str != NULL);
|
||||
|
||||
dict = prop_dictionary_internalize_from_zfile(plist);
|
||||
if (dict == NULL) {
|
||||
xbps_dbg_printf("cannot internalize %s for pkg %s: %s",
|
||||
plist, pkgname, strerror(errno));
|
||||
plist, str, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (bypattern)
|
||||
obj = xbps_find_pkg_in_dict_by_pattern(dict, key, str);
|
||||
else
|
||||
obj = xbps_find_pkg_in_dict_by_name(dict, key, str);
|
||||
|
||||
obj = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname);
|
||||
if (obj == NULL) {
|
||||
prop_object_release(dict);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = prop_dictionary_copy(obj);
|
||||
prop_object_release(dict);
|
||||
|
||||
@ -195,42 +200,19 @@ xbps_find_pkg_dict_from_plist_by_name(const char *plist, const char *pkgname)
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_dict_installed(const char *str, bool bypattern)
|
||||
xbps_find_pkg_dict_from_plist_by_name(const char *plist,
|
||||
const char *key,
|
||||
const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t d, pkgd, rpkgd = NULL;
|
||||
pkg_state_t state = 0;
|
||||
return find_pkg_dict_from_plist(plist, key, pkgname, false);
|
||||
}
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (bypattern)
|
||||
pkgd = xbps_find_pkg_in_dict_by_pattern(d, "packages", str);
|
||||
else
|
||||
pkgd = xbps_find_pkg_in_dict_by_name(d, "packages", str);
|
||||
if (pkgd == NULL)
|
||||
goto out;
|
||||
|
||||
if (xbps_get_pkg_state_dictionary(pkgd, &state) != 0)
|
||||
goto out;
|
||||
|
||||
switch (state) {
|
||||
case XBPS_PKG_STATE_INSTALLED:
|
||||
case XBPS_PKG_STATE_UNPACKED:
|
||||
rpkgd = prop_dictionary_copy(pkgd);
|
||||
break;
|
||||
case XBPS_PKG_STATE_CONFIG_FILES:
|
||||
errno = ENOENT;
|
||||
xbps_dbg_printf("'%s' installed but its state is "
|
||||
"config-files\n",str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out:
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return rpkgd;
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_dict_from_plist_by_pattern(const char *plist,
|
||||
const char *key,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_dict_from_plist(plist, key, pattern, true);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -254,7 +236,7 @@ static prop_dictionary_t
|
||||
find_pkg_in_array(prop_array_t array, const char *str, bool bypattern)
|
||||
{
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj;
|
||||
prop_object_t obj = NULL;
|
||||
const char *pkgver, *dpkgn;
|
||||
|
||||
assert(array != NULL);
|
||||
@ -266,19 +248,29 @@ find_pkg_in_array(prop_array_t array, const char *str, bool bypattern)
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
if (bypattern) {
|
||||
if (xbps_find_virtual_pkg_in_dict(obj, str, true))
|
||||
break;
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &pkgver);
|
||||
/*
|
||||
* Check if package pattern matches the
|
||||
* pkgver string object in dictionary.
|
||||
*/
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &pkgver))
|
||||
continue;
|
||||
if (xbps_pkgpattern_match(pkgver, __UNCONST(str)))
|
||||
break;
|
||||
} else {
|
||||
if (xbps_find_virtual_pkg_in_dict(obj, str, false))
|
||||
/*
|
||||
* Finally check if package pattern matches
|
||||
* any virtual package version in dictionary.
|
||||
*/
|
||||
if (xbps_find_virtual_pkg_in_dict(obj, str, true))
|
||||
break;
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgname", &dpkgn);
|
||||
} else {
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgname", &dpkgn))
|
||||
continue;
|
||||
if (strcmp(dpkgn, str) == 0)
|
||||
break;
|
||||
if (xbps_find_virtual_pkg_in_dict(obj, str, false))
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
@ -301,11 +293,93 @@ xbps_find_pkg_in_array_by_pattern(prop_array_t array, const char *pattern)
|
||||
return find_pkg_in_array(array, pattern, true);
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_virtualpkg_user_in_regpkgdb(const char *virtualpkg, bool bypattern)
|
||||
{
|
||||
prop_array_t virtual;
|
||||
prop_dictionary_t d;
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj;
|
||||
const char *pkg = NULL;
|
||||
bool found = false;
|
||||
|
||||
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((iter = xbps_get_array_iter_from_dict(d, "properties")) == NULL) {
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return NULL;
|
||||
}
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
virtual = prop_dictionary_get(obj, "provides");
|
||||
if (virtual == NULL)
|
||||
continue;
|
||||
if (bypattern)
|
||||
found = xbps_find_pkgpattern_in_array(virtual, virtualpkg);
|
||||
else
|
||||
found = xbps_find_pkgname_in_array(virtual, virtualpkg);
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
if (bypattern)
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgpattern", &pkg);
|
||||
else
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgname", &pkg);
|
||||
|
||||
break;
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
static prop_dictionary_t
|
||||
find_virtualpkg_user_in_array(prop_array_t array,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
{
|
||||
prop_object_t obj = NULL;
|
||||
prop_object_iterator_t iter;
|
||||
const char *pkgver, *dpkgn, *virtualpkg;
|
||||
|
||||
assert(array != NULL);
|
||||
assert(str != NULL);
|
||||
|
||||
virtualpkg = find_virtualpkg_user_in_regpkgdb(str, bypattern);
|
||||
if (virtualpkg == NULL)
|
||||
return NULL;
|
||||
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
if (bypattern) {
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &pkgver);
|
||||
if (xbps_pkgpattern_match(pkgver,
|
||||
__UNCONST(virtualpkg)))
|
||||
break;
|
||||
} else {
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgname", &dpkgn);
|
||||
if (strcmp(dpkgn, virtualpkg) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static prop_dictionary_t
|
||||
find_pkg_in_dict(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
bool bypattern,
|
||||
bool virtual)
|
||||
{
|
||||
prop_array_t array;
|
||||
|
||||
@ -317,23 +391,78 @@ find_pkg_in_dict(prop_dictionary_t d,
|
||||
if (prop_object_type(array) != PROP_TYPE_ARRAY)
|
||||
return NULL;
|
||||
|
||||
if (virtual)
|
||||
return find_virtualpkg_user_in_array(array, str, bypattern);
|
||||
|
||||
return find_pkg_in_array(array, str, bypattern);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict,
|
||||
xbps_find_pkg_in_dict_by_name(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pkgname)
|
||||
{
|
||||
return find_pkg_in_dict(dict, key, pkgname, false);
|
||||
return find_pkg_in_dict(d, key, pkgname, false, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict,
|
||||
xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_in_dict(dict, key, pattern, true);
|
||||
return find_pkg_in_dict(d, key, pattern, true, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_user_in_dict_by_name(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *name)
|
||||
{
|
||||
return find_pkg_in_dict(d, key, name, false, true);
|
||||
}
|
||||
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_user_in_dict_by_pattern(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_in_dict(d, key, pattern, true, true);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_dict_installed(const char *str, bool bypattern)
|
||||
{
|
||||
prop_dictionary_t d, pkgd, rpkgd = NULL;
|
||||
pkg_state_t state = 0;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
|
||||
return NULL;
|
||||
|
||||
pkgd = find_pkg_in_dict(d, "packages", str, bypattern, false);
|
||||
if (pkgd == NULL)
|
||||
goto out;
|
||||
|
||||
if (xbps_get_pkg_state_dictionary(pkgd, &state) != 0)
|
||||
goto out;
|
||||
|
||||
switch (state) {
|
||||
case XBPS_PKG_STATE_INSTALLED:
|
||||
case XBPS_PKG_STATE_UNPACKED:
|
||||
rpkgd = prop_dictionary_copy(pkgd);
|
||||
break;
|
||||
case XBPS_PKG_STATE_CONFIG_FILES:
|
||||
errno = ENOENT;
|
||||
xbps_dbg_printf("'%s' installed but its state is "
|
||||
"config-files\n",str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out:
|
||||
xbps_regpkgdb_dictionary_release();
|
||||
return rpkgd;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -235,9 +235,34 @@ struct repo_pool_fpkg {
|
||||
prop_dictionary_t pkgd;
|
||||
const char *pattern;
|
||||
bool bypattern;
|
||||
bool newpkg_found;
|
||||
bool pkgfound;
|
||||
};
|
||||
|
||||
static int
|
||||
repo_find_virtualpkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
{
|
||||
struct repo_pool_fpkg *rpf = arg;
|
||||
|
||||
if (rpf->bypattern) {
|
||||
rpf->pkgd =
|
||||
xbps_find_virtualpkg_user_in_dict_by_pattern(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
} else {
|
||||
rpf->pkgd =
|
||||
xbps_find_virtualpkg_user_in_dict_by_name(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
}
|
||||
if (rpf->pkgd) {
|
||||
prop_dictionary_set_cstring(rpf->pkgd, "repository",
|
||||
rpi->rpi_uri);
|
||||
*done = true;
|
||||
rpf->pkgfound = true;
|
||||
return 0;
|
||||
}
|
||||
/* not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
{
|
||||
@ -250,7 +275,6 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
}
|
||||
|
||||
if (rpf->pkgd) {
|
||||
/*
|
||||
* Package dictionary found, add the "repository"
|
||||
@ -259,11 +283,10 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
prop_dictionary_set_cstring(rpf->pkgd, "repository",
|
||||
rpi->rpi_uri);
|
||||
*done = true;
|
||||
errno = 0;
|
||||
rpf->pkgfound = true;
|
||||
return 0;
|
||||
}
|
||||
/* Not found */
|
||||
errno = ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -290,6 +313,8 @@ repo_find_best_pkg_cb(struct repository_pool_index *rpi,
|
||||
* the version currently installed.
|
||||
*/
|
||||
instpkgd = xbps_find_pkg_dict_installed(rpf->pattern, false);
|
||||
if (instpkgd == NULL)
|
||||
return 0;
|
||||
prop_dictionary_get_cstring_nocopy(instpkgd,
|
||||
"version", &instver);
|
||||
prop_dictionary_get_cstring_nocopy(rpf->pkgd,
|
||||
@ -303,11 +328,11 @@ repo_find_best_pkg_cb(struct repository_pool_index *rpi,
|
||||
/*
|
||||
* New package version found, exit from the loop.
|
||||
*/
|
||||
rpf->newpkg_found = true;
|
||||
prop_dictionary_set_cstring(rpf->pkgd, "repository",
|
||||
rpi->rpi_uri);
|
||||
errno = 0;
|
||||
*done = true;
|
||||
errno = 0;
|
||||
rpf->pkgfound = true;
|
||||
return 0;
|
||||
}
|
||||
xbps_dbg_printf("Skipping '%s-%s' (installed: %s) "
|
||||
@ -315,7 +340,6 @@ repo_find_best_pkg_cb(struct repository_pool_index *rpi,
|
||||
rpi->rpi_uri);
|
||||
errno = EEXIST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -335,14 +359,41 @@ xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best)
|
||||
rpf->pattern = pkg;
|
||||
rpf->bypattern = bypattern;
|
||||
|
||||
if (best)
|
||||
if (best) {
|
||||
/*
|
||||
* Look for the best package version of a package name or
|
||||
* pattern in all repositories.
|
||||
*/
|
||||
rv = xbps_repository_pool_foreach(repo_find_best_pkg_cb, rpf);
|
||||
else
|
||||
rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf);
|
||||
|
||||
if (rv != 0 || (rv == 0 && (errno == ENOENT || errno == EEXIST)))
|
||||
goto out;
|
||||
|
||||
if (rv != 0) {
|
||||
errno = rv;
|
||||
goto out;
|
||||
} else if (rpf->pkgfound == false) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Look for any virtual package set by the user matching
|
||||
* the package name or pattern.
|
||||
*/
|
||||
rv = xbps_repository_pool_foreach(repo_find_virtualpkg_cb, rpf);
|
||||
if (rv != 0) {
|
||||
errno = rv;
|
||||
goto out;
|
||||
} else if (rpf->pkgfound == false) {
|
||||
/*
|
||||
* No virtual package found. Look for real package
|
||||
* names or patterns instead.
|
||||
*/
|
||||
rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf);
|
||||
if (rv != 0) {
|
||||
errno = rv;
|
||||
goto out;
|
||||
} else if (rpf->pkgfound == false) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
pkgd = prop_dictionary_copy(rpf->pkgd);
|
||||
out:
|
||||
free(rpf);
|
||||
|
Loading…
Reference in New Issue
Block a user