Versioned provisions.

This patch introduces versioned provisions in "provision 1.0-1" format.
_alpm_db_whatprovides was modified accordingly (added sync500.py),
alpm_depcmp was modified accordingly (add043.py passes now; added add044.py
and add045.py).

Notes:
alpm_db_search now uses the whole versioned %PROVIDES% string in its search.
debug logging was simplified in alpm_depcmp.

Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
[Xavier: fixed a few typos, duplicate const strings with strdup before
modifying them, put some debugging back in alpm_depcmp, minor code cleanups
(var/function renaming), added a note in PKGBUILD man page.]
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
[Dan: made strcmp checks clearer, added a comment]
Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Nagy Gabor 2007-11-16 22:37:57 +01:00 committed by Dan McGee
parent 23b4e0270b
commit 84ebf82319
8 changed files with 94 additions and 25 deletions

View File

@ -133,6 +133,8 @@ Options and Directives
a package to provide dependencies other than its own package name. For
example, the dcron package can provide 'cron', which allows packages to
depend on 'cron' rather than 'dcron OR fcron'.
Versioned provisions are also possible. For example, dcron can provide
'cron 2.0' to satisfy the 'cron>=2.0' dependency of other packages.
*replaces (array)*::
An array of packages that this package should replace, and can be used

View File

@ -783,6 +783,25 @@ pmdb_t *_alpm_db_register_sync(const char *treename)
return(db);
}
/* helper function for alpm_list_find and _alpm_db_whatprovides
*
* @return "provision.name" == needle (as string)
*/
int _alpm_prov_cmp(const void *provision, const void *needle)
{
char *tmpptr;
char *provname = strdup(provision);
int retval = 0;
tmpptr = strchr(provname, ' ');
if(tmpptr != NULL) { /* provision-version */
*tmpptr='\0';
}
retval = strcmp(provname, needle);
free(provname);
return(retval);
}
/* return a alpm_list_t of packages in "db" that provide "package"
*/
alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package)
@ -799,7 +818,7 @@ alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package)
for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) {
pmpkg_t *info = lp->data;
if(alpm_list_find_str(alpm_pkg_get_provides(info), package)) {
if(alpm_list_find(alpm_pkg_get_provides(info), (const void *)package, _alpm_prov_cmp)) {
pkgs = alpm_list_add(pkgs, info);
}
}

View File

@ -58,6 +58,7 @@ pmdb_t *_alpm_db_register_local(void);
pmdb_t *_alpm_db_register_sync(const char *treename);
/* Provision */
int _alpm_prov_cmp(const void *provision, const void *needle);
alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package);
/* be.c, backend specific calls */

View File

@ -369,8 +369,10 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
/* else if still not found... */
if(!found) {
char *depstring = alpm_dep_get_string(depend);
_alpm_log(PM_LOG_DEBUG, "missing dependency '%s' for package '%s'\n",
(char*)j->data, alpm_pkg_get_name(tp));
depstring, alpm_pkg_get_name(tp));
free(depstring);
miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend->mod,
depend->name, depend->version);
if(!_alpm_depmiss_isin(miss, baddeps)) {
@ -415,8 +417,10 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
for(l = _alpm_db_get_pkgcache(db); l; l = l->next) {
pmpkg_t *pkg = l->data;
if(alpm_depcmp(pkg, depend) && !_alpm_pkg_find(alpm_pkg_get_name(pkg), packages)) {
char *depstring = alpm_dep_get_string(depend);
_alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' satisfied by installed package '%s'\n",
(char*)k->data, alpm_pkg_get_name(pkg));
depstring, alpm_pkg_get_name(pkg));
free(depstring);
satisfied = 1;
break;
}
@ -464,38 +468,41 @@ static int dep_vercmp(const char *version1, pmdepmod_t mod,
int SYMEXPORT alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep)
{
int equal = 0;
alpm_list_t *i;
ALPM_LOG_FUNC;
const char *pkgname = alpm_pkg_get_name(pkg);
const char *pkgversion = alpm_pkg_get_version(pkg);
int satisfy = 0;
if(strcmp(pkgname, dep->name) == 0
|| alpm_list_find_str(alpm_pkg_get_provides(pkg), dep->name)) {
/* check (pkg->name, pkg->version) */
satisfy = (strcmp(pkgname, dep->name) == 0
&& dep_vercmp(pkgversion, dep->mod, dep->version));
equal = dep_vercmp(pkgversion, dep->mod, dep->version);
/* check provisions, format : "name version" */
for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) {
char *provname = strdup(i->data);
char *provver = strchr(provname, ' ');
char *mod = "~=";
switch(dep->mod) {
case PM_DEP_MOD_EQ: mod = "=="; break;
case PM_DEP_MOD_GE: mod = ">="; break;
case PM_DEP_MOD_LE: mod = "<="; break;
default: break;
}
if(strlen(dep->version) > 0) {
_alpm_log(PM_LOG_DEBUG, "depcmp: %s-%s %s %s-%s => %s\n",
pkgname, pkgversion,
mod, dep->name, dep->version, (equal ? "match" : "no match"));
if(provver == NULL) { /* no provision version */
satisfy = (dep->mod == PM_DEP_MOD_ANY
&& strcmp(provname, dep->name) == 0);
} else {
_alpm_log(PM_LOG_DEBUG, "depcmp: %s-%s %s %s => %s\n",
pkgname, pkgversion,
mod, dep->name, (equal ? "match" : "no match"));
/* replace the space with a NULL byte, and advance ptr the version */
*provver = '\0';
provver += 1;
satisfy = (strcmp(provname, dep->name) == 0
&& dep_vercmp(provver, dep->mod, dep->version));
}
free(provname);
}
return(equal);
char *depstring = alpm_dep_get_string(dep);
_alpm_log(PM_LOG_DEBUG, "alpm_depcmp %s-%s %s : %s\n",
pkgname, pkgversion, depstring, satisfy ? "match" : "no match");
free(depstring);
return(satisfy);
}
pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)

View File

@ -492,8 +492,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
/* check if this package provides the package it's conflicting with */
if(alpm_list_find_str(alpm_pkg_get_provides(sync->pkg),
conflict->package2)) {
if(alpm_list_find(alpm_pkg_get_provides(sync->pkg),
conflict->package2, _alpm_prov_cmp)) {
/* treat like a replaces item so requiredby fields are
* inherited properly. */
_alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n",

15
pactest/tests/add044.py Normal file
View File

@ -0,0 +1,15 @@
self.description = "provision>=1.0-2 dependency (2)"
p = pmpkg("pkg1", "1.0-2")
p.depends = ["provision>=1.0-2"]
self.addpkg(p)
lp = pmpkg("pkg2", "1.0-2")
lp.provides = ["provision 1.0-2"]
self.addpkg2db("local", lp)
self.args = "-A %s" % p.filename()
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg1")
self.addrule("PKG_EXIST=pkg2")

15
pactest/tests/add045.py Normal file
View File

@ -0,0 +1,15 @@
self.description = "provision>=1.0-2 dependency (3)"
p = pmpkg("pkg1", "1.0-2")
p.depends = ["provision>=1.0-2"]
self.addpkg(p)
lp = pmpkg("pkg2", "1.0-2")
lp.provides = ["provision 1.0-1"]
self.addpkg2db("local", lp)
self.args = "-A %s" % p.filename()
self.addrule("PACMAN_RETCODE=1")
self.addrule("!PKG_EXIST=pkg1")
self.addrule("PKG_EXIST=pkg2")

10
pactest/tests/sync500.py Normal file
View File

@ -0,0 +1,10 @@
self.description = "-S provision"
sp = pmpkg("pkg1")
sp.provides = ["provision 1.0-1"]
self.addpkg2db("sync", sp)
self.args = "-S provision"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg1")