add solver->describe_decision() method
[platform/upstream/libsolv.git] / bindings / solv.i
index 8bd8ee4..7de8fac 100644 (file)
@@ -4,15 +4,6 @@
 # on the generated c code
 #
 
-#
-##if defined(SWIGRUBY)
-#  %rename("to_s") string();
-##endif
-##if defined(SWIGPYTHON)
-#  %rename("__str__") string();
-##endif
-#
-
 %module solv
 
 #ifdef SWIGRUBY
@@ -346,7 +337,7 @@ SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
   if (!desc) desc = SWIG_TypeQuery("SolvFp *");
   if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
     if (val)
-      *val = ((SolvFp *)vptr)->fp;
+      *val = vptr ? ((SolvFp *)vptr)->fp : 0;
     return SWIG_OK;
   }
 #ifdef SWIGPYTHON
@@ -377,7 +368,7 @@ SWIG_AsValDepId(void *obj, int *val) {
     return ecode;
   if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
     if (val)
-      *val = ((Dep *)vptr)->id;
+      *val = vptr ? ((Dep *)vptr)->id : 0;
     return SWIG_OK;
   }
   return SWIG_TypeError;
@@ -389,6 +380,13 @@ SWIG_AsValDepId(void *obj, int *val) {
 
 %include "typemaps.i"
 
+%typemap(in,numinputs=0,noblock=1) XRule **OUTPUT ($*1_ltype temp, int res = SWIG_TMPOBJ) {
+  $1 = &temp;
+}
+%typemap(argout,noblock=1) XRule **OUTPUT {
+  %append_output(SWIG_NewPointerObj((void*)(*$1), SWIGTYPE_p_XRule, SWIG_POINTER_OWN | %newpointer_flags));
+}
+
 %typemaps_asval(%checkcode(POINTER), SWIG_AsValSolvFpPtr, "SWIG_AsValSolvFpPtr", FILE*);
 %typemaps_asval(%checkcode(INT32), SWIG_AsValDepId, "SWIG_AsValDepId", DepId);
 
@@ -419,6 +417,9 @@ typedef int bool;
 #ifdef ENABLE_RPMDB
 #include "repo_rpmdb.h"
 #endif
+#ifdef ENABLE_PUBKEY
+#include "repo_pubkey.h"
+#endif
 #ifdef ENABLE_DEBIAN
 #include "repo_deb.h"
 #endif
@@ -454,6 +455,7 @@ typedef int bool;
 #define SOLVER_SOLUTION_REPLACE_DOWNGRADE       -102
 #define SOLVER_SOLUTION_REPLACE_ARCHCHANGE      -103
 #define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    -104
+#define SOLVER_SOLUTION_REPLACE_NAMECHANGE      -105
 
 typedef struct chksum Chksum;
 typedef void *AppObjectPtr;
@@ -528,7 +530,7 @@ typedef struct {
   Id type;
   Id source;
   Id target;
-  Id dep;
+  Id dep_id;
 } Ruleinfo;
 
 typedef struct {
@@ -595,7 +597,7 @@ typedef struct {
 typedef struct {
   Solver* const solv;
   Id const type;
-  Id const dep;
+  Id const dep_id;
 } Ruleinfo;
 
 typedef struct {
@@ -767,7 +769,7 @@ typedef struct {
   static const Id SOLVER_ERASE = SOLVER_ERASE;
   static const Id SOLVER_UPDATE = SOLVER_UPDATE;
   static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
-  static const Id SOLVER_NOOBSOLETES = SOLVER_NOOBSOLETES;
+  static const Id SOLVER_MULTIVERSION = SOLVER_MULTIVERSION;
   static const Id SOLVER_LOCK = SOLVER_LOCK;
   static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
@@ -777,11 +779,14 @@ typedef struct {
   static const Id SOLVER_WEAK = SOLVER_WEAK;
   static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
   static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
+  static const Id SOLVER_FORCEBEST = SOLVER_FORCEBEST;
+  static const Id SOLVER_TARGETED = SOLVER_TARGETED;
   static const Id SOLVER_SETEV = SOLVER_SETEV;
   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
   static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
   static const Id SOLVER_SETREPO = SOLVER_SETREPO;
+  static const Id SOLVER_SETNAME = SOLVER_SETNAME;
   static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
   static const Id SOLVER_SETMASK = SOLVER_SETMASK;
 
@@ -830,10 +835,13 @@ typedef struct {
   static const Id SELECTION_NAME = SELECTION_NAME;
   static const Id SELECTION_PROVIDES = SELECTION_PROVIDES;
   static const Id SELECTION_FILELIST = SELECTION_FILELIST;
-  static const Id SELECTION_GLOB = SELECTION_GLOB;
-  static const Id SELECTION_NOCASE = SELECTION_NOCASE;
+  static const Id SELECTION_CANON = SELECTION_CANON;
+  static const Id SELECTION_DOTARCH = SELECTION_DOTARCH;
+  static const Id SELECTION_REL = SELECTION_REL;
   static const Id SELECTION_INSTALLED_ONLY = SELECTION_INSTALLED_ONLY;
+  static const Id SELECTION_GLOB = SELECTION_GLOB;
   static const Id SELECTION_FLAT = SELECTION_FLAT;
+  static const Id SELECTION_NOCASE = SELECTION_NOCASE;
   static const Id SELECTION_SOURCE_ONLY = SELECTION_SOURCE_ONLY;
   static const Id SELECTION_WITH_SOURCE = SELECTION_WITH_SOURCE;
 
@@ -851,20 +859,17 @@ typedef struct {
   int flags() {
     return $self->flags;
   }
-  void make(const char *name, int flags) {
-    $self->flags = selection_make($self->pool, &$self->q, name, flags);
-  }
 #ifdef SWIGRUBY
   %rename("isempty?") isempty;
 #endif
   bool isempty() {
     return $self->q.count == 0;
   }
-  void limit(Selection *lsel) {
+  void filter(Selection *lsel) {
     if ($self->pool != lsel->pool)
       queue_empty(&$self->q);
     else
-      selection_limit($self->pool, &$self->q, &lsel->q);
+      selection_filter($self->pool, &$self->q, &lsel->q);
   }
   void add(Selection *lsel) {
     if ($self->pool == lsel->pool)
@@ -999,7 +1004,6 @@ typedef struct {
   }
 #if defined(SWIGRUBY)
   %rename("to_s") __str__;
-  %rename("inspect") __repr__;
 #endif
 #if defined(SWIGPERL)
   %rename("str") __str__;
@@ -1024,6 +1028,16 @@ typedef struct {
 }
 
 %extend Pool {
+  static const int POOL_FLAG_PROMOTEEPOCH = POOL_FLAG_PROMOTEEPOCH;
+  static const int POOL_FLAG_FORBIDSELFCONFLICTS = POOL_FLAG_FORBIDSELFCONFLICTS;
+  static const int POOL_FLAG_OBSOLETEUSESPROVIDES = POOL_FLAG_OBSOLETEUSESPROVIDES;
+  static const int POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES = POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES;
+  static const int POOL_FLAG_OBSOLETEUSESCOLORS = POOL_FLAG_OBSOLETEUSESCOLORS;
+  static const int POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS = POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS;
+  static const int POOL_FLAG_NOINSTALLEDOBSOLETES = POOL_FLAG_NOINSTALLEDOBSOLETES;
+  static const int POOL_FLAG_HAVEDISTEPOCH = POOL_FLAG_HAVEDISTEPOCH;
+  static const int POOL_FLAG_NOOBSOLETESMULTIVERSION = POOL_FLAG_NOOBSOLETESMULTIVERSION;
+
   Pool() {
     Pool *pool = pool_create();
     return pool;
@@ -1136,6 +1150,7 @@ typedef struct {
   Id str2id(const char *str, bool create=1) {
     return pool_str2id($self, str, create);
   }
+  %newobject Dep;
   Dep *Dep(const char *str, bool create=1) {
     Id id = pool_str2id($self, str, create);
     return new_Dep($self, id);
@@ -1172,7 +1187,7 @@ typedef struct {
   Id lookup_id(Id entry, Id keyname) {
     return pool_lookup_id($self, entry, keyname);
   }
-  unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
+  unsigned long long lookup_num(Id entry, Id keyname, unsigned long long notfound = 0) {
     return pool_lookup_num($self, entry, keyname, notfound);
   }
   bool lookup_void(Id entry, Id keyname) {
@@ -1205,6 +1220,7 @@ typedef struct {
     pool_createwhatprovides($self);
   }
 
+  %newobject id2solvable;
   XSolvable *id2solvable(Id id) {
     return new_XSolvable($self, id);
   }
@@ -1225,6 +1241,7 @@ typedef struct {
       return 0;
     return pool_id2repo($self, id);
   }
+
   %newobject repos;
   Pool_repo_iterator * const repos;
   %{
@@ -1238,6 +1255,7 @@ typedef struct {
   }
 
   Repo *installed;
+  const char * const errstr;
   %{
   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
     pool_set_installed(pool, installed);
@@ -1245,6 +1263,9 @@ typedef struct {
   Repo *Pool_installed_get(Pool *pool) {
     return pool->installed;
   }
+  const char *Pool_errstr_get(Pool *pool) {
+    return pool_errstr(pool);
+  }
   %}
 
   Queue matchprovidingids(const char *match, int flags) {
@@ -1268,13 +1289,14 @@ typedef struct {
     return q;
   }
 
+  %newobject Job;
   Job *Job(int how, Id what) {
     return new_Job($self, how, what);
   }
 
   %typemap(out) Queue whatprovides Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
   %newobject whatprovides;
-  Queue whatprovides(Id dep) {
+  Queue whatprovides(DepId dep) {
     Pool *pool = $self;
     Queue q;
     Id p, pp;
@@ -1291,7 +1313,7 @@ typedef struct {
 #ifdef SWIGRUBY
   %rename("isknownarch?") isknownarch;
 #endif
-  bool isknownarch(Id id) {
+  bool isknownarch(DepId id) {
     Pool *pool = $self;
     if (!id || id == ID_EMPTY)
       return 0;
@@ -1311,12 +1333,61 @@ typedef struct {
   Selection *Selection() {
     return new_Selection($self);
   }
+  %newobject Selection_all;
+  Selection *Selection_all(int setflags=0) {
+    Selection *sel = new_Selection($self);
+    queue_push2(&sel->q, SOLVER_SOLVABLE_ALL | setflags, 0);
+    return sel;
+  }
   %newobject select;
   Selection *select(const char *name, int flags) {
     Selection *sel = new_Selection($self);
     sel->flags = selection_make($self, &sel->q, name, flags);
     return sel;
   }
+
+  void setpooljobs_helper(Queue jobs) {
+    queue_free(&$self->pooljobs);
+    queue_init_clone(&$self->pooljobs, &jobs);
+  }
+  %typemap(out) Queue getpooljobs Queue2Array(Job *, 2, new_Job(arg1, id, idp[1]));
+  %newobject getpooljobs;
+  Queue getpooljobs() {
+    Queue q;
+    queue_init_clone(&q, &$self->pooljobs);
+    return q;
+  }
+
+#if defined(SWIGPYTHON)
+  %pythoncode {
+    def setpooljobs(self, jobs):
+      j = []
+      for job in jobs: j += [job.how, job.what]
+      self.setpooljobs_helper(j)
+  }
+#endif
+#if defined(SWIGPERL)
+  %perlcode {
+    sub solv::Solver::setpooljobs {
+      my ($self, $jobs) = @_;
+      my @j = map {($_->{'how'}, $_->{'what'})} @$jobs;
+      return $self->setpooljobs_helper(\@j);
+    }
+  }
+#endif
+#if defined(SWIGRUBY)
+%init %{
+rb_eval_string(
+    "class Solv::Pool\n"
+    "  def setpooljobs(jobs)\n"
+    "    jl = []\n"
+    "    jobs.each do |j| ; jl << j.how << j.what ; end\n"
+    "    setpooljobs_helper(jl)\n"
+    "  end\n"
+    "end\n"
+  );
+%}
+#endif
 }
 
 %extend Repo {
@@ -1357,90 +1428,106 @@ typedef struct {
     return repo_add_solv($self, fp, flags) == 0;
   }
 
+  %newobject add_solvable;
   XSolvable *add_solvable() {
     Id solvid = repo_add_solvable($self);
     return new_XSolvable($self->pool, solvid);
   }
 
 #ifdef ENABLE_RPMDB
-  bool add_rpmdb(Repo *ref, int flags = 0) {
-    return repo_add_rpmdb($self, ref, flags);
+  bool add_rpmdb(int flags = 0) {
+    return repo_add_rpmdb($self, 0, flags) == 0;
   }
-  Id add_rpm(const char *name, int flags = 0) {
-    return repo_add_rpm($self, name, flags);
+  bool add_rpmdb_reffp(FILE *reffp, int flags = 0) {
+    return repo_add_rpmdb_reffp($self, reffp, flags) == 0;
+  }
+  %newobject add_rpm;
+  XSolvable *add_rpm(const char *name, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_rpm($self, name, flags));
+  }
+#endif
+#ifdef ENABLE_PUBKEY
+#ifdef ENABLE_RPMDB
+  bool add_rpmdb_pubkeys(int flags = 0) {
+    return repo_add_rpmdb_pubkeys($self, flags) == 0;
+  }
+#endif
+  %newobject add_pubkey;
+  XSolvable *add_pubkey(const char *key, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_pubkey($self, key, flags));
   }
 #endif
 #ifdef ENABLE_RPMMD
   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
-    return repo_add_rpmmd($self, fp, language, flags);
+    return repo_add_rpmmd($self, fp, language, flags) == 0;
   }
   bool add_repomdxml(FILE *fp, int flags = 0) {
-    return repo_add_repomdxml($self, fp, flags);
+    return repo_add_repomdxml($self, fp, flags) == 0;
   }
   bool add_updateinfoxml(FILE *fp, int flags = 0) {
-    return repo_add_updateinfoxml($self, fp, flags);
+    return repo_add_updateinfoxml($self, fp, flags) == 0;
   }
   bool add_deltainfoxml(FILE *fp, int flags = 0) {
-    return repo_add_deltainfoxml($self, fp, flags);
+    return repo_add_deltainfoxml($self, fp, flags) == 0;
   }
 #endif
 #ifdef ENABLE_DEBIAN
   bool add_debdb(int flags = 0) {
-    return repo_add_debdb($self, flags);
+    return repo_add_debdb($self, flags) == 0;
+  }
+  bool add_debpackages(FILE *fp, int flags = 0) {
+    return repo_add_debpackages($self, fp, flags) == 0;
   }
-  Id add_deb(const char *name, int flags = 0) {
-    return repo_add_deb($self, name, flags);
+  %newobject add_deb;
+  XSolvable *add_deb(const char *name, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_deb($self, name, flags));
   }
 #endif
 #ifdef ENABLE_SUSEREPO
   bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
-    return repo_add_susetags($self, fp, defvendor, language, flags);
+    return repo_add_susetags($self, fp, defvendor, language, flags) == 0;
   }
   bool add_content(FILE *fp, int flags = 0) {
-    return repo_add_content($self, fp, flags);
+    return repo_add_content($self, fp, flags) == 0;
   }
   bool add_products(const char *proddir, int flags = 0) {
-    return repo_add_products($self, proddir, flags);
+    return repo_add_products($self, proddir, flags) == 0;
   }
 #endif
 #ifdef ENABLE_MDKREPO
   bool add_mdk(FILE *fp, int flags = 0) {
-    return repo_add_mdk($self, fp, flags);
+    return repo_add_mdk($self, fp, flags) == 0;
   }
   bool add_mdk_info(FILE *fp, int flags = 0) {
-    return repo_add_mdk($self, fp, flags);
+    return repo_add_mdk_info($self, fp, flags) == 0;
   }
 #endif
 #ifdef ENABLE_ARCHREPO
   bool add_arch_repo(FILE *fp, int flags = 0) {
-    return repo_add_arch_repo($self, fp, flags);
+    return repo_add_arch_repo($self, fp, flags) == 0;
+  }
+  bool add_arch_local(const char *dir, int flags = 0) {
+    return repo_add_arch_local($self, dir, flags) == 0;
   }
-  Id add_arch_pkg(const char *name, int flags = 0) {
-    return repo_add_arch_pkg($self, name, flags);
+  %newobject add_arch_pkg;
+  XSolvable *add_arch_pkg(const char *name, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_arch_pkg($self, name, flags));
   }
 #endif
   void internalize() {
     repo_internalize($self);
   }
-  const char *lookup_str(Id entry, Id keyname) {
-    return repo_lookup_str($self, entry, keyname);
-  }
-  Id lookup_id(Id entry, Id keyname) {
-    return repo_lookup_id($self, entry, keyname);
-  }
-  unsigned long long lookup_num(Id entry, Id keyname, unsigned long long notfound = 0) {
-    return repo_lookup_num($self, entry, keyname, notfound);
-  }
-  void write(FILE *fp) {
-    repo_write($self, fp);
+  bool write(FILE *fp) {
+    return repo_write($self, fp) == 0;
   }
   # HACK, remove if no longer needed!
   bool write_first_repodata(FILE *fp) {
     int oldnrepodata = $self->nrepodata;
+    int res;
     $self->nrepodata = oldnrepodata > 2 ? 2 : oldnrepodata;
-    repo_write($self, fp);
+    res = repo_write($self, fp);
     $self->nrepodata = oldnrepodata;
-    return 1;
+    return res == 0;
   }
 
   %newobject Dataiterator;
@@ -1454,17 +1541,30 @@ typedef struct {
     return repo->repoid;
   }
   %}
+  %newobject solvables;
   Repo_solvable_iterator * const solvables;
   %{
   SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
     return new_Repo_solvable_iterator(repo);
   }
   %}
+  %newobject meta;
+  Datapos * const meta;
+  %{
+  SWIGINTERN Datapos * Repo_meta_get(Repo *repo) {
+    Datapos *pos = solv_calloc(1, sizeof(*pos));
+    pos->solvid = SOLVID_META;
+    pos->repo = repo;
+    return pos;
+  }
+  %}
+
   %newobject solvables_iter;
   Repo_solvable_iterator *solvables_iter() {
     return new_Repo_solvable_iterator($self);
   }
 
+  %newobject add_repodata;
   XRepodata *add_repodata(int flags = 0) {
     Repodata *rd = repo_add_repodata($self, flags);
     return new_XRepodata($self, rd->repodataid);
@@ -1476,7 +1576,7 @@ typedef struct {
       return;
     data = repo_id2repodata($self, $self->nrepodata - 1);
     if (data->state != REPODATA_STUB)
-      repodata_create_stubs(data);
+      (void)repodata_create_stubs(data);
   }
 #ifdef SWIGRUBY
   %rename("iscontiguous?") iscontiguous;
@@ -1488,6 +1588,7 @@ typedef struct {
         return 0;
     return 1;
   }
+  %newobject first_repodata;
   XRepodata *first_repodata() {
     Repodata *data;
     int i;
@@ -1506,6 +1607,14 @@ typedef struct {
     return new_XRepodata($self, 1);
   }
 
+  %newobject Selection;
+  Selection *Selection(int setflags=0) {
+    Selection *sel = new_Selection($self->pool);
+    setflags |= SOLVER_SETREPO;
+    queue_push2(&sel->q, SOLVER_SOLVABLE_REPO | setflags, $self->repoid);
+    return sel;
+  }
+
   bool __eq__(Repo *repo) {
     return $self == repo;
   }
@@ -1546,6 +1655,7 @@ typedef struct {
   static const int SEARCH_NOCASE = SEARCH_NOCASE;
   static const int SEARCH_FILES = SEARCH_FILES;
   static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
+  static const int SEARCH_CHECKSUMS = SEARCH_CHECKSUMS;
 
   Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
     Dataiterator *di = solv_calloc(1, sizeof(*di));
@@ -1586,6 +1696,7 @@ typedef struct {
     }
     ndi = solv_calloc(1, sizeof(*ndi));
     dataiterator_init_clone(ndi, $self);
+    dataiterator_strdup(ndi);
     return ndi;
   }
 #ifdef SWIGRUBY
@@ -1623,6 +1734,24 @@ typedef struct {
     pool->pos = oldpos;
     return r;
   }
+  unsigned long long lookup_num(Id keyname, unsigned long long notfound = 0) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    unsigned long long r;
+    pool->pos = *$self;
+    r = pool_lookup_num(pool, SOLVID_POS, keyname, notfound);
+    pool->pos = oldpos;
+    return r;
+  }
+  bool lookup_void(Id keyname) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    int r;
+    pool->pos = *$self;
+    r = pool_lookup_void(pool, SOLVID_POS, keyname);
+    pool->pos = oldpos;
+    return r;
+  }
   %newobject lookup_checksum;
   Chksum *lookup_checksum(Id keyname) {
     Pool *pool = $self->repo->pool;
@@ -1656,6 +1785,26 @@ typedef struct {
     pool->pos = oldpos;
     return loc;
   }
+  Queue lookup_idarray(Id keyname) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    Queue r;
+    queue_init(&r);
+    pool->pos = *$self;
+    pool_lookup_idarray(pool, SOLVID_POS, keyname, &r);
+    pool->pos = oldpos;
+    return r;
+  }
+  %newobject Dataiterator;
+  Dataiterator *Dataiterator(Id key, const char *match, int flags) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    Dataiterator *di;
+    pool->pos = *$self;
+    di = new_Dataiterator(pool, 0, SOLVID_POS, key, match, flags);
+    pool->pos = oldpos;
+    return di;
+  }
 }
 
 %extend Datamatch {
@@ -1691,7 +1840,9 @@ typedef struct {
   const char *str() {
      return $self->kv.str;
   }
-  int num() {
+  unsigned long long num() {
+     if ($self->key->type == REPOKEY_TYPE_NUM)
+       return SOLV_KV_NUM64(&$self->kv);
      return $self->kv.num;
   }
   int num2() {
@@ -1717,12 +1868,6 @@ typedef struct {
     pool->pos = oldpos;
     return pos;
   }
-  void setpos() {
-    dataiterator_setpos($self);
-  }
-  void setpos_parent() {
-    dataiterator_setpos_parent($self);
-  }
 #if defined(SWIGPERL)
   %rename("str") __str__;
 #endif
@@ -1914,6 +2059,40 @@ typedef struct {
     s->id = id;
     return s;
   }
+  %newobject Rel;
+  Dep *Rel(int flags, DepId evrid, bool create=1) {
+    Id id = pool_rel2id($self->pool, $self->id, evrid, flags, create);
+    if (!id)
+      return 0;
+    return new_Dep($self->pool, id);
+  }
+  %newobject Selection_name;
+  Selection *Selection_name(int setflags=0) {
+    Selection *sel = new_Selection($self->pool);
+    if (ISRELDEP($self->id)) {
+      Reldep *rd = GETRELDEP($self->pool, $self->id);
+      if (rd->flags == REL_EQ) {
+        setflags |= $self->pool->disttype == DISTTYPE_DEB || strchr(pool_id2str($self->pool, rd->evr), '-') != 0 ? SOLVER_SETEVR : SOLVER_SETEV;
+        if (ISRELDEP(rd->name))
+          rd = GETRELDEP($self->pool, rd->name);
+      }
+      if (rd->flags == REL_ARCH)
+        setflags |= SOLVER_SETARCH;
+    }
+    queue_push2(&sel->q, SOLVER_SOLVABLE_NAME | setflags, $self->id);
+    return sel;
+  }
+  %newobject Selection_provides;
+  Selection *Selection_provides(int setflags=0) {
+    Selection *sel = new_Selection($self->pool);
+    if (ISRELDEP($self->id)) {
+      Reldep *rd = GETRELDEP($self->pool, $self->id);
+      if (rd->flags == REL_ARCH)
+        setflags |= SOLVER_SETARCH;
+    }
+    queue_push2(&sel->q, SOLVER_SOLVABLE_PROVIDES | setflags, $self->id);
+    return sel;
+  }
   const char *str() {
     return pool_dep2str($self->pool, $self->id);
   }
@@ -2146,6 +2325,11 @@ typedef struct {
     s->enhances = repo_addid_dep(s->repo, s->enhances, id, 0);
   }
 
+  void unset(Id keyname) {
+    Solvable *s = $self->pool->solvables + $self->id;
+    repo_unset(s->repo, $self->id, keyname);
+  }
+
   void add_deparray(Id keyname, DepId id, Id marker = -1) {
     Solvable *s = $self->pool->solvables + $self->id;
     if (marker == -1 || marker == 1) {
@@ -2159,6 +2343,13 @@ typedef struct {
     solvable_add_deparray(s, keyname, id, marker);
   }
 
+  %newobject Selection;
+  Selection *Selection(int setflags=0) {
+    Selection *sel = new_Selection($self->pool);
+    queue_push2(&sel->q, SOLVER_SOLVABLE | setflags, $self->id);
+    return sel;
+  }
+
   bool __eq__(XSolvable *s) {
     return $self->pool == s->pool && $self->id == s->id;
   }
@@ -2220,8 +2411,8 @@ typedef struct {
   int solution_count() {
     return solver_solution_count($self->solv, $self->id);
   }
-  %newobject solutions;
   %typemap(out) Queue solutions Queue2Array(Solution *, 1, new_Solution(arg1, id));
+  %newobject solutions;
   Queue solutions() {
     Queue q;
     int i, cnt;
@@ -2246,8 +2437,8 @@ typedef struct {
     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
   }
 
-  %newobject elements;
   %typemap(out) Queue elements Queue2Array(Solutionelement *, 4, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2], idp[3]));
+  %newobject elements;
   Queue elements(bool expandreplaces=0) {
     Queue q;
     int i, cnt;
@@ -2279,6 +2470,10 @@ typedef struct {
               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
               queue_push2(&q, p, rp);
             }
+            if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0) {
+              queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_NAMECHANGE);
+              queue_push2(&q, p, rp);
+            }
             continue;
           }
         }
@@ -2305,6 +2500,7 @@ typedef struct {
   const char *str() {
     Id p = $self->type;
     Id rp = $self->p;
+    int illegal = 0;
     if (p == SOLVER_SOLUTION_ERASE)
       {
         p = rp;
@@ -2316,15 +2512,19 @@ typedef struct {
         rp = $self->rp;
       }
     else if (p == SOLVER_SOLUTION_REPLACE_DOWNGRADE)
-      return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_DOWNGRADE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
+      illegal = POLICY_ILLEGAL_DOWNGRADE;
     else if (p == SOLVER_SOLUTION_REPLACE_ARCHCHANGE)
-      return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_ARCHCHANGE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
+      illegal = POLICY_ILLEGAL_ARCHCHANGE;
     else if (p == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
-      return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_VENDORCHANGE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
+      illegal = POLICY_ILLEGAL_VENDORCHANGE;
+    else if (p == SOLVER_SOLUTION_REPLACE_NAMECHANGE)
+      illegal = POLICY_ILLEGAL_NAMECHANGE;
+    if (illegal)
+      return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, illegal, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
     return solver_solutionelement2str($self->solv, p, rp);
   }
-  %newobject replaceelements;
   %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, arg1->id, id, arg1->p, arg1->rp));
+  %newobject replaceelements;
   Queue replaceelements() {
     Queue q;
     int illegal;
@@ -2340,6 +2540,8 @@ typedef struct {
       queue_push(&q, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
     if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
       queue_push(&q, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
+    if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0)
+      queue_push(&q, SOLVER_SOLUTION_REPLACE_NAMECHANGE);
     if (!q.count)
       queue_push(&q, $self->type);
     return q;
@@ -2362,7 +2564,7 @@ typedef struct {
       return new_XSolvable(e->solv->pool, e->rp);
     }
     SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) {
-      if (e->type != SOLVER_SOLUTION_JOB)
+      if (e->type != SOLVER_SOLUTION_JOB && e->type != SOLVER_SOLUTION_POOLJOB)
         return -1;
       return (e->p - 1) / 2;
     }
@@ -2370,11 +2572,11 @@ typedef struct {
   %newobject Job;
   Job *Job() {
     Id extraflags = solver_solutionelement_extrajobflags($self->solv, $self->problemid, $self->solutionid);
-    if ($self->type == SOLVER_SOLUTION_JOB)
+    if ($self->type == SOLVER_SOLUTION_JOB || SOLVER_SOLUTION_POOLJOB)
       return new_Job($self->solv->pool, SOLVER_NOOP, 0);
-    if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE)
+    if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE || $self->type == SOLVER_SOLUTION_BEST)
       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|extraflags, $self->p);
-    if ($self->type == SOLVER_SOLUTION_REPLACE || $self->type == SOLVER_SOLUTION_REPLACE_DOWNGRADE || $self->type == SOLVER_SOLUTION_REPLACE_ARCHCHANGE || $self->type == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
+    if ($self->type == SOLVER_SOLUTION_REPLACE || $self->type == SOLVER_SOLUTION_REPLACE_DOWNGRADE || $self->type == SOLVER_SOLUTION_REPLACE_ARCHCHANGE || $self->type == SOLVER_SOLUTION_REPLACE_VENDORCHANGE || $self->type == SOLVER_SOLUTION_REPLACE_NAMECHANGE)
       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|extraflags, $self->rp);
     if ($self->type == SOLVER_SOLUTION_ERASE)
       return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE|extraflags, $self->p);
@@ -2398,33 +2600,55 @@ typedef struct {
   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
+  static const int SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM = SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
+  static const int SOLVER_RULE_JOB_UNKNOWN_PACKAGE = SOLVER_RULE_JOB_UNKNOWN_PACKAGE;
+  static const int SOLVER_RULE_JOB_UNSUPPORTED = SOLVER_RULE_JOB_UNSUPPORTED;
   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
   static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT;
 
   static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB;
+  static const int SOLVER_SOLUTION_POOLJOB = SOLVER_SOLUTION_POOLJOB;
   static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH;
   static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE;
+  static const int SOLVER_SOLUTION_BEST = SOLVER_SOLUTION_BEST;
   static const int SOLVER_SOLUTION_ERASE = SOLVER_SOLUTION_ERASE;
   static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
   static const int SOLVER_SOLUTION_REPLACE_DOWNGRADE = SOLVER_SOLUTION_REPLACE_DOWNGRADE;
   static const int SOLVER_SOLUTION_REPLACE_ARCHCHANGE = SOLVER_SOLUTION_REPLACE_ARCHCHANGE;
   static const int SOLVER_SOLUTION_REPLACE_VENDORCHANGE = SOLVER_SOLUTION_REPLACE_VENDORCHANGE;
+  static const int SOLVER_SOLUTION_REPLACE_NAMECHANGE = SOLVER_SOLUTION_REPLACE_NAMECHANGE;
 
   static const int POLICY_ILLEGAL_DOWNGRADE = POLICY_ILLEGAL_DOWNGRADE;
   static const int POLICY_ILLEGAL_ARCHCHANGE = POLICY_ILLEGAL_ARCHCHANGE;
   static const int POLICY_ILLEGAL_VENDORCHANGE = POLICY_ILLEGAL_VENDORCHANGE;
+  static const int POLICY_ILLEGAL_NAMECHANGE = POLICY_ILLEGAL_NAMECHANGE;
 
   static const int SOLVER_FLAG_ALLOW_DOWNGRADE = SOLVER_FLAG_ALLOW_DOWNGRADE;
   static const int SOLVER_FLAG_ALLOW_ARCHCHANGE = SOLVER_FLAG_ALLOW_ARCHCHANGE;
   static const int SOLVER_FLAG_ALLOW_VENDORCHANGE = SOLVER_FLAG_ALLOW_VENDORCHANGE;
+  static const int SOLVER_FLAG_ALLOW_NAMECHANGE = SOLVER_FLAG_ALLOW_NAMECHANGE;
   static const int SOLVER_FLAG_ALLOW_UNINSTALL = SOLVER_FLAG_ALLOW_UNINSTALL;
   static const int SOLVER_FLAG_NO_UPDATEPROVIDE = SOLVER_FLAG_NO_UPDATEPROVIDE;
   static const int SOLVER_FLAG_SPLITPROVIDES = SOLVER_FLAG_SPLITPROVIDES;
   static const int SOLVER_FLAG_IGNORE_RECOMMENDED = SOLVER_FLAG_IGNORE_RECOMMENDED;
   static const int SOLVER_FLAG_ADD_ALREADY_RECOMMENDED = SOLVER_FLAG_ADD_ALREADY_RECOMMENDED;
   static const int SOLVER_FLAG_NO_INFARCHCHECK = SOLVER_FLAG_NO_INFARCHCHECK;
+  static const int SOLVER_FLAG_BEST_OBEY_POLICY = SOLVER_FLAG_BEST_OBEY_POLICY;
+  static const int SOLVER_FLAG_NO_AUTOTARGET = SOLVER_FLAG_NO_AUTOTARGET;
+
+  static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
+  static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
+  static const int SOLVER_REASON_KEEP_INSTALLED = SOLVER_REASON_KEEP_INSTALLED;
+  static const int SOLVER_REASON_RESOLVE_JOB = SOLVER_REASON_RESOLVE_JOB;
+  static const int SOLVER_REASON_UPDATE_INSTALLED = SOLVER_REASON_UPDATE_INSTALLED;
+  static const int SOLVER_REASON_CLEANDEPS_ERASE = SOLVER_REASON_CLEANDEPS_ERASE;
+  static const int SOLVER_REASON_RESOLVE = SOLVER_REASON_RESOLVE;
+  static const int SOLVER_REASON_WEAKDEP = SOLVER_REASON_WEAKDEP;
+  static const int SOLVER_REASON_RESOLVE_ORPHAN = SOLVER_REASON_RESOLVE_ORPHAN;
+  static const int SOLVER_REASON_RECOMMENDED = SOLVER_REASON_RECOMMENDED;
+  static const int SOLVER_REASON_SUPPLEMENTED = SOLVER_REASON_SUPPLEMENTED;
 
   ~Solver() {
     solver_free($self);
@@ -2482,6 +2706,13 @@ rb_eval_string(
   Transaction *transaction() {
     return solver_create_transaction($self);
   }
+
+  int describe_decision(XSolvable *s, XRule **OUTPUT) {
+    int ruleid;
+    int reason = solver_describe_decision($self, s->id, &ruleid);
+    *OUTPUT = new_XRule($self, ruleid);
+    return reason;
+  }
 }
 
 %extend Transaction {
@@ -2506,6 +2737,7 @@ rb_eval_string(
   static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES;
   static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL;
   static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL;
+  static const int SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE = SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
   static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES;
   static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES;
   static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY;
@@ -2528,8 +2760,8 @@ rb_eval_string(
     return new_XSolvable($self->pool, op);
   }
 
-  %newobject allothersolvables;
   %typemap(out) Queue allothersolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject allothersolvables;
   Queue allothersolvables(XSolvable *s) {
     Queue q;
     queue_init(&q);
@@ -2546,6 +2778,7 @@ rb_eval_string(
     return q;
   }
 
+  # deprecated, use newsolvables instead
   %typemap(out) Queue newpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
   %newobject newpackages;
   Queue newpackages() {
@@ -2557,6 +2790,7 @@ rb_eval_string(
     return q;
   }
 
+  # deprecated, use keptsolvables instead
   %typemap(out) Queue keptpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
   %newobject keptpackages;
   Queue keptpackages() {
@@ -2569,8 +2803,31 @@ rb_eval_string(
     return q;
   }
 
+  %typemap(out) Queue newsolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject newsolvables;
+  Queue newsolvables() {
+    Queue q;
+    int cut;
+    queue_init(&q);
+    cut = transaction_installedresult(self, &q);
+    queue_truncate(&q, cut);
+    return q;
+  }
+
+  %typemap(out) Queue keptsolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject keptsolvables;
+  Queue keptsolvables() {
+    Queue q;
+    int cut;
+    queue_init(&q);
+    cut = transaction_installedresult(self, &q);
+    if (cut)
+      queue_deleten(&q, 0, cut);
+    return q;
+  }
+
   %typemap(out) Queue steps Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
-  %newobject steps ;
+  %newobject steps;
   Queue steps() {
     Queue q;
     queue_init_clone(&q, &$self->steps);
@@ -2583,7 +2840,7 @@ rb_eval_string(
   int calc_installsizechange() {
     return transaction_calc_installsizechange($self);
   }
-  void order(int flags) {
+  void order(int flags=0) {
     transaction_order($self, flags);
   }
 }
@@ -2599,22 +2856,24 @@ rb_eval_string(
     cl->toid = toid;
     return cl;
   }
-  %newobject solvables;
   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->transaction->pool, id));
+  %newobject solvables;
   Queue solvables() {
     Queue q;
     queue_init(&q);
     transaction_classify_pkgs($self->transaction, $self->mode, $self->type, $self->fromid, $self->toid, &q);
     return q;
   }
-  %newobject fromdep;
-  Dep *fromdep() {
-    return new_Dep($self->transaction->pool, $self->fromid);
-  }
-  %newobject todep;
-  Dep *todep() {
-    return new_Dep($self->transaction->pool, $self->toid);
-  }
+  const char * const fromstr;
+  const char * const tostr;
+  %{
+    SWIGINTERN const char *TransactionClass_fromstr_get(TransactionClass *cl) {
+      return pool_id2str(cl->transaction->pool, cl->fromid);
+    }
+    SWIGINTERN const char *TransactionClass_tostr_get(TransactionClass *cl) {
+      return pool_id2str(cl->transaction->pool, cl->toid);
+    }
+  %}
 }
 
 %extend XRule {
@@ -2626,9 +2885,16 @@ rb_eval_string(
     xr->id = id;
     return xr;
   }
+  int const type;
+  %{
+    SWIGINTERN int XRule_type_get(XRule *xr) {
+      return solver_ruleclass(xr->solv, xr->id);
+    }
+  %}
+  %newobject info;
   Ruleinfo *info() {
     Id type, source, target, dep;
-    type =  solver_ruleinfo($self->solv, $self->id, &source, &target, &dep);
+    type = solver_ruleinfo($self->solv, $self->id, &source, &target, &dep);
     return new_Ruleinfo($self, type, source, target, dep);
   }
   %typemap(out) Queue allinfos Queue2Array(Ruleinfo *, 4, new_Ruleinfo(arg1, id, idp[1], idp[2], idp[3]));
@@ -2655,18 +2921,22 @@ rb_eval_string(
 }
 
 %extend Ruleinfo {
-  Ruleinfo(XRule *r, Id type, Id source, Id target, Id dep) {
+  Ruleinfo(XRule *r, Id type, Id source, Id target, Id dep_id) {
     Ruleinfo *ri = solv_calloc(1, sizeof(*ri));
     ri->solv = r->solv;
     ri->rid = r->id;
     ri->type = type;
     ri->source = source;
     ri->target = target;
-    ri->dep = dep;
+    ri->dep_id = dep_id;
     return ri;
   }
+  %newobject solvable;
   XSolvable * const solvable;
+  %newobject othersolvable;
   XSolvable * const othersolvable;
+  %newobject dep;
+  Dep * const dep;
   %{
     SWIGINTERN XSolvable *Ruleinfo_solvable_get(Ruleinfo *ri) {
       return new_XSolvable(ri->solv->pool, ri->source);
@@ -2674,9 +2944,12 @@ rb_eval_string(
     SWIGINTERN XSolvable *Ruleinfo_othersolvable_get(Ruleinfo *ri) {
       return new_XSolvable(ri->solv->pool, ri->target);
     }
+    SWIGINTERN Dep *Ruleinfo_dep_get(Ruleinfo *ri) {
+      return new_Dep(ri->solv->pool, ri->dep_id);
+    }
   %}
   const char *problemstr() {
-    return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep);
+    return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep_id);
   }
 }
 
@@ -2729,10 +3002,12 @@ rb_eval_string(
     repodata_internalize(repo_id2repodata($self->repo, $self->id));
   }
   void create_stubs() {
-    repodata_create_stubs(repo_id2repodata($self->repo, $self->id));
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
+    data = repodata_create_stubs(data);
+    $self->id = data->repodataid;
   }
-  void write(FILE *fp) {
-    repodata_write(repo_id2repodata($self->repo, $self->id), fp);
+  bool write(FILE *fp) {
+    return repodata_write(repo_id2repodata($self->repo, $self->id), fp) == 0;
   }
   bool add_solv(FILE *fp, int flags = 0) {
     Repodata *data = repo_id2repodata($self->repo, $self->id);