Imported Upstream version 0.6.35
[platform/upstream/libsolv.git] / bindings / solv.i
index 8bbbd4a..8fb469f 100644 (file)
@@ -1,17 +1,8 @@
-#
-# WARNING: for perl iterator/array support you need to run
-#   sed -i -e 's/SvTYPE(tsv) == SVt_PVHV/SvTYPE(tsv) == SVt_PVHV || SvTYPE(tsv) == SVt_PVAV/'
-# on the generated c code
-#
-
-#
-##if defined(SWIGRUBY)
-#  %rename("to_s") string();
-##endif
-##if defined(SWIGPYTHON)
-#  %rename("__str__") string();
-##endif
-#
+/*
+ * WARNING: for perl iterator/array support you need to run
+ *   sed -i -e 's/SvTYPE(tsv) == SVt_PVHV/SvTYPE(tsv) == SVt_PVHV || SvTYPE(tsv) == SVt_PVAV/'
+ * on the generated c code
+ */
 
 %module solv
 
 %markfunc Pool "mark_Pool";
 #endif
 
+/**
+ ** binaryblob handling
+ **/
+
+%{
+typedef struct {
+  const void *data;
+  size_t len;
+} BinaryBlob;
+%}
+
+%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") (const unsigned char *str, size_t len) (int res, char *buf = 0, size_t size = 0, int alloc = 0) {
+#if defined(SWIGTCL)
+  {
+    int bal;
+    unsigned char *ba;
+    res = SWIG_TypeError;
+    ba = Tcl_GetByteArrayFromObj($input, &bal);
+    if (ba) {
+      buf = (char *)ba;
+      size = bal;
+      res = SWIG_OK;
+      alloc = SWIG_OLDOBJ;
+    }
+  }
+#else
+  res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
+  if (buf && size)
+    size--;
+#endif
+  if (!SWIG_IsOK(res)) {
+#if defined(SWIGPYTHON)
+    const void *pybuf = 0;
+    Py_ssize_t pysize = 0;
+    res = PyObject_AsReadBuffer($input, &pybuf, &pysize);
+    if (res < 0) {
+      %argument_fail(res, "BinaryBlob", $symname, $argnum);
+    } else {
+      buf = (void *)pybuf;
+      size = pysize;
+    }
+#else
+    %argument_fail(res, "const char *", $symname, $argnum);
+#endif
+  }
+  $1 = (unsigned char *)buf;
+  $2 = size;
+}
+
+%typemap(freearg,noblock=1,match="in") (const unsigned char *str, int len) {
+  if (alloc$argnum == SWIG_NEWOBJ) %delete_array(buf$argnum);
+}
+
+%typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") BinaryBlob {
+#if defined(SWIGPYTHON) && defined(PYTHON3)
+  $result = $1.data ? Py_BuildValue("y#", $1.data, $1.len) : SWIG_Py_Void();
+#elif defined(SWIGTCL)
+  Tcl_SetObjResult(interp, $1.data ? Tcl_NewByteArrayObj($1.data, $1.len) : NULL);
+#else
+  $result = SWIG_FromCharPtrAndSize($1.data, $1.len);
+#if defined(SWIGPERL)
+  argvi++;
+#endif
+#endif
+}
+
+/**
+ ** Queue handling
+ **/
+
+%typemap(arginit) Queue {
+  queue_init(&$1);
+}
+%typemap(freearg) Queue {
+  queue_free(&$1);
+}
+
 #if defined(SWIGPYTHON)
 %typemap(in) Queue {
   /* Check if is a list */
-  queue_init(&$1);
   if (PyList_Check($input)) {
     int size = PyList_Size($input);
     int i = 0;
       PyObject *o = PyList_GetItem($input,i);
       int v;
       int e = SWIG_AsVal_int(o, &v);
-      if (!SWIG_IsOK(e)) {
+      if (!SWIG_IsOK(e))
         SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
-        queue_free(&$1);
-        return NULL;
-      }
       queue_push(&$1, v);
     }
   } else {
-    PyErr_SetString(PyExc_TypeError,"not a list");
-    return NULL;
+    SWIG_exception_fail(SWIG_TypeError, "list must contain only integers");
   }
 }
 
 
 %enddef
 
-#endif
-
+#endif  /* SWIGPYTHON */
 
 #if defined(SWIGPERL)
 %typemap(in) Queue {
   AV *av;
   int i, size;
-  queue_init(&$1);
   if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV)
     SWIG_croak("Argument $argnum is not an array reference.");
   av = (AV*)SvRV($input);
     queue_push(&$1, v);
   }
 }
-# AV *o = newAV();
-# av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
-# $result = newRV_noinc((SV*)o); argvi++;
-#
+/* AV *o = newAV();
+ * av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
+ * $result = newRV_noinc((SV*)o); argvi++;
+ */
 %typemap(out) Queue {
   int i;
   if (argvi + $1.count + 1 >= items) {
   queue_free(&$1);
   $result = 0;
 }
+
 %define Queue2Array(type, step, con) %{
   int i;
   int cnt = $1.count / step;
 %}
 %enddef
 
-#endif
+#endif  /* SWIGPERL */
 
-%typemap(arginit) Queue {
-  queue_init(&$1);
-}
-%typemap(freearg) Queue {
-  queue_free(&$1);
-}
 
 #if defined(SWIGRUBY)
 %typemap(in) Queue {
   int size, i;
-  VALUE *o;
-  queue_init(&$1);
-  size = RARRAY_LEN($input);
+  VALUE *o, ary;
+  ary = rb_Array($input);
+  size = RARRAY_LEN(ary);
   i = 0;
-  o = RARRAY_PTR($input);
+  o = RARRAY_PTR(ary);
   for (i = 0; i < size; i++, o++) {
     int v;
     int e = SWIG_AsVal_int(*o, &v);
     if (!SWIG_IsOK(e))
-      {
-        SWIG_Error(SWIG_RuntimeError, "list must contain only integers");
-        SWIG_fail;
-      }
+      SWIG_exception_fail(SWIG_TypeError, "list must contain only integers");
     queue_push(&$1, v);
   }
 }
   $result = o;
 %}
 %enddef
-#endif
 
+#endif  /* SWIGRUBY */
+
+#if defined(SWIGTCL)
+%typemap(in) Queue {
+  /* Check if is a list */
+  int size = 0;
+  int i = 0;
+
+  if (TCL_OK != Tcl_ListObjLength(interp, $input, &size))
+    SWIG_exception_fail(SWIG_TypeError, "argument is not a list");
+  for (i = 0; i < size; i++) {
+    Tcl_Obj *o = NULL;
+    int e, v;
+
+    if (TCL_OK != Tcl_ListObjIndex(interp, $input, i, &o))
+      SWIG_exception_fail(SWIG_IndexError, "failed to retrieve a list member");
+    e = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(o, &v);
+    if (!SWIG_IsOK(e))
+      SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
+    queue_push(&$1, v);
+  }
+}
+
+%typemap(out) Queue {
+  Tcl_Obj *objvx[$1.count];
+  int i;
+
+  for (i = 0; i < $1.count; i++) {
+    objvx[i] = SWIG_From_int($1.elements[i]);
+  }
+  Tcl_SetObjResult(interp, Tcl_NewListObj($1.count, objvx));
+  queue_free(&$1);
+}
+
+%define Queue2Array(type, step, con) %{
+  { /* scope is needed to make the goto of SWIG_exception_fail work */
+    int i;
+    int cnt = $1.count / step;
+    Id *idp = $1.elements;
+    Tcl_Obj *objvx[cnt];
+
+    for (i = 0; i < cnt; i++, idp += step) {
+      Id id = *idp;
+#define result resultx
+#define Tcl_SetObjResult(i, x) resultobj = x
+      type result = con;
+      Tcl_Obj *resultobj;
+      $typemap(out, type)
+      objvx[i] = resultobj;
+#undef Tcl_SetObjResult
+#undef result
+    }
+    queue_free(&$1);
+    Tcl_SetObjResult(interp, Tcl_NewListObj(cnt, objvx));
+  }
+%}
+
+%enddef
+
+%typemap(in) Queue solvejobs {
+  /* Check if is a list */
+  int size = 0;
+  int i = 0;
+
+  if (TCL_OK != Tcl_ListObjLength(interp, $input, &size))
+    SWIG_exception_fail(SWIG_TypeError, "argument is not a list");
+  for (i = 0; i < size; i++) {
+    Tcl_Obj *o = NULL;
+    void *jp;
+    Job *j;
+    int e;
+
+    if (TCL_OK != Tcl_ListObjIndex(interp, $input, i, &o))
+      SWIG_exception_fail(SWIG_IndexError, "failed to retrieve a list member");
+    e = SWIG_ConvertPtr(o, &jp ,SWIGTYPE_p_Job, 0 |  0 );
+    if (!SWIG_IsOK(e))
+      SWIG_exception_fail(SWIG_ArgError(e), "list member is not a Job");
+    j = (Job *)jp;
+    queue_push2(&$1, j->how, j->what);
+  }
+}
 
+#endif  /* SWIGTCL */
 
 
 #if defined(SWIGPERL)
 
-# work around a swig bug
+/* work around a swig bug for swig versions < 2.0.5 */
+#if SWIG_VERSION < 0x020005
 %{
 #undef SWIG_CALLXS
-#ifdef PERL_OBJECT 
-#  define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl) 
-#else 
-#  ifndef MULTIPLICITY 
-#    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv) 
-#  else 
-#    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv) 
-#  endif 
-#endif 
+#ifdef PERL_OBJECT
+#  define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl)
+#else
+#  ifndef MULTIPLICITY
+#    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv)
+#  else
+#    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv)
+#  endif
+#endif
 %}
+#endif
 
 
 %define perliter(class)
@@ -292,27 +428,38 @@ SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int f
 %typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
 %typemap(out) Dataiterator * = Perliterator;
 
-#endif
+#endif  /* SWIGPERL */
+
 
+/**
+ ** appdata handling
+ **/
 
 #if defined(SWIGPYTHON)
 typedef PyObject *AppObjectPtr;
+%typemap(in) AppObjectPtr {
+  if ($input)
+    Py_INCREF($input);
+  $1 = $input;
+}
 %typemap(out) AppObjectPtr {
   $result = $1 ? $1 : Py_None;
   Py_INCREF($result);
 }
-#endif
-#if defined(SWIGPERL)
+#elif defined(SWIGPERL)
 typedef SV *AppObjectPtr;
 %typemap(in) AppObjectPtr {
-  $1 = SvROK($input) ? SvRV($input) : 0;
+  if ($input) {
+    $1 = newSV(0);
+    sv_setsv((SV *)$1, $input);
+  } else
+    $1 = (void *)0;
 }
 %typemap(out) AppObjectPtr {
-  $result = $1 ? newRV_inc($1) : newSV(0);
+  $result = sv_2mortal($1 ? SvREFCNT_inc($1) : newSV(0));
   argvi++;
 }
-#endif
-#if defined(SWIGRUBY)
+#elif defined(SWIGRUBY)
 typedef VALUE AppObjectPtr;
 %typemap(in) AppObjectPtr {
   $1 = (void *)$input;
@@ -320,10 +467,24 @@ typedef VALUE AppObjectPtr;
 %typemap(out) AppObjectPtr {
   $result = (VALUE)$1;
 }
+#elif defined(SWIGTCL)
+typedef Tcl_Obj *AppObjectPtr;
+%typemap(in) AppObjectPtr {
+  if ($input)
+    Tcl_IncrRefCount($input);
+  $1 = (void *)$input;
+}
+%typemap(out) AppObjectPtr {
+  Tcl_SetObjResult(interp, $1 ? $1 : Tcl_NewObj());
+}
+#else
+#warning AppObjectPtr not defined for this language!
 #endif
 
+/**
+ ** FILE handling
+ **/
 
-%include "cdata.i"
 #ifdef SWIGPYTHON
 %include "file.i"
 #else
@@ -336,6 +497,8 @@ typedef VALUE AppObjectPtr;
 SWIGINTERN int
 #ifdef SWIGRUBY
 SWIG_AsValSolvFpPtr(VALUE obj, FILE **val) {
+#elif defined(SWIGTCL)
+SWIG_AsValSolvFpPtr SWIG_TCL_DECL_ARGS_2(void *obj, FILE **val) {
 #else
 SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
 #endif
@@ -357,22 +520,36 @@ SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
   return SWIG_TypeError;
 }
 
+#if defined(SWIGTCL)
+#define SWIG_AsValSolvFpPtr(x, y) SWIG_AsValSolvFpPtr SWIG_TCL_CALL_ARGS_2(x, y)
+#endif
+
 }
 
 
+/**
+ ** DepId handling
+ **/
+
 %fragment("SWIG_AsValDepId","header") {
 
 SWIGINTERN int
 #ifdef SWIGRUBY
 SWIG_AsValDepId(VALUE obj, int *val) {
+#elif defined(SWIGTCL)
+SWIG_AsValDepId SWIG_TCL_DECL_ARGS_2(void *obj, int *val) {
 #else
 SWIG_AsValDepId(void *obj, int *val) {
 #endif
   static swig_type_info* desc = 0;
-  void *vptr = 0; 
+  void *vptr = 0;
   int ecode;
   if (!desc) desc = SWIG_TypeQuery("Dep *");
+#ifdef SWIGTCL
+  ecode = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(obj, val);
+#else
   ecode = SWIG_AsVal_int(obj, val);
+#endif
   if (SWIG_IsOK(ecode))
     return ecode;
   if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
@@ -383,16 +560,57 @@ SWIG_AsValDepId(void *obj, int *val) {
   return SWIG_TypeError;
 }
 
+#ifdef SWIGTCL
+#define SWIG_AsValDepId(x, y) SWIG_AsValDepId SWIG_TCL_CALL_ARGS_2(x, y)
+#endif
 }
 
+/**
+ ** Pool disown helper
+ **/
 
+%typemap(out) disown_helper {
+#if defined(SWIGRUBY)
+  SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
+#elif defined(SWIGPYTHON)
+  SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
+#elif defined(SWIGPERL)
+  SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
+#elif defined(SWIGTCL)
+  SWIG_ConvertPtr(objv[1], &argp1, SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN | 0);
+#else
+#warning disown_helper not implemented for this language, this is likely going to leak memory
+#endif
+
+#ifdef SWIGTCL
+  Tcl_SetObjResult(interp, SWIG_From_int((int)(0)));
+#else
+  $result = SWIG_From_int((int)(0));
+#endif
+}
+
+
+/**
+ ** misc stuff
+ **/
 
 %include "typemaps.i"
 
+%typemap(in,numinputs=0,noblock=1) XRule **OUTPUT ($*1_ltype temp) {
+  $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);
 
 
+/**
+ ** the C declarations
+ **/
+
 %{
 #include <stdbool.h>
 #include <stdio.h>
@@ -400,6 +618,7 @@ SWIG_AsValDepId(void *obj, int *val) {
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 /* argh, swig undefs bool for perl */
 #ifndef bool
@@ -408,6 +627,7 @@ typedef int bool;
 
 #include "pool.h"
 #include "poolarch.h"
+#include "evr.h"
 #include "solver.h"
 #include "policy.h"
 #include "solverdebug.h"
@@ -416,11 +636,11 @@ typedef int bool;
 #include "selection.h"
 
 #include "repo_write.h"
-#ifdef ENABLE_RPMDB
+#if defined(ENABLE_RPMDB) || defined(ENABLE_RPMPKG)
 #include "repo_rpmdb.h"
 #endif
-#ifdef ENABLE_RPMDB_PUBKEYS
-#include "repo_rpmdb_pubkey.h"
+#ifdef ENABLE_PUBKEY
+#include "repo_pubkey.h"
 #endif
 #ifdef ENABLE_DEBIAN
 #include "repo_deb.h"
@@ -442,7 +662,14 @@ typedef int bool;
 #ifdef ENABLE_ARCHREPO
 #include "repo_arch.h"
 #endif
+#ifdef SUSE
+#include "repo_autopattern.h"
+#endif
+#if defined(ENABLE_COMPLEX_DEPS) && (defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) || defined(ENABLE_RPMDB) || defined(ENABLE_RPMPKG))
+#include "pool_parserpmrichdep.h"
+#endif
 #include "solv_xfopen.h"
+#include "testcase.h"
 
 /* for old ruby versions */
 #ifndef RARRAY_PTR
@@ -459,7 +686,6 @@ typedef int bool;
 #define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    -104
 #define SOLVER_SOLUTION_REPLACE_NAMECHANGE      -105
 
-typedef struct chksum Chksum;
 typedef void *AppObjectPtr;
 typedef Id DepId;
 
@@ -532,10 +758,21 @@ typedef struct {
   Id type;
   Id source;
   Id target;
-  Id dep;
+  Id dep_id;
 } Ruleinfo;
 
 typedef struct {
+  Solver *solv;
+  Id type;
+  Id rid;
+  Id from_id;
+  Id dep_id;
+  Id chosen_id;
+  Queue choices;
+  int level;
+} Alternative;
+
+typedef struct {
   Transaction *transaction;
   int mode;
   Id type;
@@ -556,8 +793,132 @@ typedef struct {
 
 typedef Dataiterator Datamatch;
 
+typedef int disown_helper;
+
+struct myappdata {
+  void *appdata;
+  int disowned;
+};
+
+
+%}
+
+/**
+ ** appdata helpers
+ **/
+
+#ifdef SWIGRUBY
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+  *appdatap = 0;
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+  *appdatap = appdata;
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+  return appdata;
+}
+%}
+
+#elif defined(SWIGTCL)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+  if (*appdatap)
+    Tcl_DecrRefCount((Tcl_Obj *)(*appdatap));
+  *appdatap = 0;
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+  appdata_clr_helper(appdatap);
+  *appdatap = appdata;
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+  return appdata;
+}
+%}
+
+#elif defined(SWIGPYTHON)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+  struct myappdata *myappdata = appdata;
+  if (!myappdata || !myappdata->appdata || myappdata->disowned)
+    return;
+  myappdata->disowned = 1;
+  Py_DECREF((PyObject *)myappdata->appdata);
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+  struct myappdata *myappdata = *(struct myappdata **)appdatap;
+  if (myappdata && myappdata->appdata && !myappdata->disowned) {
+    Py_DECREF((PyObject *)myappdata->appdata);
+  }
+  *appdatap = solv_free(myappdata);
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+  appdata_clr_helper(appdatap);
+  if (appdata) {
+    struct myappdata *myappdata = *appdatap = solv_calloc(sizeof(struct myappdata), 1);
+    myappdata->appdata = appdata;
+  }
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+  return appdata ? ((struct myappdata *)appdata)->appdata : 0;
+}
+
+%}
+
+#elif defined(SWIGPERL)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+  struct myappdata *myappdata = appdata;
+  SV *rsv;
+  if (!myappdata || !myappdata->appdata || myappdata->disowned)
+    return;
+  rsv = myappdata->appdata;
+  if (!SvROK(rsv))
+    return;
+  myappdata->appdata = SvRV(rsv);
+  myappdata->disowned = 1;
+  SvREFCNT_dec(rsv);
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+  struct myappdata *myappdata = *(struct myappdata **)appdatap;
+  if (myappdata && myappdata->appdata && !myappdata->disowned) {
+    SvREFCNT_dec((SV *)myappdata->appdata);
+  }
+  *appdatap = solv_free(myappdata);
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+  appdata_clr_helper(appdatap);
+  if (appdata) {
+    struct myappdata *myappdata = *appdatap = solv_calloc(sizeof(struct myappdata), 1);
+    myappdata->appdata = appdata;
+  }
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+  struct myappdata *myappdata = appdata;
+  if (!myappdata || !myappdata->appdata)
+    return 0;
+  return myappdata->disowned ? newRV_noinc((SV *)myappdata->appdata) : myappdata->appdata;
+}
+
 %}
 
+#else
+#warning appdata helpers not implemented for this language
+#endif
+
+
+/**
+ ** the SWIG declarations defining the API
+ **/
+
 #ifdef SWIGRUBY
 %mixin Dataiterator "Enumerable";
 %mixin Pool_solvable_iterator "Enumerable";
@@ -569,14 +930,27 @@ typedef int Id;
 
 %include "knownid.h"
 
-# from repodata.h
+/* from repodata.h */
 %constant Id SOLVID_META;
 %constant Id SOLVID_POS;
 
 %constant int REL_EQ;
 %constant int REL_GT;
 %constant int REL_LT;
+%constant int REL_AND;
+%constant int REL_OR;
+%constant int REL_WITH;
+%constant int REL_NAMESPACE;
 %constant int REL_ARCH;
+%constant int REL_FILECONFLICT;
+%constant int REL_COND;
+%constant int REL_COMPAT;
+%constant int REL_KIND;
+%constant int REL_MULTIARCH;
+%constant int REL_ELSE;
+%constant int REL_ERROR;
+%constant int REL_WITHOUT;
+%constant int REL_UNLESS;
 
 typedef struct {
   Pool* const pool;
@@ -587,7 +961,7 @@ typedef struct {
   Id const id;
 } Dep;
 
-# put before pool/repo so we can access the constructor
+/* put before pool/repo so we can access the constructor */
 %nodefaultdtor Dataiterator;
 typedef struct {} Dataiterator;
 
@@ -599,7 +973,7 @@ typedef struct {
 typedef struct {
   Solver* const solv;
   Id const type;
-  Id const dep;
+  Id const dep_id;
 } Ruleinfo;
 
 typedef struct {
@@ -638,7 +1012,6 @@ typedef struct {
 %nodefaultctor Pool;
 %nodefaultdtor Pool;
 typedef struct {
-  AppObjectPtr appdata;
 } Pool;
 
 %nodefaultctor Repo;
@@ -649,7 +1022,6 @@ typedef struct {
   int priority;
   int subpriority;
   int const nsolvables;
-  AppObjectPtr appdata;
 } Repo;
 
 %nodefaultctor Solver;
@@ -661,6 +1033,15 @@ typedef struct {
 typedef struct {
 } Chksum;
 
+#ifdef ENABLE_PUBKEY
+typedef struct {
+  Id const htype;
+  unsigned int const created;
+  unsigned int const expires;
+  const char * const keyid;
+} Solvsig;
+#endif
+
 %rename(xfopen) solvfp_xfopen;
 %rename(xfopen_fd) solvfp_xfopen_fd;
 
@@ -679,9 +1060,14 @@ SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
     SolvFp *sfp;
     FILE *fp;
     fd = dup(fd);
-    fp = fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
-    if (!fp)
+    if (fd == -1)
+      return 0;
+    fcntl(fd, F_SETFD, FD_CLOEXEC);
+    fp = solv_xfopen_fd(fn, fd, mode);
+    if (!fp) {
+      close(fd);
       return 0;
+    }
     sfp = solv_calloc(1, sizeof(SolvFp));
     sfp->fp = fp;
     return sfp;
@@ -692,6 +1078,8 @@ SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
     fp = solv_xfopen(fn, mode);
     if (!fp)
       return 0;
+    if (fileno(fp) != -1)
+      fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
     sfp = solv_calloc(1, sizeof(SolvFp));
     sfp->fp = fp;
     return sfp;
@@ -717,6 +1105,17 @@ typedef struct {
   Id const type;
 } Solutionelement;
 
+%nodefaultctor Alternative;
+typedef struct {
+  Solver *const solv;
+  Id const type;
+  Id const rid;
+  Id const from_id;
+  Id const dep_id;
+  Id const chosen_id;
+  int level;
+} Alternative;
+
 %nodefaultctor Transaction;
 %nodefaultdtor Transaction;
 typedef struct {
@@ -743,6 +1142,9 @@ typedef struct {
   int dup() {
     return $self->fp ? dup(fileno($self->fp)) : -1;
   }
+  bool write(const unsigned char *str, size_t len) {
+    return fwrite(str, len, 1, $self->fp) == 1;
+  }
   bool flush() {
     if (!$self->fp)
       return 1;
@@ -756,6 +1158,11 @@ typedef struct {
     $self->fp = 0;
     return ret;
   }
+  void cloexec(bool state) {
+    if (!$self->fp || fileno($self->fp) == -1)
+      return;
+    fcntl(fileno($self->fp), F_SETFD, state ? FD_CLOEXEC : 0);
+  }
 }
 
 %extend Job {
@@ -777,12 +1184,16 @@ typedef struct {
   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
   static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
   static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
+  static const Id SOLVER_ALLOWUNINSTALL = SOLVER_ALLOWUNINSTALL;
+  static const Id SOLVER_FAVOR = SOLVER_FAVOR;
+  static const Id SOLVER_DISFAVOR = SOLVER_DISFAVOR;
   static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
   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_NOTBYUSER = SOLVER_NOTBYUSER;
   static const Id SOLVER_SETEV = SOLVER_SETEV;
   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
@@ -815,18 +1226,27 @@ typedef struct {
     return pool_isemptyupdatejob($self->pool, $self->how, $self->what);
   }
 
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(Job *j) {
     return $self->pool == j->pool && $self->how == j->how && $self->what == j->what;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(Job *j) {
     return !Job___eq__($self, j);
   }
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   const char *__str__() {
     return pool_job2str($self->pool, $self->how, $self->what, 0);
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   const char *__repr__() {
     const char *str = pool_job2str($self->pool, $self->how, $self->what, ~0);
     return pool_tmpjoin($self->pool, "<Job ", str, ">");
@@ -844,8 +1264,18 @@ typedef struct {
   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_SKIP_KIND = SELECTION_SKIP_KIND;
+  static const Id SELECTION_MATCH_DEPSTR = SELECTION_MATCH_DEPSTR;
   static const Id SELECTION_SOURCE_ONLY = SELECTION_SOURCE_ONLY;
   static const Id SELECTION_WITH_SOURCE = SELECTION_WITH_SOURCE;
+  static const Id SELECTION_WITH_DISABLED = SELECTION_WITH_DISABLED;
+  static const Id SELECTION_WITH_BADARCH = SELECTION_WITH_BADARCH;
+  static const Id SELECTION_WITH_ALL = SELECTION_WITH_ALL;
+  static const Id SELECTION_ADD = SELECTION_ADD;
+  static const Id SELECTION_SUBTRACT = SELECTION_SUBTRACT;
+  static const Id SELECTION_FILTER = SELECTION_FILTER;
+  static const Id SELECTION_FILTER_KEEP_IFEMPTY = SELECTION_FILTER_KEEP_IFEMPTY;
+  static const Id SELECTION_FILTER_SWAPPED = SELECTION_FILTER_SWAPPED;
 
   Selection(Pool *pool) {
     Selection *s;
@@ -861,15 +1291,19 @@ 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;
   }
+  %newobject clone;
+  Selection *clone(int flags = 0) {
+    Selection *s = new_Selection($self->pool);
+    queue_init_clone(&s->q, &$self->q);
+    s->flags = $self->flags;
+    return s;
+  }
   void filter(Selection *lsel) {
     if ($self->pool != lsel->pool)
       queue_empty(&$self->q);
@@ -886,6 +1320,27 @@ typedef struct {
   void add_raw(Id how, Id what) {
     queue_push2(&$self->q, how, what);
   }
+  void subtract(Selection *lsel) {
+    if ($self->pool == lsel->pool)
+      selection_subtract($self->pool, &$self->q, &lsel->q);
+  }
+  
+  void select(const char *name, int flags) {
+    if ((flags & SELECTION_MODEBITS) == 0)
+      flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
+    $self->flags = selection_make($self->pool, &$self->q, name, flags);
+  }
+  void matchdeps(const char *name, int flags, Id keyname, Id marker = -1) {
+    if ((flags & SELECTION_MODEBITS) == 0)
+      flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
+    $self->flags = selection_make_matchdeps($self->pool, &$self->q, name, flags, keyname, marker);
+  }
+  void matchdepid(DepId dep, int flags, Id keyname, Id marker = -1) {
+    if ((flags & SELECTION_MODEBITS) == 0)
+      flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
+    $self->flags = selection_make_matchdepid($self->pool, &$self->q, dep, flags, keyname, marker);
+  }
+
   %typemap(out) Queue jobs Queue2Array(Job *, 2, new_Job(arg1->pool, id, idp[1]));
   %newobject jobs;
   Queue jobs(int flags) {
@@ -906,12 +1361,15 @@ typedef struct {
     return q;
   }
 
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   const char *__str__() {
     return pool_selection2str($self->pool, &$self->q, 0);
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   const char *__repr__() {
     const char *str = pool_selection2str($self->pool, &$self->q, ~0);
     return pool_tmpjoin($self->pool, "<Selection ", str, ">");
@@ -920,7 +1378,7 @@ typedef struct {
 
 %extend Chksum {
   Chksum(Id type) {
-    return (Chksum *)solv_chksum_create(type);
+    return solv_chksum_create(type);
   }
   Chksum(Id type, const char *hex) {
     unsigned char buf[64];
@@ -929,19 +1387,33 @@ typedef struct {
       return 0;
     if (solv_hex2bin(&hex, buf, sizeof(buf)) != l || hex[0])
       return 0;
-    return (Chksum *)solv_chksum_create_from_bin(type, buf);
+    return solv_chksum_create_from_bin(type, buf);
+  }
+  %newobject from_bin;
+  static Chksum *from_bin(Id type, const unsigned char *str, size_t len) {
+    return len == solv_chksum_len(type) ? solv_chksum_create_from_bin(type, str) : 0;
+  }
+#if defined(SWIGPERL)
+  %perlcode {
+    undef *solv::Chksum::from_bin;
+    *solv::Chksum::from_bin = sub {
+      my $pkg = shift;
+      my $self = solvc::Chksum_from_bin(@_);
+      bless $self, $pkg if defined $self;
+    };
   }
+#endif
   ~Chksum() {
     solv_chksum_free($self, 0);
   }
   Id const type;
   %{
-  SWIGINTERN Id Chksum_type_get(Chksum *chksum) {
-    return solv_chksum_get_type(chksum);
+  SWIGINTERN Id Chksum_type_get(Chksum *chk) {
+    return solv_chksum_get_type(chk);
   }
   %}
-  void add(const char *str) {
-    solv_chksum_add($self, str, strlen((char *)str));
+  void add(const unsigned char *str, size_t len) {
+    solv_chksum_add($self, str, (int)len);
   }
   void add_fp(FILE *fp) {
     char buf[4096];
@@ -975,11 +1447,14 @@ typedef struct {
     solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
     solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
   }
-  SWIGCDATA raw() {
+  BinaryBlob raw() {
+    BinaryBlob bl;
     int l;
     const unsigned char *b;
     b = solv_chksum_get($self, &l);
-    return cdata_void((void *)b, l);
+    bl.data = b;
+    bl.len = l;
+    return bl;
   }
   %newobject hex;
   char *hex() {
@@ -992,26 +1467,26 @@ typedef struct {
     solv_bin2hex(b, l, ret);
     return ret;
   }
+  const char *typestr() {
+    return solv_chksum_type2str(solv_chksum_get_type($self));
+  }
 
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(Chksum *chk) {
-    int l;
-    const unsigned char *b, *bo;
-    if (!chk)
-      return 0;
-    if (solv_chksum_get_type($self) != solv_chksum_get_type(chk))
-      return 0;
-    b = solv_chksum_get($self, &l);
-    bo = solv_chksum_get(chk, 0);
-    return memcmp(b, bo, l) == 0;
+    return solv_chksum_cmp($self, chk);
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(Chksum *chk) {
-    return !Chksum___eq__($self, chk);
+    return !solv_chksum_cmp($self, chk);
   }
 #if defined(SWIGRUBY)
   %rename("to_s") __str__;
-  %rename("inspect") __repr__;
 #endif
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   %newobject __str__;
@@ -1024,6 +1499,9 @@ typedef struct {
     solv_free((void *)h);
     return str;
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     const char *h = Chksum___str__($self);
@@ -1034,11 +1512,26 @@ 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;
+  static const int DISTTYPE_RPM = DISTTYPE_RPM;
+  static const int DISTTYPE_DEB = DISTTYPE_DEB;
+  static const int DISTTYPE_ARCH = DISTTYPE_ARCH;
+  static const int DISTTYPE_HAIKU = DISTTYPE_HAIKU;
+
   Pool() {
     Pool *pool = pool_create();
     return pool;
   }
-  ~Pool() {
+  int setdisttype(int disttype) {
+    return pool_setdisttype($self, disttype);
   }
   void set_debuglevel(int level) {
     pool_setdebuglevel($self, level);
@@ -1071,18 +1564,21 @@ typedef struct {
     return SWIG_IsOK(ecode) ? vresult : 0;
   }
   %}
-  void set_loadcallback(PyObject *callable) {
+  void clr_loadcallback() {
     if ($self->loadcallback == loadcallback) {
       PyObject *obj = $self->loadcallbackdata;
       Py_DECREF(obj);
+      pool_setloadcallback($self, 0, 0);
     }
+  }
+  void set_loadcallback(PyObject *callable) {
+    Pool_clr_loadcallback($self);
     if (callable) {
       Py_INCREF(callable);
+      pool_setloadcallback($self, loadcallback, callable);
     }
-    pool_setloadcallback($self, callable ? loadcallback : 0, callable);
   }
-#endif
-#if defined(SWIGPERL)
+#elif defined(SWIGPERL)
 %{
   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
     int count;
@@ -1105,16 +1601,20 @@ typedef struct {
     return ret;
   }
 %}
-  void set_loadcallback(SV *callable) {
-    if ($self->loadcallback == loadcallback)
+  void clr_loadcallback() {
+    if ($self->loadcallback == loadcallback) {
       SvREFCNT_dec($self->loadcallbackdata);
-    if (callable)
+      pool_setloadcallback($self, 0, 0);
+    }
+  }
+  void set_loadcallback(SV *callable) {
+    Pool_clr_loadcallback($self);
+    if (callable) {
       SvREFCNT_inc(callable);
-    pool_setloadcallback($self, callable ? loadcallback : 0, callable);
+      pool_setloadcallback($self, loadcallback, callable);
+    }
   }
-#endif
-
-#if defined(SWIGRUBY)
+#elif defined(SWIGRUBY)
 %{
   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
     XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
@@ -1131,25 +1631,112 @@ typedef struct {
     }
   }
 %}
+  void clr_loadcallback() {
+    pool_setloadcallback($self, 0, 0);
+  }
   %typemap(in, numinputs=0) VALUE callable {
     $1 = rb_block_given_p() ? rb_block_proc() : 0;
   }
   void set_loadcallback(VALUE callable) {
     pool_setloadcallback($self, callable ? loadcallback : 0, (void *)callable);
   }
+#elif defined(SWIGTCL)
+  %{
+  typedef struct {
+    Tcl_Interp *interp;
+    Tcl_Obj *obj;
+  } tcl_callback_t;
+  SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
+    tcl_callback_t *callback_var = (tcl_callback_t *)d;
+    Tcl_Interp *interp = callback_var->interp;
+    XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
+    int result, ecode = 0, vresult = 0;
+    Tcl_Obj *objvx[2];
+    objvx[0] = callback_var->obj;
+    objvx[1] = SWIG_NewInstanceObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, 0); 
+    Tcl_IncrRefCount(objvx[1]);
+    result = Tcl_EvalObjv(interp, sizeof(objvx)/sizeof(*objvx), objvx, TCL_EVAL_GLOBAL);
+    Tcl_DecrRefCount(objvx[1]);
+    if (result != TCL_OK)
+      return 0; /* exception */
+    ecode = SWIG_AsVal_int(interp, Tcl_GetObjResult(interp), &vresult);
+    return SWIG_IsOK(ecode) ? vresult : 0;
+  }
+  %}
+  void clr_loadcallback() {
+    if ($self->loadcallback == loadcallback) {
+      tcl_callback_t *callback_var = $self->loadcallbackdata;
+      Tcl_DecrRefCount(callback_var->obj);
+      solv_free(callback_var);
+      pool_setloadcallback($self, 0, 0);
+    }
+  }
+  void set_loadcallback(Tcl_Obj *callable, Tcl_Interp *interp) {
+    Pool_clr_loadcallback($self);
+    if (callable) {
+      tcl_callback_t *callback_var = solv_malloc(sizeof(tcl_callback_t));
+      Tcl_IncrRefCount(callable);
+      callback_var->interp = interp;
+      callback_var->obj = callable;
+      pool_setloadcallback($self, loadcallback, callback_var);
+    }
+  }
+#else
+#warning loadcallback not implemented for this language
 #endif
 
-  void free() {
-    Pool_set_loadcallback($self, 0);
-    pool_free($self);
+  ~Pool() {
+    Pool *pool = $self;
+    Id repoid;
+    Repo *repo;
+    FOR_REPOS(repoid, repo)
+      appdata_clr_helper(&repo->appdata);
+    Pool_clr_loadcallback(pool);
+    appdata_clr_helper(&pool->appdata);
+    pool_free(pool);
+  }
+  disown_helper free() {
+    Pool *pool = $self;
+    Id repoid;
+    Repo *repo;
+    FOR_REPOS(repoid, repo)
+      appdata_clr_helper(&repo->appdata);
+    Pool_clr_loadcallback(pool);
+    appdata_clr_helper(&pool->appdata);
+    pool_free(pool);
+    return 0;
   }
+  disown_helper disown() {
+    return 0;
+  }
+  AppObjectPtr appdata;
+  %{
+  SWIGINTERN void Pool_appdata_set(Pool *pool, AppObjectPtr appdata) {
+    appdata_set_helper(&pool->appdata, appdata);
+  }
+  SWIGINTERN AppObjectPtr Pool_appdata_get(Pool *pool) {
+    return appdata_get_helper(pool->appdata);
+  }
+  %}
+  void appdata_disown() {
+    appdata_disown_helper($self->appdata);
+  }
+
   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);
   }
+#if defined(ENABLE_COMPLEX_DEPS) && (defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) || defined(ENABLE_RPMDB) || defined(ENABLE_RPMPKG))
+  %newobject Dep;
+  Dep *parserpmrichdep(const char *str) {
+    Id id = pool_parserpmrichdep($self, str);
+    return new_Dep($self, id);
+  }
+#endif
   const char *id2str(Id id) {
     return pool_id2str($self, id);
   }
@@ -1196,7 +1783,11 @@ typedef struct {
   }
 
   %newobject Dataiterator;
-  Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
+  Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
+    return new_Dataiterator($self, 0, 0, key, match, flags);
+  }
+  %newobject Dataiterator_solvid;
+  Dataiterator *Dataiterator_solvid(Id p, Id key, const char *match = 0, int flags = 0) {
     return new_Dataiterator($self, 0, p, key, match, flags);
   }
   const char *solvid2str(Id solvid) {
@@ -1215,6 +1806,7 @@ typedef struct {
     pool_createwhatprovides($self);
   }
 
+  %newobject id2solvable;
   XSolvable *id2solvable(Id id) {
     return new_XSolvable($self, id);
   }
@@ -1249,13 +1841,17 @@ typedef struct {
   }
 
   Repo *installed;
+  const char * const errstr;
   %{
   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
     pool_set_installed(pool, installed);
   }
-  Repo *Pool_installed_get(Pool *pool) {
+  SWIGINTERN Repo *Pool_installed_get(Pool *pool) {
     return pool->installed;
   }
+  SWIGINTERN const char *Pool_errstr_get(Pool *pool) {
+    return pool_errstr(pool);
+  }
   %}
 
   Queue matchprovidingids(const char *match, int flags) {
@@ -1279,6 +1875,7 @@ typedef struct {
     return q;
   }
 
+  %newobject Job;
   Job *Job(int how, Id what) {
     return new_Job($self, how, what);
   }
@@ -1299,6 +1896,25 @@ typedef struct {
     return pool_queuetowhatprovides($self, &q);
   }
 
+  void set_namespaceproviders(DepId ns, DepId evr, bool value=1) {
+    Id dep = pool_rel2id($self, ns, evr, REL_NAMESPACE, 1);
+    pool_set_whatprovides($self, dep, value ? 2 : 1);
+  }
+
+  void flush_namespaceproviders(DepId ns, DepId evr) {
+    pool_flush_namespaceproviders($self, ns, evr);
+  }
+
+
+  %typemap(out) Queue whatmatchesdep Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
+  %newobject whatmatchesdep;
+  Queue whatmatchesdep(Id keyname, DepId dep, Id marker = -1) {
+    Queue q;
+    queue_init(&q);
+    pool_whatmatchesdep($self, keyname, dep, &q, marker);
+    return q;
+  }
+
 #ifdef SWIGRUBY
   %rename("isknownarch?") isknownarch;
 #endif
@@ -1308,7 +1924,7 @@ typedef struct {
       return 0;
     if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
       return 1;
-    if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
+    if (pool->id2arch && pool_arch2score(pool, id) == 0)
       return 0;
     return 1;
   }
@@ -1335,6 +1951,20 @@ typedef struct {
     return sel;
   }
 
+  %newobject matchdeps;
+  Selection *matchdeps(const char *name, int flags, Id keyname, Id marker = -1) {
+    Selection *sel = new_Selection($self);
+    sel->flags = selection_make_matchdeps($self, &sel->q, name, flags, keyname, marker);
+    return sel;
+  }
+
+  %newobject matchdepid;
+  Selection *matchdepid(DepId dep, int flags, Id keyname, Id marker = -1) {
+    Selection *sel = new_Selection($self);
+    sel->flags = selection_make_matchdepid($self, &sel->q, dep, flags, keyname, marker);
+    return sel;
+  }
+
   void setpooljobs_helper(Queue jobs) {
     queue_free(&$self->pooljobs);
     queue_init_clone(&$self->pooljobs, &jobs);
@@ -1393,6 +2023,7 @@ rb_eval_string(
 #endif
 
   void free(bool reuseids = 0) {
+    appdata_clr_helper(&$self->appdata);
     repo_free($self, reuseids);
   }
   void empty(bool reuseids = 0) {
@@ -1404,6 +2035,17 @@ rb_eval_string(
   bool isempty() {
     return !$self->nsolvables;
   }
+
+  AppObjectPtr appdata;
+  %{
+  SWIGINTERN void Repo_appdata_set(Repo *repo, AppObjectPtr appdata) {
+    appdata_set_helper(&repo->appdata, appdata);
+  }
+  SWIGINTERN AppObjectPtr Repo_appdata_get(Repo *repo) {
+    return appdata_get_helper(repo->appdata);
+  }
+  %}
+
   bool add_solv(const char *name, int flags = 0) {
     FILE *fp = fopen(name, "r");
     int r;
@@ -1417,6 +2059,7 @@ rb_eval_string(
     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);
@@ -1429,16 +2072,28 @@ rb_eval_string(
   bool add_rpmdb_reffp(FILE *reffp, int flags = 0) {
     return repo_add_rpmdb_reffp($self, reffp, flags) == 0;
   }
-  Id add_rpm(const char *name, int flags = 0) {
-    return repo_add_rpm($self, name, flags);
+#endif
+#ifdef ENABLE_RPMPKG
+  %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_RPMDB_PUBKEYS
+#ifdef ENABLE_PUBKEY
+#ifdef ENABLE_RPMDB
   bool add_rpmdb_pubkeys(int flags = 0) {
     return repo_add_rpmdb_pubkeys($self, flags) == 0;
   }
-  Id add_pubkey(const char *key, int flags = 0) {
-    return repo_add_pubkey($self, key, flags);
+#endif
+  %newobject add_pubkey;
+  XSolvable *add_pubkey(const char *keyfile, int flags = 0) {
+    return new_XSolvable($self->pool, repo_add_pubkey($self, keyfile, flags));
+  }
+  bool add_keyring(FILE *fp, int flags = 0) {
+    return repo_add_keyring($self, fp, flags);
+  }
+  bool add_keydir(const char *keydir, const char *suffix, int flags = 0) {
+    return repo_add_keydir($self, keydir, suffix, flags);
   }
 #endif
 #ifdef ENABLE_RPMMD
@@ -1462,8 +2117,9 @@ rb_eval_string(
   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
@@ -1492,8 +2148,14 @@ rb_eval_string(
   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
+#ifdef SUSE
+  bool add_autopattern(int flags = 0) {
+    return repo_add_autopattern($self, flags) == 0;
   }
 #endif
   void internalize() {
@@ -1502,7 +2164,7 @@ rb_eval_string(
   bool write(FILE *fp) {
     return repo_write($self, fp) == 0;
   }
-  # HACK, remove if no longer needed!
+  /* HACK, remove if no longer needed! */
   bool write_first_repodata(FILE *fp) {
     int oldnrepodata = $self->nrepodata;
     int res;
@@ -1513,8 +2175,12 @@ rb_eval_string(
   }
 
   %newobject Dataiterator;
-  Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
-    return new_Dataiterator($self->pool, $self, p, key, match, flags);
+  Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
+    return new_Dataiterator($self->pool, $self, 0, key, match, flags);
+  }
+  %newobject Dataiterator_meta;
+  Dataiterator *Dataiterator_meta(Id key, const char *match = 0, int flags = 0) {
+    return new_Dataiterator($self->pool, $self, SOLVID_META, key, match, flags);
   }
 
   Id const id;
@@ -1546,6 +2212,7 @@ rb_eval_string(
     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);
@@ -1557,7 +2224,7 @@ rb_eval_string(
       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;
@@ -1569,6 +2236,7 @@ rb_eval_string(
         return 0;
     return 1;
   }
+  %newobject first_repodata;
   XRepodata *first_repodata() {
     Repodata *data;
     int i;
@@ -1595,13 +2263,59 @@ rb_eval_string(
     return sel;
   }
 
+#ifdef ENABLE_PUBKEY
+  %newobject find_pubkey;
+  XSolvable *find_pubkey(const char *keyid) {
+    return new_XSolvable($self->pool, repo_find_pubkey($self, keyid));
+  }
+#endif
+
+  Repo *createshadow(const char *name) {
+    Repo *repo = repo_create($self->pool, name);
+    if ($self->idarraysize) {
+      repo_reserve_ids(repo, 0, $self->idarraysize);
+      memcpy(repo->idarraydata, $self->idarraydata, sizeof(Id) * $self->idarraysize);
+      repo->idarraysize = $self->idarraysize;
+    }
+    repo->start = $self->start;
+    repo->end = $self->end;
+    repo->nsolvables = $self->nsolvables;
+    return repo;
+  }
+
+  void moveshadow(Queue q) {
+    Pool *pool = $self->pool;
+    int i;
+    for (i = 0; i < q.count; i++) {
+      Solvable *s;
+      Id p = q.elements[i];
+      if (p < $self->start || p >= $self->end)
+        continue;
+      s = pool->solvables + p;
+      if ($self->idarraysize != s->repo->idarraysize)
+        continue;
+      s->repo = $self;
+    }
+  }
+
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(Repo *repo) {
     return $self == repo;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(Repo *repo) {
     return $self != repo;
   }
-#if defined(SWIGPERL)
+#if defined(SWIGPYTHON)
+  int __hash__() {
+    return $self->repoid;
+  }
+#endif
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   %newobject __str__;
@@ -1612,6 +2326,9 @@ rb_eval_string(
     sprintf(buf, "Repo#%d", $self->repoid);
     return solv_strdup(buf);
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     char buf[20];
@@ -1635,6 +2352,7 @@ rb_eval_string(
   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));
@@ -1645,15 +2363,13 @@ rb_eval_string(
     dataiterator_free($self);
     solv_free($self);
   }
-#if defined(SWIGPYTHON)
-  %newobject __iter__;
-  Dataiterator *__iter__() {
-    Dataiterator *ndi;
-    ndi = solv_calloc(1, sizeof(*ndi));
-    dataiterator_init_clone(ndi, $self);
-    return ndi;
-  }
+#if defined(SWIGPYTHON)
+  %pythoncode {
+    def __iter__(self): return self
+  }
+#ifndef PYTHON3
   %rename("next") __next__();
+#endif
   %exception __next__ {
     $action
     if (!result) {
@@ -1662,11 +2378,9 @@ rb_eval_string(
     }
   }
 #endif
-
 #ifdef SWIGPERL
   perliter(solv::Dataiterator)
 #endif
-
   %newobject __next__;
   Datamatch *__next__() {
     Dataiterator *ndi;
@@ -1764,6 +2478,26 @@ rb_eval_string(
     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 = 0, int flags = 0) {
+    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 {
@@ -1773,38 +2507,67 @@ rb_eval_string(
   }
   %newobject solvable;
   XSolvable * const solvable;
+  Id const key_id;
+  const char * const key_idstr;
+  Id const type_id;
+  const char * const type_idstr;
+  Id const id;
+  const char * const idstr;
+  const char * const str;
+  BinaryBlob const binary;
+  unsigned long long const num;
+  unsigned int const num2;
   %{
   SWIGINTERN XSolvable *Datamatch_solvable_get(Dataiterator *di) {
     return new_XSolvable(di->pool, di->solvid);
   }
-  %}
-  Id key_id() {
-    return $self->key->name;
+  SWIGINTERN Id Datamatch_key_id_get(Dataiterator *di) {
+    return di->key->name;
   }
-  const char *key_idstr() {
-    return pool_id2str($self->pool, $self->key->name);
+  SWIGINTERN const char *Datamatch_key_idstr_get(Dataiterator *di) {
+    return pool_id2str(di->pool, di->key->name);
   }
-  Id type_id() {
-    return $self->key->type;
+  SWIGINTERN Id Datamatch_type_id_get(Dataiterator *di) {
+    return di->key->type;
   }
-  const char *type_idstr() {
-    return pool_id2str($self->pool, $self->key->type);
+  SWIGINTERN const char *Datamatch_type_idstr_get(Dataiterator *di) {
+    return pool_id2str(di->pool, di->key->type);
   }
-  Id id() {
-     return $self->kv.id;
+  SWIGINTERN Id Datamatch_id_get(Dataiterator *di) {
+    return di->kv.id;
   }
-  const char *idstr() {
-     return pool_id2str($self->pool, $self->kv.id);
+  SWIGINTERN const char *Datamatch_idstr_get(Dataiterator *di) {
+   if (di->data && (di->key->type == REPOKEY_TYPE_DIR || di->key->type == REPOKEY_TYPE_DIRSTRARRAY || di->key->type == REPOKEY_TYPE_DIRNUMNUMARRAY))
+      return repodata_dir2str(di->data,  di->kv.id, 0);
+    if (di->data && di->data->localpool)
+      return stringpool_id2str(&di->data->spool, di->kv.id);
+    return pool_id2str(di->pool, di->kv.id);
   }
-  const char *str() {
-     return $self->kv.str;
+  SWIGINTERN const char * const Datamatch_str_get(Dataiterator *di) {
+    return di->kv.str;
   }
-  int num() {
-     return $self->kv.num;
+  SWIGINTERN BinaryBlob Datamatch_binary_get(Dataiterator *di) {
+    BinaryBlob bl;
+    bl.data = 0;
+    bl.len = 0;
+    if (di->key->type == REPOKEY_TYPE_BINARY)
+      {
+        bl.data = di->kv.str;
+        bl.len = di->kv.num;
+      }
+    else if ((bl.len = solv_chksum_len(di->key->type)) != 0)
+      bl.data = di->kv.str;
+    return bl;
   }
-  int num2() {
-     return $self->kv.num2;
+  SWIGINTERN unsigned long long Datamatch_num_get(Dataiterator *di) {
+   if (di->key->type == REPOKEY_TYPE_NUM)
+     return SOLV_KV_NUM64(&di->kv);
+   return di->kv.num;
   }
+  SWIGINTERN unsigned int Datamatch_num2_get(Dataiterator *di) {
+    return di->kv.num2;
+  }
+  %}
   %newobject pos;
   Datapos *pos() {
     Pool *pool = $self->pool;
@@ -1825,19 +2588,20 @@ rb_eval_string(
     pool->pos = oldpos;
     return pos;
   }
-  void setpos() {
-    dataiterator_setpos($self);
-  }
-  void setpos_parent() {
-    dataiterator_setpos_parent($self);
-  }
 #if defined(SWIGPERL)
-  %rename("str") __str__;
+  /* cannot use str here because swig reports a bogus conflict... */
+  %rename("stringify") __str__;
+  %perlcode {
+    *solv::Datamatch::str = *solvc::Datamatch_stringify;
+  }
+#endif
+#if defined(SWIGTCL)
+  %rename("stringify") __str__;
 #endif
   const char *__str__() {
-    if (!repodata_stringify($self->pool, $self->data, $self->key, &$self->kv, $self->flags))
-      return "";
-    return $self->kv.str;
+    KeyValue kv = $self->kv;
+    const char *str = repodata_stringify($self->pool, $self->data, $self->key, &kv, SEARCH_FILES | SEARCH_CHECKSUMS);
+    return str ? str : "";
   }
 }
 
@@ -1849,14 +2613,12 @@ rb_eval_string(
     return s;
   }
 #if defined(SWIGPYTHON)
-  %newobject __iter__;
-  Pool_solvable_iterator *__iter__() {
-    Pool_solvable_iterator *s;
-    s = solv_calloc(1, sizeof(*s));
-    *s = *$self;
-    return s;
+  %pythoncode {
+    def __iter__(self): return self
   }
+#ifndef PYTHON3
   %rename("next") __next__();
+#endif
   %exception __next__ {
     $action
     if (!result) {
@@ -1865,7 +2627,6 @@ rb_eval_string(
     }
   }
 #endif
-
 #ifdef SWIGPERL
   perliter(solv::Pool_solvable_iterator)
 #endif
@@ -1907,14 +2668,12 @@ rb_eval_string(
     return s;
   }
 #if defined(SWIGPYTHON)
-  %newobject __iter__;
-  Pool_repo_iterator *__iter__() {
-    Pool_repo_iterator *s;
-    s = solv_calloc(1, sizeof(*s));
-    *s = *$self;
-    return s;
+  %pythoncode {
+    def __iter__(self): return self
   }
+#ifndef PYTHON3
   %rename("next") __next__();
+#endif
   %exception __next__ {
     $action
     if (!result) {
@@ -1923,7 +2682,9 @@ rb_eval_string(
     }
   }
 #endif
-  %newobject __next__;
+#ifdef SWIGPERL
+  perliter(solv::Pool_repo_iterator)
+#endif
   Repo *__next__() {
     Pool *pool = $self->pool;
     if ($self->id >= pool->nrepos)
@@ -1939,7 +2700,7 @@ rb_eval_string(
   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, 0 | 0));
     }
   }
 #endif
@@ -1962,14 +2723,12 @@ rb_eval_string(
     return s;
   }
 #if defined(SWIGPYTHON)
-  %newobject __iter__;
-  Repo_solvable_iterator *__iter__() {
-    Repo_solvable_iterator *s;
-    s = solv_calloc(1, sizeof(*s));
-    *s = *$self;
-    return s;
+  %pythoncode {
+    def __iter__(self): return self
   }
+#ifndef PYTHON3
   %rename("next") __next__();
+#endif
   %exception __next__ {
     $action
     if (!result) {
@@ -1978,6 +2737,9 @@ rb_eval_string(
     }
   }
 #endif
+#ifdef SWIGPERL
+  perliter(solv::Repo_solvable_iterator)
+#endif
   %newobject __next__;
   XSolvable *__next__() {
     Repo *repo = $self->repo;
@@ -2059,18 +2821,32 @@ rb_eval_string(
   const char *str() {
     return pool_dep2str($self->pool, $self->id);
   }
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(Dep *s) {
     return $self->pool == s->pool && $self->id == s->id;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(Dep *s) {
     return !Dep___eq__($self, s);
   }
-#if defined(SWIGPERL)
+#if defined(SWIGPYTHON)
+  int __hash__() {
+    return $self->id;
+  }
+#endif
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   const char *__str__() {
     return pool_dep2str($self->pool, $self->id);
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     char buf[20];
@@ -2114,14 +2890,6 @@ rb_eval_string(
     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;
   }
@@ -2131,22 +2899,17 @@ rb_eval_string(
     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_lookup_location($self->pool->solvables + $self->id, OUTPUT);
   }
+  const char *lookup_sourcepkg() {
+    return solvable_lookup_sourcepkg($self->pool->solvables + $self->id);
+  }
   %newobject Dataiterator;
-  Dataiterator *Dataiterator(Id key, const char *match, int flags) {
+  Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
     return new_Dataiterator($self->pool, 0, $self->id, key, match, flags);
   }
 #ifdef SWIGRUBY
@@ -2253,8 +3016,7 @@ rb_eval_string(
   /* 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;
+    marker = solv_depmarker(SOLVABLE_PROVIDES, marker);
     s->provides = repo_addid_dep(s->repo, s->provides, id, marker);
   }
   void add_obsoletes(DepId id) {
@@ -2267,8 +3029,7 @@ rb_eval_string(
   }
   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;
+    marker = solv_depmarker(SOLVABLE_REQUIRES, marker);
     s->requires = repo_addid_dep(s->repo, s->requires, id, marker);
   }
   void add_recommends(DepId id) {
@@ -2288,16 +3049,13 @@ rb_eval_string(
     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) {
-      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);
   }
 
@@ -2308,18 +3066,48 @@ rb_eval_string(
     return sel;
   }
 
+#ifdef SWIGRUBY
+  %rename("identical?") identical;
+#endif
+  bool identical(XSolvable *s2) {
+    return solvable_identical($self->pool->solvables + $self->id, s2->pool->solvables + s2->id);
+  }
+  int evrcmp(XSolvable *s2) {
+    return pool_evrcmp($self->pool, $self->pool->solvables[$self->id].evr, s2->pool->solvables[s2->id].evr, EVRCMP_COMPARE);
+  }
+#ifdef SWIGRUBY
+  %rename("matchesdep?") matchesdep;
+#endif
+  bool matchesdep(Id keyname, DepId id, Id marker = -1) {
+    return solvable_matchesdep($self->pool->solvables + $self->id, keyname, id, marker);
+  }
+
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(XSolvable *s) {
     return $self->pool == s->pool && $self->id == s->id;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(XSolvable *s) {
     return !XSolvable___eq__($self, s);
   }
-#if defined(SWIGPERL)
+#if defined(SWIGPYTHON)
+  int __hash__() {
+    return $self->id;
+  }
+#endif
+#if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
 #endif
   const char *__str__() {
     return pool_solvid2str($self->pool, $self->id);
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     char buf[20];
@@ -2369,8 +3157,8 @@ rb_eval_string(
   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;
@@ -2380,6 +3168,12 @@ rb_eval_string(
       queue_push(&q, i);
     return q;
   }
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("str") __str__;
+#endif
+  const char *__str__() {
+    return solver_problem2str($self->solv, $self->id);
+  }
 }
 
 %extend Solution {
@@ -2395,8 +3189,8 @@ rb_eval_string(
     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;
@@ -2481,8 +3275,8 @@ rb_eval_string(
       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;
@@ -2522,7 +3316,7 @@ rb_eval_string(
       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;
     }
@@ -2530,12 +3324,12 @@ rb_eval_string(
   %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 || $self->type == SOLVER_SOLUTION_POOLJOB)
       return new_Job($self->solv->pool, SOLVER_NOOP, 0);
     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);
+      return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_NOTBYUSER|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);
+      return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_NOTBYUSER|extraflags, $self->rp);
     if ($self->type == SOLVER_SOLUTION_ERASE)
       return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE|extraflags, $self->p);
     return 0;
@@ -2544,21 +3338,23 @@ rb_eval_string(
 
 %extend Solver {
   static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN;
-  static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
-  static const int SOLVER_RULE_RPM_NOT_INSTALLABLE = SOLVER_RULE_RPM_NOT_INSTALLABLE;
-  static const int SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP = SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP;
-  static const int SOLVER_RULE_RPM_PACKAGE_REQUIRES = SOLVER_RULE_RPM_PACKAGE_REQUIRES;
-  static const int SOLVER_RULE_RPM_SELF_CONFLICT = SOLVER_RULE_RPM_SELF_CONFLICT;
-  static const int SOLVER_RULE_RPM_PACKAGE_CONFLICT = SOLVER_RULE_RPM_PACKAGE_CONFLICT;
-  static const int SOLVER_RULE_RPM_SAME_NAME = SOLVER_RULE_RPM_SAME_NAME;
-  static const int SOLVER_RULE_RPM_PACKAGE_OBSOLETES = SOLVER_RULE_RPM_PACKAGE_OBSOLETES;
-  static const int SOLVER_RULE_RPM_IMPLICIT_OBSOLETES = SOLVER_RULE_RPM_IMPLICIT_OBSOLETES;
-  static const int SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES = SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES;
+  static const int SOLVER_RULE_PKG = SOLVER_RULE_PKG;
+  static const int SOLVER_RULE_PKG_NOT_INSTALLABLE = SOLVER_RULE_PKG_NOT_INSTALLABLE;
+  static const int SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP = SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP;
+  static const int SOLVER_RULE_PKG_REQUIRES = SOLVER_RULE_PKG_REQUIRES;
+  static const int SOLVER_RULE_PKG_SELF_CONFLICT = SOLVER_RULE_PKG_SELF_CONFLICT;
+  static const int SOLVER_RULE_PKG_CONFLICTS = SOLVER_RULE_PKG_CONFLICTS;
+  static const int SOLVER_RULE_PKG_SAME_NAME = SOLVER_RULE_PKG_SAME_NAME;
+  static const int SOLVER_RULE_PKG_OBSOLETES = SOLVER_RULE_PKG_OBSOLETES;
+  static const int SOLVER_RULE_PKG_IMPLICIT_OBSOLETES = SOLVER_RULE_PKG_IMPLICIT_OBSOLETES;
+  static const int SOLVER_RULE_PKG_INSTALLED_OBSOLETES = SOLVER_RULE_PKG_INSTALLED_OBSOLETES;
   static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE;
   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;
@@ -2591,6 +3387,35 @@ rb_eval_string(
   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_FLAG_DUP_ALLOW_DOWNGRADE = SOLVER_FLAG_DUP_ALLOW_DOWNGRADE;
+  static const int SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE = SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE;
+  static const int SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE = SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE;
+  static const int SOLVER_FLAG_DUP_ALLOW_NAMECHANGE = SOLVER_FLAG_DUP_ALLOW_NAMECHANGE;
+  static const int SOLVER_FLAG_KEEP_ORPHANS = SOLVER_FLAG_KEEP_ORPHANS;
+  static const int SOLVER_FLAG_BREAK_ORPHANS = SOLVER_FLAG_BREAK_ORPHANS;
+  static const int SOLVER_FLAG_FOCUS_INSTALLED = SOLVER_FLAG_FOCUS_INSTALLED;
+  static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES;
+  static const int SOLVER_FLAG_NEED_UPDATEPROVIDE = SOLVER_FLAG_NEED_UPDATEPROVIDE;
+  static const int SOLVER_FLAG_FOCUS_BEST = SOLVER_FLAG_FOCUS_BEST;
+  static const int SOLVER_FLAG_STRONG_RECOMMENDS = SOLVER_FLAG_STRONG_RECOMMENDS;
+  static const int SOLVER_FLAG_INSTALL_ALSO_UPDATES = SOLVER_FLAG_INSTALL_ALSO_UPDATES;
+
+  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;
+
+  /* legacy */
+  static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
 
   ~Solver() {
     solver_free($self);
@@ -2644,10 +3469,140 @@ rb_eval_string(
       queue_push(&q, i);
     return q;
   }
+#if defined(SWIGTCL)
+  %typemap(out) Queue solve Queue2Array(Problem *, 1, new_Problem(arg1, id));
+  %newobject solve;
+  Queue solve(Queue solvejobs) {
+    Queue q;
+    int i, cnt;
+    queue_init(&q);
+    solver_solve($self, &solvejobs);
+    cnt = solver_problem_count($self);
+    for (i = 1; i <= cnt; i++)
+      queue_push(&q, i);
+    return q;
+  }
+#endif
+
   %newobject transaction;
   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;
+  }
+
+  %newobject describe_weakdep_decision_raw;
+  Queue describe_weakdep_decision_raw(XSolvable *s) {
+    Queue q;
+    queue_init(&q);
+    solver_describe_weakdep_decision($self, s->id, &q);
+    return q;
+  }
+#if defined(SWIGPYTHON)
+  %pythoncode {
+    def describe_weakdep_decision(self, s):
+      d = iter(self.describe_weakdep_decision_raw(s))
+      return [ (t, XSolvable(self.pool, sid), Dep(self.pool, id)) for t, sid, id in zip(d, d, d) ]
+  }
+#endif
+#if defined(SWIGPERL)
+  %perlcode {
+    sub solv::Solver::describe_weakdep_decision {
+      my ($self, $s) = @_;
+      my $pool = $self->{'pool'};
+      my @res;
+      my @d = $self->describe_weakdep_decision_raw($s);
+      push @res, [ splice(@d, 0, 3) ] while @d;
+      return map { [ $_->[0], solv::XSolvable->new($pool, $_->[1]), solv::Dep->new($pool, $_->[2]) ] } @res;
+    }
+  }
+#endif
+#if defined(SWIGRUBY)
+%init %{
+rb_eval_string(
+    "class Solv::Solver\n"
+    "  def describe_weakdep_decision(s)\n"
+    "    self.describe_weakdep_decision_raw(s).each_slice(3).map { |t, sid, id| [ t, Solv::XSolvable.new(self.pool, sid), Solv::Dep.new(self.pool, id)] }\n"
+    "  end\n"
+    "end\n"
+  );
+%}
+#endif
+
+  int alternatives_count() {
+    return solver_alternatives_count($self);
+  }
+
+  %newobject alternative;
+  Alternative *alternative(Id aid) {
+    Alternative *a = solv_calloc(1, sizeof(*a));
+    a->solv = $self;
+    queue_init(&a->choices);
+    a->type = solver_get_alternative($self, aid, &a->dep_id, &a->from_id, &a->chosen_id, &a->choices, &a->level);
+    if (!a->type) {
+      queue_free(&a->choices);
+      solv_free(a);
+      return 0;
+    }
+    if (a->type == SOLVER_ALTERNATIVE_TYPE_RULE) {
+      a->rid = a->dep_id;
+      a->dep_id = 0;
+    }
+    return a;
+  }
+
+  %typemap(out) Queue all_alternatives Queue2Array(Alternative *, 1, Solver_alternative(arg1, id));
+  %newobject all_alternatives;
+  Queue all_alternatives() {
+    Queue q;
+    int i, cnt;
+    queue_init(&q);
+    cnt = solver_alternatives_count($self);
+    for (i = 1; i <= cnt; i++)
+      queue_push(&q, i);
+    return q;
+  }
+
+  bool write_testcase(const char *dir) {
+    return testcase_write($self, dir, TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, 0, 0);
+  }
+
+  Queue raw_decisions(int filter=0) {
+    Queue q;
+    queue_init(&q);
+    solver_get_decisionqueue($self, &q);
+    if (filter) {
+      int i, j;
+      for (i = j = 0; i < q.count; i++)
+        if ((filter > 0 && q.elements[i] > 1) ||
+            (filter < 0 && q.elements[i] < 0))
+          q.elements[j++] = q.elements[i];
+      queue_truncate(&q, j);
+    }
+    return q;
+  }
+
+  %typemap(out) Queue get_recommended Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject get_recommended;
+  Queue get_recommended(bool noselected=0) {
+    Queue q;
+    queue_init(&q);
+    solver_get_recommendations($self, &q, NULL, noselected);
+    return q;
+  }
+  %typemap(out) Queue get_suggested Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+  %newobject get_suggested;
+  Queue get_suggested(bool noselected=0) {
+    Queue q;
+    queue_init(&q);
+    solver_get_recommendations($self, NULL, &q, noselected);
+    return q;
+  }
 }
 
 %extend Transaction {
@@ -2695,8 +3650,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);
@@ -2713,6 +3668,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() {
@@ -2724,6 +3680,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() {
@@ -2736,8 +3693,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);
@@ -2750,7 +3730,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);
   }
 }
@@ -2766,22 +3746,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 {
@@ -2793,9 +3775,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]));
@@ -2807,12 +3796,26 @@ rb_eval_string(
     return q;
   }
 
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(XRule *xr) {
     return $self->solv == xr->solv && $self->id == xr->id;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(XRule *xr) {
     return !XRule___eq__($self, xr);
   }
+#if defined(SWIGPYTHON)
+  int __hash__() {
+    return $self->id;
+  }
+#endif
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     char buf[20];
@@ -2822,18 +3825,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);
@@ -2841,9 +3848,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);
   }
 }
 
@@ -2877,6 +3887,9 @@ rb_eval_string(
     if (buf)
       repodata_set_bin_checksum(repo_id2repodata($self->repo, $self->id), solvid, keyname, solv_chksum_get_type(chksum), buf);
   }
+  void set_sourcepkg(Id solvid, const char *sourcepkg) {
+    repodata_set_sourcepkg(repo_id2repodata($self->repo, $self->id), solvid, sourcepkg);
+  }
   const char *lookup_str(Id solvid, Id keyname) {
     return repodata_lookup_str(repo_id2repodata($self->repo, $self->id), solvid, keyname);
   }
@@ -2896,11 +3909,25 @@ 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;
   }
   bool write(FILE *fp) {
     return repodata_write(repo_id2repodata($self->repo, $self->id), fp) == 0;
   }
+  Id str2dir(const char *dir, bool create=1) {
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
+    return repodata_str2dir(data, dir, create);
+  }
+  const char *dir2str(Id did, const char *suf = 0) {
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
+    return repodata_dir2str(data, did, suf);
+  }
+  void add_dirstr(Id solvid, Id keyname, Id dir, const char *str) {
+    Repodata *data = repo_id2repodata($self->repo, $self->id);
+    repodata_add_dirstr(data, solvid, keyname, dir, str);
+  }
   bool add_solv(FILE *fp, int flags = 0) {
     Repodata *data = repo_id2repodata($self->repo, $self->id);
     int r, oldstate = data->state;
@@ -2914,12 +3941,26 @@ rb_eval_string(
     Repodata *data = repo_id2repodata($self->repo, $self->id);
     repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
   }
+#if defined(SWIGTCL)
+  %rename("==") __eq__;
+#endif
   bool __eq__(XRepodata *xr) {
     return $self->repo == xr->repo && $self->id == xr->id;
   }
+#if defined(SWIGTCL)
+  %rename("!=") __ne__;
+#endif
   bool __ne__(XRepodata *xr) {
     return !XRepodata___eq__($self, xr);
   }
+#if defined(SWIGPYTHON)
+  int __hash__() {
+    return $self->id;
+  }
+#endif
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("repr") __repr__;
+#endif
   %newobject __repr__;
   const char *__repr__() {
     char buf[20];
@@ -2928,3 +3969,103 @@ rb_eval_string(
   }
 }
 
+#ifdef ENABLE_PUBKEY
+%extend Solvsig {
+  Solvsig(FILE *fp) {
+    return solvsig_create(fp);
+  }
+  ~Solvsig() {
+    solvsig_free($self);
+  }
+  %newobject Chksum;
+  Chksum *Chksum() {
+    return $self->htype ? (Chksum *)solv_chksum_create($self->htype) : 0;
+  }
+#ifdef ENABLE_PGPVRFY
+  %newobject verify;
+  XSolvable *verify(Repo *repo, Chksum *chksum) {
+    Id p = solvsig_verify($self, repo, chksum);
+    return new_XSolvable(repo->pool, p);
+  }
+#endif
+}
+#endif
+
+%extend Alternative {
+  static const int SOLVER_ALTERNATIVE_TYPE_RULE = SOLVER_ALTERNATIVE_TYPE_RULE;
+  static const int SOLVER_ALTERNATIVE_TYPE_RECOMMENDS = SOLVER_ALTERNATIVE_TYPE_RECOMMENDS;
+  static const int SOLVER_ALTERNATIVE_TYPE_SUGGESTS = SOLVER_ALTERNATIVE_TYPE_SUGGESTS;
+
+  ~Alternative() {
+    queue_free(&$self->choices);
+    solv_free($self);
+  }
+  %newobject chosen;
+  XSolvable * const chosen;
+  %newobject rule;
+  XRule * const rule;
+  %newobject depsolvable;
+  XSolvable * const depsolvable;
+  %newobject dep;
+  Dep * const dep;
+  %{
+    SWIGINTERN XSolvable *Alternative_chosen_get(Alternative *a) {
+      return new_XSolvable(a->solv->pool, a->chosen_id);
+    }
+    SWIGINTERN XRule *Alternative_rule_get(Alternative *a) {
+      return new_XRule(a->solv, a->rid);
+    }
+    SWIGINTERN XSolvable *Alternative_depsolvable_get(Alternative *a) {
+      return new_XSolvable(a->solv->pool, a->from_id);
+    }
+    SWIGINTERN Dep *Alternative_dep_get(Alternative *a) {
+      return new_Dep(a->solv->pool, a->dep_id);
+    }
+  %}
+
+  Queue choices_raw() {
+    Queue r;
+    queue_init_clone(&r, &$self->choices);
+    return r;
+  }
+
+  %typemap(out) Queue choices Queue2Array(XSolvable *, 1, new_XSolvable(arg1->solv->pool, id));
+  Queue choices() {
+    int i;
+    Queue r;
+    queue_init_clone(&r, &$self->choices);
+    for (i = 0; i < r.count; i++)
+      if (r.elements[i] < 0)
+        r.elements[i] = -r.elements[i];
+    return r;
+  }
+
+#if defined(SWIGPERL) || defined(SWIGTCL)
+  %rename("str") __str__;
+#endif
+  const char *__str__() {
+    return solver_alternative2str($self->solv, $self->type, $self->type == SOLVER_ALTERNATIVE_TYPE_RULE ? $self->rid : $self->dep_id, $self->from_id);
+  }
+}
+
+#if defined(SWIGTCL)
+%init %{
+  Tcl_Eval(interp,
+"proc solv::iter {varname iter body} {\n"\
+"  while 1 {\n"\
+"    set value [$iter __next__]\n"\
+"    if {$value eq \"NULL\"} { break }\n"\
+"    uplevel [list set $varname $value]\n"\
+"    set code [catch {uplevel $body} result]\n"\
+"    switch -exact -- $code {\n"\
+"      0 {}\n"\
+"      3 { return }\n"\
+"      4 {}\n"\
+"      default { return -code $code $result }\n"\
+"    }\n"\
+"  }\n"\
+"}\n"
+  );
+%}
+#endif
+