add solver->describe_decision() method
[platform/upstream/libsolv.git] / bindings / solv.i
index 929cf7f..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
 #
 %typemap(out) Queue {
   int i;
-  if (argvi + $1.count + 1>= items) {
-    EXTEND(sp, items - (argvi + $1.count + 1) + 1);
+  if (argvi + $1.count + 1 >= items) {
+    EXTEND(sp, (argvi + $1.count + 1) - items + 1);
   }
   for (i = 0; i < $1.count; i++)
     ST(argvi++) = SvREFCNT_inc(SWIG_From_int($1.elements[i]));
   int cnt = $1.count / step;
   Id *idp = $1.elements;
   if (argvi + cnt + 1 >= items) {
-    EXTEND(sp, items - (argvi + cnt + 1) + 1);
+    EXTEND(sp, (argvi + cnt + 1) - items + 1);
   }
   for (i = 0; i < cnt; i++, idp += step)
     {
   int size, i;
   VALUE *o;
   queue_init(&$1);
-  size = RARRAY($input)->len;
+  size = RARRAY_LEN($input);
   i = 0;
-  o = RARRAY($input)->ptr;
+  o = RARRAY_PTR($input);
   for (i = 0; i < size; i++, o++) {
     int v;
     int e = SWIG_AsVal_int(*o, &v);
@@ -295,11 +286,10 @@ SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int f
 #endif
 
 
-
 #if defined(SWIGPYTHON)
 typedef PyObject *AppObjectPtr;
 %typemap(out) AppObjectPtr {
-  $result = $1;
+  $result = $1 ? $1 : Py_None;
   Py_INCREF($result);
 }
 #endif
@@ -325,17 +315,95 @@ typedef VALUE AppObjectPtr;
 
 
 %include "cdata.i"
-#ifndef SWIGPERL
+#ifdef SWIGPYTHON
 %include "file.i"
+#else
+%fragment("SWIG_AsValFilePtr","header") {}
+#endif
+
+
+%fragment("SWIG_AsValSolvFpPtr","header", fragment="SWIG_AsValFilePtr") {
+
+SWIGINTERN int
+#ifdef SWIGRUBY
+SWIG_AsValSolvFpPtr(VALUE obj, FILE **val) {
+#else
+SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
+#endif
+  static swig_type_info* desc = 0;
+  void *vptr = 0;
+  int ecode;
+
+  if (!desc) desc = SWIG_TypeQuery("SolvFp *");
+  if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
+    if (val)
+      *val = vptr ? ((SolvFp *)vptr)->fp : 0;
+    return SWIG_OK;
+  }
+#ifdef SWIGPYTHON
+  ecode = SWIG_AsValFilePtr(obj, val);
+  if (ecode == SWIG_OK)
+    return ecode;
+#endif
+  return SWIG_TypeError;
+}
+
+}
+
+
+%fragment("SWIG_AsValDepId","header") {
+
+SWIGINTERN int
+#ifdef SWIGRUBY
+SWIG_AsValDepId(VALUE obj, int *val) {
+#else
+SWIG_AsValDepId(void *obj, int *val) {
 #endif
+  static swig_type_info* desc = 0;
+  void *vptr = 0; 
+  int ecode;
+  if (!desc) desc = SWIG_TypeQuery("Dep *");
+  ecode = SWIG_AsVal_int(obj, val);
+  if (SWIG_IsOK(ecode))
+    return ecode;
+  if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
+    if (val)
+      *val = vptr ? ((Dep *)vptr)->id : 0;
+    return SWIG_OK;
+  }
+  return SWIG_TypeError;
+}
+
+}
+
+
+
 %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);
+
+
 %{
+#include <stdbool.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
 #include <sys/types.h>
 #include <unistd.h>
 
+/* argh, swig undefs bool for perl */
+#ifndef bool
+typedef int bool;
+#endif
+
 #include "pool.h"
 #include "poolarch.h"
 #include "solver.h"
@@ -343,33 +411,55 @@ typedef VALUE AppObjectPtr;
 #include "solverdebug.h"
 #include "repo_solv.h"
 #include "chksum.h"
+#include "selection.h"
 
-#ifndef DEBIAN
+#include "repo_write.h"
+#ifdef ENABLE_RPMDB
 #include "repo_rpmdb.h"
 #endif
+#ifdef ENABLE_PUBKEY
+#include "repo_pubkey.h"
+#endif
+#ifdef ENABLE_DEBIAN
 #include "repo_deb.h"
+#endif
+#ifdef ENABLE_RPMMD
 #include "repo_rpmmd.h"
-#include "repo_write.h"
-#include "repo_products.h"
-#include "repo_susetags.h"
 #include "repo_updateinfoxml.h"
 #include "repo_deltainfoxml.h"
 #include "repo_repomdxml.h"
+#endif
+#ifdef ENABLE_SUSEREPO
+#include "repo_products.h"
+#include "repo_susetags.h"
 #include "repo_content.h"
+#endif
+#ifdef ENABLE_MDKREPO
+#include "repo_mdk.h"
+#endif
+#ifdef ENABLE_ARCHREPO
+#include "repo_arch.h"
+#endif
 #include "solv_xfopen.h"
 
-#define true 1
-#define false 1
+/* for old ruby versions */
+#ifndef RARRAY_PTR
+#define RARRAY_PTR(ary) (RARRAY(ary)->ptr)
+#endif
+#ifndef RARRAY_LEN
+#define RARRAY_LEN(ary) (RARRAY(ary)->len)
+#endif
 
 #define SOLVER_SOLUTION_ERASE                   -100
 #define SOLVER_SOLUTION_REPLACE                 -101
 #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 int bool;
 typedef void *AppObjectPtr;
+typedef Id DepId;
 
 typedef struct {
   Pool *pool;
@@ -440,7 +530,7 @@ typedef struct {
   Id type;
   Id source;
   Id target;
-  Id dep;
+  Id dep_id;
 } Ruleinfo;
 
 typedef struct {
@@ -452,6 +542,16 @@ typedef struct {
   Id toid;
 } TransactionClass;
 
+typedef struct {
+  Pool *pool;
+  Queue q;
+  int flags;
+} Selection;
+
+typedef struct {
+  FILE *fp;
+} SolvFp;
+
 typedef Dataiterator Datamatch;
 
 %}
@@ -478,9 +578,17 @@ typedef int Id;
 
 typedef struct {
   Pool* const pool;
+} Selection;
+
+typedef struct {
+  Pool* const pool;
   Id const id;
 } Dep;
 
+# put before pool/repo so we can access the constructor
+%nodefaultdtor Dataiterator;
+typedef struct {} Dataiterator;
+
 typedef struct {
   Pool* const pool;
   Id const id;
@@ -489,7 +597,7 @@ typedef struct {
 typedef struct {
   Solver* const solv;
   Id const type;
-  Id const dep;
+  Id const dep_id;
 } Ruleinfo;
 
 typedef struct {
@@ -502,9 +610,6 @@ typedef struct {
   Id const id;
 } XRepodata;
 
-# put before pool/repo so we can access the constructor
-%nodefaultdtor Dataiterator;
-typedef struct {} Dataiterator;
 typedef struct {} Pool_solvable_iterator;
 typedef struct {} Pool_repo_iterator;
 typedef struct {} Repo_solvable_iterator;
@@ -536,7 +641,7 @@ typedef struct {
 
 %nodefaultctor Repo;
 %nodefaultdtor Repo;
-typedef struct _Repo {
+typedef struct {
   Pool * const pool;
   const char * const name;
   int priority;
@@ -551,31 +656,43 @@ typedef struct {
   Pool * const pool;
 } Solver;
 
-typedef struct chksum {
+typedef struct {
 } Chksum;
 
-%rename(xfopen) solv_xfopen;
-%rename(xfopen_fd) solv_xfopen_fd;
-%rename(xfopen_dup) solv_xfopen_dup;
-%rename(xfclose) solv_xfclose;
-%rename(xfileno) solv_xfileno;
+%rename(xfopen) solvfp_xfopen;
+%rename(xfopen_fd) solvfp_xfopen_fd;
+
+%nodefaultctor SolvFp;
+typedef struct {
+} SolvFp;
+
+%newobject solvfp_xfopen;
+%newobject solvfp_xfopen_fd;
 
-FILE *solv_xfopen(const char *fn, const char *mode = 0);
-FILE *solv_xfopen_fd(const char *fn, int fd, const char *mode = 0);
-FILE *solv_xfopen_dup(const char *fn, int fd, const char *mode = 0);
-int solv_xfclose(FILE *fp);
-int solv_xfileno(FILE *fp);
+SolvFp *solvfp_xfopen(const char *fn, const char *mode = 0);
+SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
 
 %{
-  SWIGINTERN int solv_xfclose(FILE *fp) {
-    return fclose(fp);
-  }
-  SWIGINTERN int solv_xfileno(FILE *fp) {
-    return fileno(fp);
-  }
-  SWIGINTERN FILE *solv_xfopen_dup(const char *fn, int fd, const char *mode) {
+  SWIGINTERN SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode) {
+    SolvFp *sfp;
+    FILE *fp;
     fd = dup(fd);
-    return fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
+    fp = fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
+    if (!fp)
+      return 0;
+    sfp = solv_calloc(1, sizeof(SolvFp));
+    sfp->fp = fp;
+    return sfp;
+  }
+  SWIGINTERN SolvFp *solvfp_xfopen(const char *fn, const char *mode) {
+    SolvFp *sfp;
+    FILE *fp;
+    fp = solv_xfopen(fn, mode);
+    if (!fp)
+      return 0;
+    sfp = solv_calloc(1, sizeof(SolvFp));
+    sfp->fp = fp;
+    return sfp;
   }
 %}
 
@@ -612,6 +729,32 @@ typedef struct {
   int const count;
 } TransactionClass;
 
+%extend SolvFp {
+  ~SolvFp() {
+    if ($self->fp)
+      fclose($self->fp);
+    free($self);
+  }
+  int fileno() {
+    return $self->fp ? fileno($self->fp) : -1;
+  }
+  int dup() {
+    return $self->fp ? dup(fileno($self->fp)) : -1;
+  }
+  bool flush() {
+    if (!$self->fp)
+      return 1;
+    return fflush($self->fp) == 0;
+  }
+  bool close() {
+    bool ret;
+    if (!$self->fp)
+      return 1;
+    ret = fclose($self->fp) == 0;
+    $self->fp = 0;
+    return ret;
+  }
+}
 
 %extend Job {
   static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
@@ -626,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;
@@ -636,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;
 
@@ -655,15 +801,17 @@ typedef struct {
   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
   %newobject solvables;
   Queue solvables() {
-    Pool *pool = $self->pool;
-    Id p, pp, how;
     Queue q;
     queue_init(&q);
-    how = $self->how & SOLVER_SELECTMASK;
-    FOR_JOB_SELECT(p, pp, how, $self->what)
-      queue_push(&q, p);
+    pool_job2solvables($self->pool, &q, $self->how, $self->what);
     return q;
   }
+#ifdef SWIGRUBY
+  %rename("isemptyupdate?") isemptyupdate;
+#endif
+  bool isemptyupdate() {
+    return pool_isemptyupdatejob($self->pool, $self->how, $self->what);
+  }
 
   bool __eq__(Job *j) {
     return $self->pool == j->pool && $self->how == j->how && $self->what == j->what;
@@ -683,6 +831,88 @@ typedef struct {
   }
 }
 
+%extend Selection {
+  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_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;
+
+  Selection(Pool *pool) {
+    Selection *s;
+    s = solv_calloc(1, sizeof(*s));
+    s->pool = pool;
+    return s;
+  }
+
+  ~Selection() {
+    queue_free(&$self->q);
+    solv_free($self);
+  }
+  int flags() {
+    return $self->flags;
+  }
+#ifdef SWIGRUBY
+  %rename("isempty?") isempty;
+#endif
+  bool isempty() {
+    return $self->q.count == 0;
+  }
+  void filter(Selection *lsel) {
+    if ($self->pool != lsel->pool)
+      queue_empty(&$self->q);
+    else
+      selection_filter($self->pool, &$self->q, &lsel->q);
+  }
+  void add(Selection *lsel) {
+    if ($self->pool == lsel->pool)
+      {
+        selection_add($self->pool, &$self->q, &lsel->q);
+        $self->flags |= lsel->flags;
+      }
+  }
+  void add_raw(Id how, Id what) {
+    queue_push2(&$self->q, how, what);
+  }
+  %typemap(out) Queue jobs Queue2Array(Job *, 2, new_Job(arg1->pool, id, idp[1]));
+  %newobject jobs;
+  Queue jobs(int flags) {
+    Queue q;
+    int i;
+    queue_init_clone(&q, &$self->q);
+    for (i = 0; i < q.count; i += 2)
+      q.elements[i] |= flags;
+    return q;
+  }
+
+  %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject solvables;
+  Queue solvables() {
+    Queue q;
+    queue_init(&q);
+    selection_solvables($self->pool, &$self->q, &q);
+    return q;
+  }
+
+#if defined(SWIGPERL)
+  %rename("str") __str__;
+#endif
+  const char *__str__() {
+    return pool_selection2str($self->pool, &$self->q, 0);
+  }
+  const char *__repr__() {
+    const char *str = pool_selection2str($self->pool, &$self->q, ~0);
+    return pool_tmpjoin($self->pool, "<Selection ", str, ">");
+  }
+}
+
 %extend Chksum {
   Chksum(Id type) {
     return (Chksum *)solv_chksum_create(type);
@@ -731,6 +961,15 @@ typedef struct {
     solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
     solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
   }
+  void add_fstat(int fd) {
+    struct stat stb;
+    if (fstat(fd, &stb))
+      memset(&stb, 0, sizeof(stb));
+    solv_chksum_add($self, &stb.st_dev, sizeof(stb.st_dev));
+    solv_chksum_add($self, &stb.st_ino, sizeof(stb.st_ino));
+    solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
+    solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
+  }
   SWIGCDATA raw() {
     int l;
     const unsigned char *b;
@@ -765,7 +1004,6 @@ typedef struct {
   }
 #if defined(SWIGRUBY)
   %rename("to_s") __str__;
-  %rename("inspect") __repr__;
 #endif
 #if defined(SWIGPERL)
   %rename("str") __str__;
@@ -790,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;
@@ -799,10 +1047,22 @@ typedef struct {
   void set_debuglevel(int level) {
     pool_setdebuglevel($self, level);
   }
+  int set_flag(int flag, int value) {
+    return pool_set_flag($self, flag, value);
+  }
+  int get_flag(int flag) {
+    return pool_get_flag($self, flag);
+  }
+  void set_rootdir(const char *rootdir) {
+    pool_set_rootdir($self, rootdir);
+  }
+  const char *get_rootdir(int flag) {
+    return pool_get_rootdir($self);
+  }
 #if defined(SWIGPYTHON)
   %{
   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
-    XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
+    XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
     PyObject *args = Py_BuildValue("(O)", SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0));
     PyObject *result = PyEval_CallObject((PyObject *)d, args);
     int ecode = 0;
@@ -817,7 +1077,8 @@ typedef struct {
   %}
   void set_loadcallback(PyObject *callable) {
     if ($self->loadcallback == loadcallback) {
-      Py_DECREF($self->loadcallbackdata);
+      PyObject *obj = $self->loadcallbackdata;
+      Py_DECREF(obj);
     }
     if (callable) {
       Py_INCREF(callable);
@@ -831,7 +1092,7 @@ typedef struct {
     int count;
     int ret = 0;
     dSP;
-    XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
+    XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
 
     ENTER;
     SAVETMPS;
@@ -860,7 +1121,7 @@ typedef struct {
 #if defined(SWIGRUBY)
 %{
   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
-    XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
+    XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
     VALUE callable = (VALUE)d;
     VALUE rd = SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0);
     VALUE res = rb_funcall(callable, rb_intern("call"), 1, rd);
@@ -889,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);
@@ -905,7 +1167,15 @@ typedef struct {
   Id id2langid(Id id, const char *lang, bool create=1) {
     return pool_id2langid($self, id, lang, create);
   }
-  void setarch(const char *arch) {
+  void setarch(const char *arch = 0) {
+    struct utsname un;
+    if (!arch) {
+      if (uname(&un)) {
+        perror("uname");
+        return;
+      }
+      arch = un.machine;
+    }
     pool_setarch($self, arch);
   }
   Repo *add_repo(const char *name) {
@@ -917,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) {
@@ -940,21 +1210,17 @@ typedef struct {
   void addfileprovides() {
     pool_addfileprovides($self);
   }
-  Queue addfileprovides_ids() {
+  Queue addfileprovides_queue() {
     Queue r;
-    Id *addedfileprovides = 0;
     queue_init(&r);
-    pool_addfileprovides_ids($self, $self->installed, &addedfileprovides);
-    if (addedfileprovides) {
-      for (; *addedfileprovides; addedfileprovides++)
-        queue_push(&r, *addedfileprovides);
-    }
+    pool_addfileprovides_queue($self, &r, 0);
     return r;
   }
   void createwhatprovides() {
     pool_createwhatprovides($self);
   }
 
+  %newobject id2solvable;
   XSolvable *id2solvable(Id id) {
     return new_XSolvable($self, id);
   }
@@ -975,6 +1241,7 @@ typedef struct {
       return 0;
     return pool_id2repo($self, id);
   }
+
   %newobject repos;
   Pool_repo_iterator * const repos;
   %{
@@ -988,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);
@@ -995,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) {
@@ -1018,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;
@@ -1041,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;
@@ -1056,6 +1328,66 @@ typedef struct {
   Solver *Solver() {
     return solver_create($self);
   }
+
+  %newobject Selection;
+  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 {
@@ -1064,8 +1396,12 @@ typedef struct {
   static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
   static const int REPO_USE_LOADING = REPO_USE_LOADING;
   static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
+  static const int REPO_USE_ROOTDIR = REPO_USE_ROOTDIR;
+  static const int REPO_NO_LOCATION = REPO_NO_LOCATION;
   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
+#ifdef ENABLE_SUSEREPO
   static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES;     /* repo_susetags */
+#endif
 
   void free(bool reuseids = 0) {
     repo_free($self, reuseids);
@@ -1084,85 +1420,114 @@ typedef struct {
     int r;
     if (!fp)
       return 0;
-    r = repo_add_solv_flags($self, fp, flags);
+    r = repo_add_solv($self, fp, flags);
     fclose(fp);
     return r == 0;
   }
   bool add_solv(FILE *fp, int flags = 0) {
-    return repo_add_solv_flags($self, fp, flags) == 0;
+    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);
   }
 
-  bool add_products(const char *proddir, int flags = 0) {
-    repo_add_products($self, proddir, 0, flags);
-    return 1;
+#ifdef ENABLE_RPMDB
+  bool add_rpmdb(int flags = 0) {
+    return repo_add_rpmdb($self, 0, flags) == 0;
+  }
+  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) {
-    repo_add_rpmmd($self, fp, language, flags);
-    return 1;
+    return repo_add_rpmmd($self, fp, language, flags) == 0;
   }
-#ifndef DEBIAN
-  bool add_rpmdb(Repo *ref, int flags = 0) {
-    repo_add_rpmdb($self, ref, 0, flags);
-    return 1;
+  bool add_repomdxml(FILE *fp, int flags = 0) {
+    return repo_add_repomdxml($self, fp, flags) == 0;
   }
-  Id add_rpm(const char *name, int flags = 0) {
-    return repo_add_rpm($self, name, flags);
+  bool add_updateinfoxml(FILE *fp, int flags = 0) {
+    return repo_add_updateinfoxml($self, fp, flags) == 0;
+  }
+  bool add_deltainfoxml(FILE *fp, int flags = 0) {
+    return repo_add_deltainfoxml($self, fp, flags) == 0;
   }
 #endif
+#ifdef ENABLE_DEBIAN
   bool add_debdb(int flags = 0) {
-    repo_add_debdb($self, 0, flags);
-    return 1;
+    return repo_add_debdb($self, flags) == 0;
   }
-  Id add_deb(const char *name, int flags = 0) {
-    return repo_add_deb($self, name, flags);
+  bool add_debpackages(FILE *fp, int flags = 0) {
+    return repo_add_debpackages($self, fp, flags) == 0;
   }
-  bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
-    repo_add_susetags($self, fp, defvendor, language, flags);
-    return 1;
+  %newobject add_deb;
+  XSolvable *add_deb(const char *name, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_deb($self, name, flags));
   }
-  bool add_repomdxml(FILE *fp, int flags = 0) {
-    repo_add_repomdxml($self, fp, flags);
-    return 1;
+#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) == 0;
   }
   bool add_content(FILE *fp, int flags = 0) {
-    repo_add_content($self, fp, flags);
-    return 1;
+    return repo_add_content($self, fp, flags) == 0;
   }
-  bool add_updateinfoxml(FILE *fp, int flags = 0) {
-    repo_add_updateinfoxml($self, fp, flags);
-    return 1;
+  bool add_products(const char *proddir, int flags = 0) {
+    return repo_add_products($self, proddir, flags) == 0;
   }
-  bool add_deltainfoxml(FILE *fp, int flags = 0) {
-    repo_add_deltainfoxml($self, fp, flags);
-    return 1;
+#endif
+#ifdef ENABLE_MDKREPO
+  bool add_mdk(FILE *fp, int flags = 0) {
+    return repo_add_mdk($self, fp, flags) == 0;
   }
-  void internalize() {
-    repo_internalize($self);
+  bool add_mdk_info(FILE *fp, int flags = 0) {
+    return repo_add_mdk_info($self, fp, flags) == 0;
   }
-  const char *lookup_str(Id entry, Id keyname) {
-    return repo_lookup_str($self, entry, keyname);
+#endif
+#ifdef ENABLE_ARCHREPO
+  bool add_arch_repo(FILE *fp, int flags = 0) {
+    return repo_add_arch_repo($self, fp, flags) == 0;
   }
-  Id lookup_id(Id entry, Id keyname) {
-    return repo_lookup_id($self, entry, keyname);
+  bool add_arch_local(const char *dir, int flags = 0) {
+    return repo_add_arch_local($self, dir, flags) == 0;
+  }
+  %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));
   }
-  unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
-    return repo_lookup_num($self, entry, keyname, notfound);
+#endif
+  void internalize() {
+    repo_internalize($self);
   }
-  void write(FILE *fp) {
-    repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
+  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, repo_write_stdkeyfilter, 0, 0);
+    res = repo_write($self, fp);
     $self->nrepodata = oldnrepodata;
-    return 1;
+    return res == 0;
   }
 
   %newobject Dataiterator;
@@ -1176,29 +1541,42 @@ 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 - $self->repodata);
+    return new_XRepodata($self, rd->repodataid);
   }
 
   void create_stubs() {
     Repodata *data;
     if (!$self->nrepodata)
       return;
-    data = $self->repodata  + ($self->nrepodata - 1);
+    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;
@@ -1210,18 +1588,32 @@ typedef struct {
         return 0;
     return 1;
   }
+  %newobject first_repodata;
   XRepodata *first_repodata() {
-     int i;
-     if ($self->nrepodata < 2)
+    Repodata *data;
+    int i;
+    if ($self->nrepodata < 2)
+      return 0;
+    /* make sure all repodatas but the first are extensions */
+    data = repo_id2repodata($self, 1);
+    if (data->loadcallback)
        return 0;
-     /* make sure all repodatas but the first are extensions */
-     if ($self->repodata[1].loadcallback)
-        return 0;
-     for (i = 2; i < $self->nrepodata; i++)
-       if (!$self->repodata[i].loadcallback)
-         return 0;       /* oops, not an extension */
-     return new_XRepodata($self, 1);
-   }
+    for (i = 2; i < $self->nrepodata; i++)
+      {
+        data = repo_id2repodata($self, i);
+        if (!data->loadcallback)
+          return 0;       /* oops, not an extension */
+      }
+    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;
@@ -1255,12 +1647,15 @@ typedef struct {
 
 %extend Dataiterator {
   static const int SEARCH_STRING = SEARCH_STRING;
+  static const int SEARCH_STRINGSTART = SEARCH_STRINGSTART;
+  static const int SEARCH_STRINGEND = SEARCH_STRINGEND;
   static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
   static const int SEARCH_GLOB = SEARCH_GLOB;
   static const int SEARCH_REGEX = SEARCH_REGEX;
   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));
@@ -1301,6 +1696,7 @@ typedef struct {
     }
     ndi = solv_calloc(1, sizeof(*ndi));
     dataiterator_init_clone(ndi, $self);
+    dataiterator_strdup(ndi);
     return ndi;
   }
 #ifdef SWIGRUBY
@@ -1319,6 +1715,98 @@ typedef struct {
   }
 }
 
+%extend Datapos {
+  Id lookup_id(Id keyname) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    Id r;
+    pool->pos = *$self;
+    r = pool_lookup_id(pool, SOLVID_POS, keyname);
+    pool->pos = oldpos;
+    return r;
+  }
+  const char *lookup_str(Id keyname) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    const char *r;
+    pool->pos = *$self;
+    r = pool_lookup_str(pool, SOLVID_POS, keyname);
+    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;
+    Datapos oldpos = pool->pos;
+    Id type = 0;
+    const unsigned char *b;
+    pool->pos = *$self;
+    b = pool_lookup_bin_checksum(pool, SOLVID_POS, keyname, &type);
+    pool->pos = oldpos;
+    return solv_chksum_create_from_bin(type, b);
+  }
+  const char *lookup_deltaseq() {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    const char *seq;
+    pool->pos = *$self;
+    seq = pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NAME);
+    if (seq) {
+      seq = pool_tmpjoin(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_EVR));
+      seq = pool_tmpappend(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NUM));
+    }
+    pool->pos = oldpos;
+    return seq;
+  }
+  const char *lookup_deltalocation(unsigned int *OUTPUT) {
+    Pool *pool = $self->repo->pool;
+    Datapos oldpos = pool->pos;
+    const char *loc;
+    pool->pos = *$self;
+    loc = pool_lookup_deltalocation(pool, SOLVID_POS, OUTPUT);
+    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 {
   ~Datamatch() {
     dataiterator_free($self);
@@ -1352,17 +1840,41 @@ 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() {
      return $self->kv.num2;
   }
-  void setpos() {
+  %newobject pos;
+  Datapos *pos() {
+    Pool *pool = $self->pool;
+    Datapos *pos, oldpos = pool->pos;
     dataiterator_setpos($self);
+    pos = solv_calloc(1, sizeof(*pos));
+    *pos = pool->pos;
+    pool->pos = oldpos;
+    return pos;
   }
-  void setpos_parent() {
+  %newobject parentpos;
+  Datapos *parentpos() {
+    Pool *pool = $self->pool;
+    Datapos *pos, oldpos = pool->pos;
     dataiterator_setpos_parent($self);
+    pos = solv_calloc(1, sizeof(*pos));
+    *pos = pool->pos;
+    pool->pos = oldpos;
+    return pos;
+  }
+#if defined(SWIGPERL)
+  %rename("str") __str__;
+#endif
+  const char *__str__() {
+    if (!repodata_stringify($self->pool, $self->data, $self->key, &$self->kv, $self->flags))
+      return "";
+    return $self->kv.str;
   }
 }
 
@@ -1464,7 +1976,7 @@ typedef struct {
   void each() {
     Repo *n;
     while ((n = Pool_repo_iterator___next__($self)) != 0) {
-      rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p__Repo, SWIG_POINTER_OWN | 0));
+      rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_Repo, SWIG_POINTER_OWN | 0));
     }
   }
 #endif
@@ -1547,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);
   }
@@ -1589,7 +2135,7 @@ typedef struct {
   Id lookup_id(Id keyname) {
     return pool_lookup_id($self->pool, $self->id, keyname);
   }
-  unsigned int lookup_num(Id keyname, unsigned int notfound = 0) {
+  unsigned long long lookup_num(Id keyname, unsigned long long notfound = 0) {
     return pool_lookup_num($self->pool, $self->id, keyname, notfound);
   }
   bool lookup_void(Id keyname) {
@@ -1601,8 +2147,44 @@ typedef struct {
     const unsigned char *b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, &type);
     return solv_chksum_create_from_bin(type, b);
   }
+  Queue lookup_idarray(Id keyname, Id marker = -1) {
+    Solvable *s = $self->pool->solvables + $self->id;
+    Queue r;
+    queue_init(&r);
+    if (marker == -1 || marker == 1) {
+      if (keyname == SOLVABLE_PROVIDES)
+        marker = marker < 0 ? -SOLVABLE_FILEMARKER : SOLVABLE_FILEMARKER;
+      else if (keyname == SOLVABLE_REQUIRES)
+        marker = marker < 0 ? -SOLVABLE_PREREQMARKER : SOLVABLE_PREREQMARKER;
+      else
+        marker = 0;
+    }
+    solvable_lookup_deparray(s, keyname, &r, marker);
+    return r;
+  }
+  %typemap(out) Queue lookup_deparray Queue2Array(Dep *, 1, new_Dep(arg1->pool, id));
+  %newobject lookup_deparray;
+  Queue lookup_deparray(Id keyname, Id marker = -1) {
+    Solvable *s = $self->pool->solvables + $self->id;
+    Queue r;
+    queue_init(&r);
+    if (marker == -1 || marker == 1) {
+      if (keyname == SOLVABLE_PROVIDES)
+        marker = marker < 0 ? -SOLVABLE_FILEMARKER : SOLVABLE_FILEMARKER;
+      else if (keyname == SOLVABLE_REQUIRES)
+        marker = marker < 0 ? -SOLVABLE_PREREQMARKER : SOLVABLE_PREREQMARKER;
+      else
+        marker = 0;
+    }
+    solvable_lookup_deparray(s, keyname, &r, marker);
+    return r;
+  }
   const char *lookup_location(unsigned int *OUTPUT) {
-    return solvable_get_location($self->pool->solvables + $self->id, OUTPUT);
+    return solvable_lookup_location($self->pool->solvables + $self->id, OUTPUT);
+  }
+  %newobject Dataiterator;
+  Dataiterator *Dataiterator(Id key, const char *match, int flags) {
+    return new_Dataiterator($self->pool, 0, $self->id, key, match, flags);
   }
 #ifdef SWIGRUBY
   %rename("installable?") installable;
@@ -1705,69 +2287,67 @@ typedef struct {
     }
   %}
 
-  void add_provides(Dep *dep, Id marker = -SOLVABLE_FILEMARKER) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->provides = repo_addid_dep(s->repo, s->provides, dep->id, marker);
-  }
-  void add_providesid(Id id, Id marker = -SOLVABLE_FILEMARKER) {
+  /* old interface, please use the generic add_deparray instead */
+  void add_provides(DepId id, Id marker = -1) {
     Solvable *s = $self->pool->solvables + $self->id;
+    if (marker == -1 || marker == 1)
+      marker = marker < 0 ? -SOLVABLE_FILEMARKER : SOLVABLE_FILEMARKER;
     s->provides = repo_addid_dep(s->repo, s->provides, id, marker);
   }
-  void add_obsoletes(Dep *dep) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->obsoletes = repo_addid_dep(s->repo, s->obsoletes, dep->id, 0);
-  }
-  void add_obsoletesid(Id id) {
+  void add_obsoletes(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
     s->obsoletes = repo_addid_dep(s->repo, s->obsoletes, id, 0);
   }
-  void add_conflicts(Dep *dep) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->conflicts = repo_addid_dep(s->repo, s->conflicts, dep->id, 0);
-  }
-  void add_conflictsid(Id id) {
+  void add_conflicts(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
     s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0);
   }
-  void add_requires(Dep *dep, Id marker = -SOLVABLE_PREREQMARKER) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->requires = repo_addid_dep(s->repo, s->requires, dep->id, marker);
-  }
-  void add_requiresid(Id id, Id marker = -SOLVABLE_PREREQMARKER) {
+  void add_requires(DepId id, Id marker = -1) {
     Solvable *s = $self->pool->solvables + $self->id;
+    if (marker == -1 || marker == 1)
+      marker = marker < 0 ? -SOLVABLE_PREREQMARKER : SOLVABLE_PREREQMARKER;
     s->requires = repo_addid_dep(s->repo, s->requires, id, marker);
   }
-  void add_recommends(Dep *dep) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->recommends = repo_addid_dep(s->repo, s->recommends, dep->id, 0);
-  }
-  void add_recommendsid(Id id) {
+  void add_recommends(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
     s->recommends = repo_addid_dep(s->repo, s->recommends, id, 0);
   }
-  void add_suggests(Dep *dep) {
-    Solvable *s = $self->pool->solvables + $self->id;
-    s->suggests = repo_addid_dep(s->repo, s->suggests, dep->id, 0);
-  }
-  void add_suggestsid(Id id) {
+  void add_suggests(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
     s->suggests = repo_addid_dep(s->repo, s->suggests, id, 0);
   }
-  void add_supplements(Dep *dep) {
+  void add_supplements(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
-    s->supplements = repo_addid_dep(s->repo, s->supplements, dep->id, 0);
+    s->supplements = repo_addid_dep(s->repo, s->supplements, id, 0);
   }
-  void add_supplementsid(Id id) {
+  void add_enhances(DepId id) {
     Solvable *s = $self->pool->solvables + $self->id;
-    s->supplements = repo_addid_dep(s->repo, s->supplements, id, 0);
+    s->enhances = repo_addid_dep(s->repo, s->enhances, id, 0);
   }
-  void add_enhances(Dep *dep) {
+
+  void unset(Id keyname) {
     Solvable *s = $self->pool->solvables + $self->id;
-    s->enhances = repo_addid_dep(s->repo, s->enhances, dep->id, 0);
+    repo_unset(s->repo, $self->id, keyname);
   }
-  void add_enhancesid(Id id) {
+
+  void add_deparray(Id keyname, DepId id, Id marker = -1) {
     Solvable *s = $self->pool->solvables + $self->id;
-    s->enhances = repo_addid_dep(s->repo, s->enhances, id, 0);
+    if (marker == -1 || marker == 1) {
+      if (keyname == SOLVABLE_PROVIDES)
+        marker = marker < 0 ? -SOLVABLE_FILEMARKER : SOLVABLE_FILEMARKER;
+      else if (keyname == SOLVABLE_REQUIRES)
+        marker = marker < 0 ? -SOLVABLE_PREREQMARKER : SOLVABLE_PREREQMARKER;
+      else
+        marker = 0;
+    }
+    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) {
@@ -1831,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;
@@ -1857,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;
@@ -1890,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;
           }
         }
@@ -1916,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;
@@ -1927,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;
@@ -1951,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;
@@ -1973,21 +2564,22 @@ 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;
     }
   %}
   %newobject Job;
   Job *Job() {
-    if ($self->type == SOLVER_SOLUTION_JOB)
+    Id extraflags = solver_solutionelement_extrajobflags($self->solv, $self->problemid, $self->solutionid);
+    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)
-      return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $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)
-      return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->rp);
+    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 || $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, $self->p);
+      return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE|extraflags, $self->p);
     return 0;
   }
 }
@@ -2008,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_IGNORE_ALREADY_RECOMMENDED = SOLVER_FLAG_IGNORE_ALREADY_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);
@@ -2092,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 {
@@ -2116,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;
@@ -2138,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);
@@ -2156,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() {
@@ -2167,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() {
@@ -2179,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);
@@ -2193,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);
   }
 }
@@ -2209,14 +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;
   }
+  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 {
@@ -2228,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]));
@@ -2257,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);
@@ -2276,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);
   }
 }
 
@@ -2290,63 +2961,65 @@ rb_eval_string(
     return xr;
   }
   Id new_handle() {
-    return repodata_new_handle($self->repo->repodata + $self->id);
+    return repodata_new_handle(repo_id2repodata($self->repo, $self->id));
   }
-  void set_id(Id solvid, Id keyname, Id id) {
-    repodata_set_id($self->repo->repodata + $self->id, solvid, keyname, id);
+  void set_id(Id solvid, Id keyname, DepId id) {
+    repodata_set_id(repo_id2repodata($self->repo, $self->id), solvid, keyname, id);
   }
   void set_str(Id solvid, Id keyname, const char *str) {
-    repodata_set_str($self->repo->repodata + $self->id, solvid, keyname, str);
+    repodata_set_str(repo_id2repodata($self->repo, $self->id), solvid, keyname, str);
   }
   void set_poolstr(Id solvid, Id keyname, const char *str) {
-    repodata_set_poolstr($self->repo->repodata + $self->id, solvid, keyname, str);
+    repodata_set_poolstr(repo_id2repodata($self->repo, $self->id), solvid, keyname, str);
   }
-  void add_idarray(Id solvid, Id keyname, Id id) {
-    repodata_add_idarray($self->repo->repodata + $self->id, solvid, keyname, id);
+  void add_idarray(Id solvid, Id keyname, DepId id) {
+    repodata_add_idarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, id);
   }
   void add_flexarray(Id solvid, Id keyname, Id handle) {
-    repodata_add_flexarray($self->repo->repodata + $self->id, solvid, keyname, handle);
+    repodata_add_flexarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, handle);
   }
   void set_checksum(Id solvid, Id keyname, Chksum *chksum) {
     const unsigned char *buf = solv_chksum_get(chksum, 0);
     if (buf)
-      repodata_set_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, solv_chksum_get_type(chksum), buf);
+      repodata_set_bin_checksum(repo_id2repodata($self->repo, $self->id), solvid, keyname, solv_chksum_get_type(chksum), buf);
   }
   const char *lookup_str(Id solvid, Id keyname) {
-    return repodata_lookup_str($self->repo->repodata + $self->id, solvid, keyname);
+    return repodata_lookup_str(repo_id2repodata($self->repo, $self->id), solvid, keyname);
   }
   Queue lookup_idarray(Id solvid, Id keyname) {
     Queue r;
     queue_init(&r);
-    repodata_lookup_idarray($self->repo->repodata + $self->id, solvid, keyname, &r);
+    repodata_lookup_idarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, &r);
     return r;
   }
   %newobject lookup_checksum;
   Chksum *lookup_checksum(Id solvid, Id keyname) {
     Id type = 0;
-    const unsigned char *b = repodata_lookup_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, &type);
+    const unsigned char *b = repodata_lookup_bin_checksum(repo_id2repodata($self->repo, $self->id), solvid, keyname, &type);
     return solv_chksum_create_from_bin(type, b);
   }
   void internalize() {
-    repodata_internalize($self->repo->repodata + $self->id);
+    repodata_internalize(repo_id2repodata($self->repo, $self->id));
   }
   void create_stubs() {
-    repodata_create_stubs($self->repo->repodata + $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($self->repo->repodata + $self->id, fp, repo_write_stdkeyfilter, 0);
+  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 = $self->repo->repodata + $self->id;
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
     int r, oldstate = data->state;
     data->state = REPODATA_LOADING;
-    r = repo_add_solv_flags(data->repo, fp, flags | REPO_USE_LOADING);
+    r = repo_add_solv(data->repo, fp, flags | REPO_USE_LOADING);
     if (r || data->state == REPODATA_LOADING)
       data->state = oldstate;
     return r;
   }
   void extend_to_repo() {
-    Repodata *data = $self->repo->repodata + $self->id;
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
     repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
   }
   bool __eq__(XRepodata *xr) {