From a60f0f7d91c2c79f2264d75439fafda064c068a7 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 20 Oct 2012 16:48:15 +0000 Subject: [PATCH] Implement recommends and suggests. --- python/pakfire/api.py | 4 +-- python/pakfire/cli.py | 6 ++++- python/pakfire/constants.py | 12 +++++++-- python/pakfire/packages/base.py | 18 ++++++++++++++ python/pakfire/packages/file.py | 20 +++++++++++++++ python/pakfire/packages/installed.py | 18 ++++++++++++++ python/pakfire/packages/lexer.py | 2 +- python/pakfire/packages/make.py | 16 ++++++++++++ python/pakfire/packages/packager.py | 4 +++ python/pakfire/packages/solv.py | 8 ++++++ python/pakfire/repository/database.py | 12 ++++++++- python/pakfire/repository/index.py | 10 ++++++++ python/pakfire/satsolver.py | 1 + python/src/_pakfiremodule.c | 5 ++++ python/src/request.c | 6 ++--- python/src/solvable.c | 36 +++++++++++++++++++++++++++ python/src/solvable.h | 6 +++++ 17 files changed, 174 insertions(+), 10 deletions(-) diff --git a/python/pakfire/api.py b/python/pakfire/api.py index 372e4d544..6f93332ce 100644 --- a/python/pakfire/api.py +++ b/python/pakfire/api.py @@ -26,10 +26,10 @@ from errors import * Pakfire = base.Pakfire -def install(requires, **pakfire_args): +def install(requires, ignore_recommended=False, **pakfire_args): pakfire = Pakfire(**pakfire_args) - return pakfire.install(requires) + return pakfire.install(requires, ignore_recommended=ignore_recommended) def resolvdep(pkgs, **pakfire_args): pakfire = Pakfire(**pakfire_args) diff --git a/python/pakfire/cli.py b/python/pakfire/cli.py index 5b56b4501..9a72d747f 100644 --- a/python/pakfire/cli.py +++ b/python/pakfire/cli.py @@ -148,6 +148,8 @@ class Cli(object): help=_("Install one or more packages to the system.")) sub_install.add_argument("package", nargs="+", help=_("Give name of at least one package to install.")) + sub_install.add_argument("--without-recommends", action="store_true", + help=_("Don't install recommended packages.")) sub_install.add_argument("action", action="store_const", const="install") def parse_command_reinstall(self): @@ -317,7 +319,9 @@ class Cli(object): **args) def handle_install(self): - pakfire.install(self.args.package, **self.pakfire_args) + pakfire.install(self.args.package, + ignore_recommended=self.args.without_recommends, + **self.pakfire_args) def handle_reinstall(self): pakfire.reinstall(self.args.package, **self.pakfire_args) diff --git a/python/pakfire/constants.py b/python/pakfire/constants.py index 45b1b40c5..f10daecff 100644 --- a/python/pakfire/constants.py +++ b/python/pakfire/constants.py @@ -75,8 +75,8 @@ PACKAGE_FORMATS_SUPPORTED = [0, 1, 2, 3, 4] PACKAGE_EXTENSION = "pfm" MAKEFILE_EXTENSION = "nm" -DATABASE_FORMAT = 3 -DATABASE_FORMATS_SUPPORTED = [0, 1, 2, 3] +DATABASE_FORMAT = 4 +DATABASE_FORMATS_SUPPORTED = [0, 1, 2, 3, 4] PACKAGE_FILENAME_FMT = "%(name)s-%(version)s-%(release)s.%(arch)s.%(ext)s" @@ -177,6 +177,14 @@ dependencies def obsoletes %(obsoletes)s end + + def recommends +%(recommends)s + end + + def suggests +%(suggests)s + end end # EOF diff --git a/python/pakfire/packages/base.py b/python/pakfire/packages/base.py index 91625362d..8e5ba030e 100644 --- a/python/pakfire/packages/base.py +++ b/python/pakfire/packages/base.py @@ -171,6 +171,16 @@ class Package(object): items.append((caption, req)) caption = "" + caption = _("Recommends") + for req in sorted(self.recommends): + items.append((caption, req)) + caption = "" + + caption = _("Suggests") + for req in sorted(self.suggests): + items.append((caption, req)) + caption = "" + # Append filelist if requested. if filelist: for file in self.filelist: @@ -455,6 +465,14 @@ class Package(object): def obsoletes(self): return self.metadata.get("PKG_OBSOLETES", "").splitlines() + @property + def recommends(self): + return [] + + @property + def suggests(self): + return [] + @property def scriptlets(self): return self.metadata.get("PKG_SCRIPTLETS", "").splitlines() diff --git a/python/pakfire/packages/file.py b/python/pakfire/packages/file.py index 070c763b7..4f465ec69 100644 --- a/python/pakfire/packages/file.py +++ b/python/pakfire/packages/file.py @@ -960,6 +960,26 @@ class FilePackage(Package): conflicts = conflicts.splitlines() return self.filter_deps(conflicts) + @property + def recommends(self): + recommends = self.lexer.deps.get_var("recommends") + + if not recommends: + return [] + + recommends = recommends.splitlines() + return self.filter_deps(recommends) + + @property + def suggests(self): + suggests = self.lexer.deps.get_var("suggests") + + if not suggests: + return [] + + suggests = suggests.splitlines() + return self.filter_deps(suggests) + class SourcePackage(FilePackage): _type = "source" diff --git a/python/pakfire/packages/installed.py b/python/pakfire/packages/installed.py index 33c241d0c..de4d4f61f 100644 --- a/python/pakfire/packages/installed.py +++ b/python/pakfire/packages/installed.py @@ -160,6 +160,24 @@ class DatabasePackage(Package): def obsoletes(self): return self.metadata.get("obsoletes", "").splitlines() + @property + def recommends(self): + recommends = self.metadata.get("recommends", None) + + if recommends: + return recommends.splitlines() + + return [] + + @property + def suggests(self): + suggests = self.metadata.get("suggests", None) + + if suggests: + return suggests.splitlines() + + return [] + @property def hash1(self): return self.metadata.get("hash1") diff --git a/python/pakfire/packages/lexer.py b/python/pakfire/packages/lexer.py index af6dda0fd..52eeb1978 100644 --- a/python/pakfire/packages/lexer.py +++ b/python/pakfire/packages/lexer.py @@ -365,7 +365,7 @@ class Lexer(object): raise LexerUnhandledLine, "%d: %s" % (self.lineno, line) - DEP_DEFINITIONS = ("prerequires", "requires", "provides", "conflicts", "obsoletes",) + DEP_DEFINITIONS = ("prerequires", "requires", "provides", "conflicts", "obsoletes", "recommends", "suggests") def parse_definition(self, pattern=LEXER_DEFINITION): line = self.get_line(self._lineno) diff --git a/python/pakfire/packages/make.py b/python/pakfire/packages/make.py index 263527ab8..34e9d5fa4 100644 --- a/python/pakfire/packages/make.py +++ b/python/pakfire/packages/make.py @@ -293,6 +293,14 @@ class Makefile(MakefileBase): def conflicts(self): return [] + @property + def recommends(self): + return [] + + @property + def suggests(self): + return [] + @property def files(self): files = [] @@ -571,6 +579,14 @@ class MakefilePackage(MakefileBase): def conflicts(self): return self.get_deps("conflicts") + @property + def recommends(self): + return self.get_deps("recommends") + + @property + def suggests(self): + return self.get_deps("suggests") + def get_scriptlet(self, type): return self.lexer.get_scriptlet(type) diff --git a/python/pakfire/packages/packager.py b/python/pakfire/packages/packager.py index d44a6dc19..671574132 100644 --- a/python/pakfire/packages/packager.py +++ b/python/pakfire/packages/packager.py @@ -265,6 +265,10 @@ class BinaryPackager(Packager): for d in self.pkg.conflicts]), "obsoletes" : "\n".join([PACKAGE_INFO_DEPENDENCY_LINE % d \ for d in self.pkg.obsoletes]), + "recommends" : "\n".join([PACKAGE_INFO_DEPENDENCY_LINE % d \ + for d in self.pkg.recommends]), + "suggests" : "\n".join([PACKAGE_INFO_DEPENDENCY_LINE % d \ + for d in self.pkg.suggests]), }) # Format description. diff --git a/python/pakfire/packages/solv.py b/python/pakfire/packages/solv.py index 84c127d5a..80a30c259 100644 --- a/python/pakfire/packages/solv.py +++ b/python/pakfire/packages/solv.py @@ -181,6 +181,14 @@ class SolvPackage(base.Package): def conflicts(self): return self.solvable.get_conflicts() + @property + def recommends(self): + return self.solvable.get_recommends() + + @property + def suggests(self): + return self.solvable.get_suggests() + @property def filename(self): return self.solvable.get_filename() diff --git a/python/pakfire/repository/database.py b/python/pakfire/repository/database.py index a5e5b858b..6f02422c2 100644 --- a/python/pakfire/repository/database.py +++ b/python/pakfire/repository/database.py @@ -189,6 +189,8 @@ class DatabaseLocal(Database): requires TEXT, conflicts TEXT, obsoletes TEXT, + recommends TEXT, + suggests TEXT, license TEXT, summary TEXT, description TEXT, @@ -250,6 +252,10 @@ class DatabaseLocal(Database): if self.format < 3: c.execute("ALTER TABLE files ADD COLUMN `capabilities` TEXT") + if self.format < 4: + c.execute("ALTER TABLE packages ADD COLUMN recommends TEXT AFTER obsoletes") + c.execute("ALTER TABLE packages ADD COLUMN suggests TEXT AFTER recommends") + # In the end, we can easily update the version of the database. c.execute("UPDATE settings SET val = ? WHERE key = 'version'", (DATABASE_FORMAT,)) self.__format = DATABASE_FORMAT @@ -278,6 +284,8 @@ class DatabaseLocal(Database): requires, conflicts, obsoletes, + recommends, + suggests, license, summary, description, @@ -290,7 +298,7 @@ class DatabaseLocal(Database): installed, repository, reason - ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", + ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", ( pkg.name, pkg.epoch, @@ -305,6 +313,8 @@ class DatabaseLocal(Database): "\n".join(pkg.requires), "\n".join(pkg.conflicts), "\n".join(pkg.obsoletes), + "\n".join(pkg.recommends), + "\n".join(pkg.suggests), pkg.license, pkg.summary, pkg.description, diff --git a/python/pakfire/repository/index.py b/python/pakfire/repository/index.py index 7620b3897..452ef5e29 100644 --- a/python/pakfire/repository/index.py +++ b/python/pakfire/repository/index.py @@ -147,6 +147,16 @@ class Index(object): rel = self.create_relation(file) solvable.add_provides(rel) + # Import all recommends. + for reco in pkg.recommends: + rel = self.create_relation(reco) + solvable.add_recommends(rel) + + # Import all suggests. + for sugg in pkg.suggests: + rel = self.create_relation(sugg) + solvable.add_suggests(rel) + def rem_package(self, pkg): """ Delete the solvable from the index. diff --git a/python/pakfire/satsolver.py b/python/pakfire/satsolver.py index 48c6d0dee..f10d61941 100644 --- a/python/pakfire/satsolver.py +++ b/python/pakfire/satsolver.py @@ -116,6 +116,7 @@ class Solver(object): "allow_downgrade" : SOLVER_FLAG_ALLOW_DOWNGRADE, "allow_uninstall" : SOLVER_FLAG_ALLOW_UNINSTALL, "allow_vendorchange" : SOLVER_FLAG_ALLOW_VENDORCHANGE, + "ignore_recommended" : SOLVER_FLAG_IGNORE_RECOMMENDED, } def __init__(self, pakfire, request, logger=None): diff --git a/python/src/_pakfiremodule.c b/python/src/_pakfiremodule.c index 8e80468fd..1a8b34fb2 100644 --- a/python/src/_pakfiremodule.c +++ b/python/src/_pakfiremodule.c @@ -147,6 +147,10 @@ static PyMethodDef Solvable_methods[] = { {"get_obsoletes", (PyCFunction)Solvable_get_obsoletes, METH_NOARGS, NULL}, {"add_conflicts", (PyCFunction)Solvable_add_conflicts, METH_VARARGS, NULL}, {"get_conflicts", (PyCFunction)Solvable_get_conflicts, METH_NOARGS, NULL}, + {"add_recommends", (PyCFunction)Solvable_add_recommends, METH_VARARGS, NULL}, + {"get_recommends", (PyCFunction)Solvable_get_recommends, METH_NOARGS, NULL}, + {"add_suggests", (PyCFunction)Solvable_add_suggests, METH_VARARGS, NULL}, + {"get_suggests", (PyCFunction)Solvable_get_suggests, METH_NOARGS, NULL}, { NULL, NULL, 0, NULL } }; @@ -317,4 +321,5 @@ void init_pakfire(void) { PyDict_SetItemString(d, "SOLVER_FLAG_ALLOW_UNINSTALL", Py_BuildValue("i", SOLVER_FLAG_ALLOW_UNINSTALL)); PyDict_SetItemString(d, "SOLVER_FLAG_NO_UPDATEPROVIDE", Py_BuildValue("i", SOLVER_FLAG_NO_UPDATEPROVIDE)); PyDict_SetItemString(d, "SOLVER_FLAG_SPLITPROVIDES", Py_BuildValue("i", SOLVER_FLAG_SPLITPROVIDES)); + PyDict_SetItemString(d, "SOLVER_FLAG_IGNORE_RECOMMENDED", Py_BuildValue("i", SOLVER_FLAG_IGNORE_RECOMMENDED)); } diff --git a/python/src/request.c b/python/src/request.c index 7d7c5b200..974e853db 100644 --- a/python/src/request.c +++ b/python/src/request.c @@ -64,15 +64,15 @@ PyObject *Request_dealloc(RequestObject *self) { } void _Request_solvable(RequestObject *self, Id what, Id solvable) { - queue_push2(&self->_queue, what|SOLVER_SOLVABLE, solvable); + queue_push2(&self->_queue, what|SOLVER_SOLVABLE|SOLVER_WEAK, solvable); } void _Request_relation(RequestObject *self, Id what, Id relation) { - queue_push2(&self->_queue, what|SOLVER_SOLVABLE_PROVIDES, relation); + queue_push2(&self->_queue, what|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK, relation); } void _Request_name(RequestObject *self, Id what, Id provides) { - queue_push2(&self->_queue, what|SOLVER_SOLVABLE_NAME, provides); + queue_push2(&self->_queue, what|SOLVER_SOLVABLE_NAME|SOLVER_WEAK, provides); } PyObject *Request_install_solvable(RequestObject *self, PyObject *args) { diff --git a/python/src/solvable.c b/python/src/solvable.c index 91ad45088..490df0f64 100644 --- a/python/src/solvable.c +++ b/python/src/solvable.c @@ -239,6 +239,42 @@ PyObject *Solvable_get_conflicts(SolvableObject *self) { return _Solvable_get_dependencies(solv, solv->conflicts); } +PyObject *Solvable_add_recommends(SolvableObject *self, PyObject *args) { + Solvable *solv = pool_id2solvable(self->_pool, self->_id); + + RelationObject *rel; + if (!PyArg_ParseTuple(args, "O", &rel)) { + return NULL; + } + + solv->recommends = repo_addid_dep(solv->repo, solv->recommends, rel->_id, 0); + Py_RETURN_NONE; +} + +PyObject *Solvable_get_recommends(SolvableObject *self) { + Solvable *solv = pool_id2solvable(self->_pool, self->_id); + + return _Solvable_get_dependencies(solv, solv->recommends); +} + +PyObject *Solvable_add_suggests(SolvableObject *self, PyObject *args) { + Solvable *solv = pool_id2solvable(self->_pool, self->_id); + + RelationObject *rel; + if (!PyArg_ParseTuple(args, "O", &rel)) { + return NULL; + } + + solv->suggests = repo_addid_dep(solv->repo, solv->suggests, rel->_id, 0); + Py_RETURN_NONE; +} + +PyObject *Solvable_get_suggests(SolvableObject *self) { + Solvable *solv = pool_id2solvable(self->_pool, self->_id); + + return _Solvable_get_dependencies(solv, solv->suggests); +} + PyObject *Solvable_set_uuid(SolvableObject *self, PyObject *args) { Solvable *solv = pool_id2solvable(self->_pool, self->_id); diff --git a/python/src/solvable.h b/python/src/solvable.h index 656c36f19..5d2b28109 100644 --- a/python/src/solvable.h +++ b/python/src/solvable.h @@ -99,6 +99,12 @@ extern PyObject *Solvable_get_obsoletes(SolvableObject *self); extern PyObject *Solvable_add_conflicts(SolvableObject *self, PyObject *args); extern PyObject *Solvable_get_conflicts(SolvableObject *self); +extern PyObject *Solvable_add_recommends(SolvableObject *self, PyObject *args); +extern PyObject *Solvable_get_recommends(SolvableObject *self); + +extern PyObject *Solvable_add_suggests(SolvableObject *self, PyObject *args); +extern PyObject *Solvable_get_suggests(SolvableObject *self); + extern PyTypeObject SolvableType; #endif -- 2.39.5