]> git.ipfire.org Git - pakfire.git/commitdiff
Implement recommends and suggests.
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 Oct 2012 16:48:15 +0000 (16:48 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 Oct 2012 16:48:15 +0000 (16:48 +0000)
17 files changed:
python/pakfire/api.py
python/pakfire/cli.py
python/pakfire/constants.py
python/pakfire/packages/base.py
python/pakfire/packages/file.py
python/pakfire/packages/installed.py
python/pakfire/packages/lexer.py
python/pakfire/packages/make.py
python/pakfire/packages/packager.py
python/pakfire/packages/solv.py
python/pakfire/repository/database.py
python/pakfire/repository/index.py
python/pakfire/satsolver.py
python/src/_pakfiremodule.c
python/src/request.c
python/src/solvable.c
python/src/solvable.h

index 372e4d544067be0d8e9ef57e259796868ef18a3e..6f93332ce042e93534d5a33f9c10f08540be761f 100644 (file)
@@ -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)
index 5b56b450145ff88fdd79613cbdc7d759fa1badfd..9a72d747fea11508e414d422ea01302d5a01e229 100644 (file)
@@ -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)
index 45b1b40c52426959b5c22e0e54b8c9cf85da2045..f10daecff60c91251ed60d65dcf5ed2cd4013ef0 100644 (file)
@@ -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
index 91625362db70cdd3d02e7e521530c67771143569..8e5ba030ebfb824a84862be2c08247e9327b71da 100644 (file)
@@ -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()
index 070c763b74f508770401537e41eba54216194c83..4f465ec691a89617c73f8ea3b4781f3d16ac00bb 100644 (file)
@@ -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"
index 33c241d0cbbf59d2a08846767039a3ee579fb1c8..de4d4f61ff7c13a5b5f8415eabc8e85e9b2c03f2 100644 (file)
@@ -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")
index af6dda0fdbe56f8853fe4c8f4d2b116e33abccf0..52eeb1978faf5c8e1f562356d34bc5f41ef8e287 100644 (file)
@@ -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)
index 263527ab8296854400f696b524ed30c8a8c5e97a..34e9d5fa411f99b0aed256466fae5773863205d5 100644 (file)
@@ -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)
 
index d44a6dc1984f9515553a779cb98500cc96875bb5..6715741320689f761d2872e87eaafb23844fe6f6 100644 (file)
@@ -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.
index 84c127d5a77f69d342bab1174b1fc7bacebb46d7..80a30c2598e5f518e1a4cc77b549fbe508cd22ca 100644 (file)
@@ -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()
index a5e5b858b9f2be4e2dc822b7923a18ccb901a286..6f02422c24bfbcd9fa8cba592e164ac0007d3a6c 100644 (file)
@@ -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,
index 7620b38971d3391cefc6dd680f3cd335117df3ce..452ef5e295a4b4fde804fa3984d4ea819b2b7b00 100644 (file)
@@ -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.
index 48c6d0dee93ed5bccdd78516b0739814bf764be0..f10d6194172f0b239bab7821719b14c458981fe7 100644 (file)
@@ -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):
index 8e80468fdfbf0428ced2c87aed4d2717450ef792..1a8b34fb25035f2f460fd1d6f65ee5ee746f95b2 100644 (file)
@@ -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));
 }
index 7d7c5b200697c41769bec71b0dab4c1d0f3b1040..974e853db5e6e76ea440618752a18b03e20d14ab 100644 (file)
@@ -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) {
index 91ad450887fa521a77cebaeb9d583d5c9339d1ab..490df0f64b0fa83cca27d4940c8f1b73f15b3fa0 100644 (file)
@@ -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);
 
index 656c36f19be90f15fca77d05d6303bf6afef23f1..5d2b28109ef69e042d5f4136cfa1b2b6fee36a2d 100644 (file)
@@ -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